diff options
284 files changed, 5919 insertions, 2191 deletions
diff --git a/Android.mk b/Android.mk index fc9c319a996a..ae5d67ed2de3 100644 --- a/Android.mk +++ b/Android.mk @@ -244,6 +244,8 @@ LOCAL_SRC_FILES += \ core/java/android/service/notification/IConditionListener.aidl \ core/java/android/service/notification/IConditionProvider.aidl \ core/java/android/service/vr/IVrListener.aidl \ + core/java/android/service/vr/IVrManager.aidl \ + core/java/android/service/vr/IVrStateCallbacks.aidl \ core/java/android/print/ILayoutResultCallback.aidl \ core/java/android/print/IPrinterDiscoveryObserver.aidl \ core/java/android/print/IPrintDocumentAdapter.aidl \ diff --git a/api/current.txt b/api/current.txt index 57b1177954b1..f346e0b6f054 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4979,7 +4979,7 @@ package android.app { field public int ledARGB; field public int ledOffMS; field public int ledOnMS; - field public int number; + field public deprecated int number; field public int priority; field public android.app.Notification publicVersion; field public android.net.Uri sound; @@ -5074,7 +5074,7 @@ package android.app { method public android.app.Notification.Builder setChronometerCountsDown(boolean); method public android.app.Notification.Builder setColor(int); method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews); - method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence); + method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence); method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent); method public android.app.Notification.Builder setContentText(java.lang.CharSequence); method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence); @@ -5091,7 +5091,7 @@ package android.app { method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon); method public android.app.Notification.Builder setLights(int, int, int); method public android.app.Notification.Builder setLocalOnly(boolean); - method public android.app.Notification.Builder setNumber(int); + method public deprecated android.app.Notification.Builder setNumber(int); method public android.app.Notification.Builder setOngoing(boolean); method public android.app.Notification.Builder setOnlyAlertOnce(boolean); method public android.app.Notification.Builder setPriority(int); @@ -5925,7 +5925,7 @@ package android.app.admin { method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName); method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); - method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String); + method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException; method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; @@ -7889,6 +7889,7 @@ package android.content { method public static boolean isSyncPending(android.accounts.Account, java.lang.String); method public void notifyChange(android.net.Uri, android.database.ContentObserver); method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean); + method public void notifyChange(android.net.Uri, android.database.ContentObserver, int); method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException; method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; @@ -7919,6 +7920,8 @@ package android.content { field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir"; field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item"; field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE"; + field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2 + field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1 field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource"; field public static final java.lang.String SCHEME_CONTENT = "content"; field public static final java.lang.String SCHEME_FILE = "file"; @@ -20077,7 +20080,6 @@ package android.media { } public abstract class DrmInitData { - ctor public DrmInitData(); method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID); } @@ -46440,21 +46442,21 @@ package android.widget { ctor public DatePicker(android.content.Context, android.util.AttributeSet); ctor public DatePicker(android.content.Context, android.util.AttributeSet, int); ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int); - method public android.widget.CalendarView getCalendarView(); - method public boolean getCalendarViewShown(); + method public deprecated android.widget.CalendarView getCalendarView(); + method public deprecated boolean getCalendarViewShown(); method public int getDayOfMonth(); method public int getFirstDayOfWeek(); method public long getMaxDate(); method public long getMinDate(); method public int getMonth(); - method public boolean getSpinnersShown(); + method public deprecated boolean getSpinnersShown(); method public int getYear(); method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener); - method public void setCalendarViewShown(boolean); + method public deprecated void setCalendarViewShown(boolean); method public void setFirstDayOfWeek(int); method public void setMaxDate(long); method public void setMinDate(long); - method public void setSpinnersShown(boolean); + method public deprecated void setSpinnersShown(boolean); method public void updateDate(int, int, int); } diff --git a/api/system-current.txt b/api/system-current.txt index 32078dbcf041..e73287ea82f0 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5112,7 +5112,7 @@ package android.app { field public int ledARGB; field public int ledOffMS; field public int ledOnMS; - field public int number; + field public deprecated int number; field public int priority; field public android.app.Notification publicVersion; field public android.net.Uri sound; @@ -5207,7 +5207,7 @@ package android.app { method public android.app.Notification.Builder setChronometerCountsDown(boolean); method public android.app.Notification.Builder setColor(int); method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews); - method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence); + method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence); method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent); method public android.app.Notification.Builder setContentText(java.lang.CharSequence); method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence); @@ -5224,7 +5224,7 @@ package android.app { method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon); method public android.app.Notification.Builder setLights(int, int, int); method public android.app.Notification.Builder setLocalOnly(boolean); - method public android.app.Notification.Builder setNumber(int); + method public deprecated android.app.Notification.Builder setNumber(int); method public android.app.Notification.Builder setOngoing(boolean); method public android.app.Notification.Builder setOnlyAlertOnce(boolean); method public android.app.Notification.Builder setPriority(int); @@ -6074,7 +6074,7 @@ package android.app.admin { method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException; - method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String); + method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException; method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; @@ -8187,6 +8187,7 @@ package android.content { method public static boolean isSyncPending(android.accounts.Account, java.lang.String); method public void notifyChange(android.net.Uri, android.database.ContentObserver); method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean); + method public void notifyChange(android.net.Uri, android.database.ContentObserver, int); method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException; method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; @@ -8217,6 +8218,8 @@ package android.content { field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir"; field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item"; field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE"; + field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2 + field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1 field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource"; field public static final java.lang.String SCHEME_CONTENT = "content"; field public static final java.lang.String SCHEME_FILE = "file"; @@ -21556,7 +21559,6 @@ package android.media { } public abstract class DrmInitData { - ctor public DrmInitData(); method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID); } @@ -49537,21 +49539,21 @@ package android.widget { ctor public DatePicker(android.content.Context, android.util.AttributeSet); ctor public DatePicker(android.content.Context, android.util.AttributeSet, int); ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int); - method public android.widget.CalendarView getCalendarView(); - method public boolean getCalendarViewShown(); + method public deprecated android.widget.CalendarView getCalendarView(); + method public deprecated boolean getCalendarViewShown(); method public int getDayOfMonth(); method public int getFirstDayOfWeek(); method public long getMaxDate(); method public long getMinDate(); method public int getMonth(); - method public boolean getSpinnersShown(); + method public deprecated boolean getSpinnersShown(); method public int getYear(); method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener); - method public void setCalendarViewShown(boolean); + method public deprecated void setCalendarViewShown(boolean); method public void setFirstDayOfWeek(int); method public void setMaxDate(long); method public void setMinDate(long); - method public void setSpinnersShown(boolean); + method public deprecated void setSpinnersShown(boolean); method public void updateDate(int, int, int); } diff --git a/api/test-current.txt b/api/test-current.txt index 886eca70f285..a4408be22859 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4979,7 +4979,7 @@ package android.app { field public int ledARGB; field public int ledOffMS; field public int ledOnMS; - field public int number; + field public deprecated int number; field public int priority; field public android.app.Notification publicVersion; field public android.net.Uri sound; @@ -5074,7 +5074,7 @@ package android.app { method public android.app.Notification.Builder setChronometerCountsDown(boolean); method public android.app.Notification.Builder setColor(int); method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews); - method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence); + method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence); method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent); method public android.app.Notification.Builder setContentText(java.lang.CharSequence); method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence); @@ -5091,7 +5091,7 @@ package android.app { method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon); method public android.app.Notification.Builder setLights(int, int, int); method public android.app.Notification.Builder setLocalOnly(boolean); - method public android.app.Notification.Builder setNumber(int); + method public deprecated android.app.Notification.Builder setNumber(int); method public android.app.Notification.Builder setOngoing(boolean); method public android.app.Notification.Builder setOnlyAlertOnce(boolean); method public android.app.Notification.Builder setPriority(int); @@ -5929,7 +5929,7 @@ package android.app.admin { method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName); method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); - method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String); + method public void setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException, java.lang.UnsupportedOperationException; method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException; @@ -7894,6 +7894,7 @@ package android.content { method public static boolean isSyncPending(android.accounts.Account, java.lang.String); method public void notifyChange(android.net.Uri, android.database.ContentObserver); method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean); + method public void notifyChange(android.net.Uri, android.database.ContentObserver, int); method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException; method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException; @@ -7924,6 +7925,8 @@ package android.content { field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir"; field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item"; field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE"; + field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2 + field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1 field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource"; field public static final java.lang.String SCHEME_CONTENT = "content"; field public static final java.lang.String SCHEME_FILE = "file"; @@ -20142,7 +20145,6 @@ package android.media { } public abstract class DrmInitData { - ctor public DrmInitData(); method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID); } @@ -46514,21 +46516,21 @@ package android.widget { ctor public DatePicker(android.content.Context, android.util.AttributeSet); ctor public DatePicker(android.content.Context, android.util.AttributeSet, int); ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int); - method public android.widget.CalendarView getCalendarView(); - method public boolean getCalendarViewShown(); + method public deprecated android.widget.CalendarView getCalendarView(); + method public deprecated boolean getCalendarViewShown(); method public int getDayOfMonth(); method public int getFirstDayOfWeek(); method public long getMaxDate(); method public long getMinDate(); method public int getMonth(); - method public boolean getSpinnersShown(); + method public deprecated boolean getSpinnersShown(); method public int getYear(); method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener); - method public void setCalendarViewShown(boolean); + method public deprecated void setCalendarViewShown(boolean); method public void setFirstDayOfWeek(int); method public void setMaxDate(long); method public void setMinDate(long); - method public void setSpinnersShown(boolean); + method public deprecated void setSpinnersShown(boolean); method public void updateDate(int, int, int); } diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index c745644adf13..2a04c39f2c5a 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -1033,7 +1033,8 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * false if it is not. */ public void setUserVisibleHint(boolean isVisibleToUser) { - if (!mUserVisibleHint && isVisibleToUser && mState < STARTED && isAdded()) { + if (!mUserVisibleHint && isVisibleToUser && mState < STARTED + && mFragmentManager != null && isAdded()) { mFragmentManager.performPendingDeferredStart(this); } mUserVisibleHint = isVisibleToUser; diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 25194d416d71..2e4a8c6d82e9 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -174,6 +174,9 @@ public class Notification implements Parcelable * <li>Notification of an ongoing countdown timer should be stamped with the timer's end time. * </ul> * + * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is not shown + * anymore by default and must be opted into by using + * {@link android.app.Notification.Builder#setShowWhen(boolean)} */ public long when; @@ -206,6 +209,8 @@ public class Notification implements Parcelable * {@link Notification.Builder} has displayed the number in the expanded notification view. * * If the number is 0 or negative, it is never shown. + * + * @deprecated this number is not shown anymore */ public int number; @@ -2158,7 +2163,9 @@ public class Notification implements Parcelable if (toAdopt == null) { mN = new Notification(); - mN.extras.putBoolean(EXTRA_SHOW_WHEN, true); + if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { + mN.extras.putBoolean(EXTRA_SHOW_WHEN, true); + } mN.priority = PRIORITY_DEFAULT; mN.visibility = VISIBILITY_PRIVATE; } else { @@ -2208,8 +2215,10 @@ public class Notification implements Parcelable /** * Add a timestamp pertaining to the notification (usually the time the event occurred). - * It will be shown in the notification content view by default; use - * {@link #setShowWhen(boolean) setShowWhen} to control this. + * + * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this time is not + * shown anymore by default and must be opted into by using + * {@link android.app.Notification.Builder#setShowWhen(boolean)} * * @see Notification#when */ @@ -2221,6 +2230,8 @@ public class Notification implements Parcelable /** * Control whether the timestamp set with {@link #setWhen(long) setWhen} is shown * in the content view. + * For apps targeting {@link android.os.Build.VERSION_CODES#N} and above, this defaults to + * {@code false}. For earlier apps, the default is {@code true}. */ public Builder setShowWhen(boolean show) { mN.extras.putBoolean(EXTRA_SHOW_WHEN, show); @@ -2329,9 +2340,22 @@ public class Notification implements Parcelable } /** - * Set the third line of text in the platform notification template. - * Don't use if you're also using {@link #setProgress(int, int, boolean)}; they occupy the - * same location in the standard template. + * This provides some additional information that is displayed in the notification. No + * guarantees are given where exactly it is displayed. + * + * <p>This information should only be provided if it provides an essential + * benefit to the understanding of the notification. The more text you provide the + * less readable it becomes. For example, an email client should only provide the account + * name here if more than one email account has been added.</p> + * + * <p>As of {@link android.os.Build.VERSION_CODES#N} this information is displayed in the + * notification header area. + * + * On Android versions before {@link android.os.Build.VERSION_CODES#N} + * this will be shown in the third line of text in the platform notification template. + * You should not be using {@link #setProgress(int, int, boolean)} at the + * same time on those versions; they occupy the same place. + * </p> */ public Builder setSubText(CharSequence text) { mN.extras.putCharSequence(EXTRA_SUB_TEXT, safeCharSequence(text)); @@ -2370,6 +2394,8 @@ public class Notification implements Parcelable * Set the large number at the right-hand side of the notification. This is * equivalent to setContentInfo, although it might show the number in a different * font size for readability. + * + * @deprecated this number is not shown anywhere anymore */ public Builder setNumber(int number) { mN.number = number; @@ -2381,6 +2407,10 @@ public class Notification implements Parcelable * * The platform template will draw this on the last line of the notification, at the far * right (to the right of a smallIcon if it has been placed there). + * + * @deprecated use {@link #setSubText(CharSequence)} instead to set a text in the header. + * For legacy apps targeting a version below {@link android.os.Build.VERSION_CODES#N} this + * field will still show up, but the subtext will take precedence. */ public Builder setContentInfo(CharSequence info) { mN.extras.putCharSequence(EXTRA_INFO_TEXT, safeCharSequence(info)); @@ -3034,10 +3064,8 @@ public class Notification implements Parcelable contentView.setBoolean(R.id.notification_header, "setExpanded", false); contentView.setTextViewText(R.id.app_name_text, null); contentView.setViewVisibility(R.id.chronometer, View.GONE); - contentView.setViewVisibility(R.id.header_sub_text, View.GONE); - contentView.setViewVisibility(R.id.header_content_info, View.GONE); - contentView.setViewVisibility(R.id.sub_text_divider, View.GONE); - contentView.setViewVisibility(R.id.content_info_divider, View.GONE); + contentView.setViewVisibility(R.id.header_text, View.GONE); + contentView.setViewVisibility(R.id.header_text_divider, View.GONE); contentView.setViewVisibility(R.id.time_divider, View.GONE); contentView.setImageViewIcon(R.id.profile_badge, null); contentView.setViewVisibility(R.id.profile_badge, View.GONE); @@ -3137,39 +3165,12 @@ public class Notification implements Parcelable private void bindNotificationHeader(RemoteViews contentView) { bindSmallIcon(contentView); bindHeaderAppName(contentView); - bindHeaderSubText(contentView); - bindContentInfo(contentView); + bindHeaderText(contentView); bindHeaderChronometerAndTime(contentView); bindExpandButton(contentView); bindProfileBadge(contentView); } - private void bindContentInfo(RemoteViews contentView) { - boolean visible = false; - if (mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) { - contentView.setTextViewText(R.id.header_content_info, - processLegacyText(mN.extras.getCharSequence(EXTRA_INFO_TEXT))); - contentView.setViewVisibility(R.id.header_content_info, View.VISIBLE); - visible = true; - } else if (mN.number > 0) { - final int tooBig = mContext.getResources().getInteger( - R.integer.status_bar_notification_info_maxnum); - if (mN.number > tooBig) { - contentView.setTextViewText(R.id.header_content_info, processLegacyText( - mContext.getResources().getString( - R.string.status_bar_notification_info_overflow))); - } else { - contentView.setTextViewText(R.id.header_content_info, - processLegacyText(String.valueOf(mN.number))); - } - contentView.setViewVisibility(R.id.header_content_info, View.VISIBLE); - visible = true; - } - if (visible) { - contentView.setViewVisibility(R.id.content_info_divider, View.VISIBLE); - } - } - private void bindExpandButton(RemoteViews contentView) { contentView.setDrawableParameters(R.id.expand_button, false, -1, resolveContrastColor(), PorterDuff.Mode.SRC_ATOP, -1); @@ -3194,17 +3195,22 @@ public class Notification implements Parcelable } } - private void bindHeaderSubText(RemoteViews contentView) { - CharSequence subText = mN.extras.getCharSequence(EXTRA_SUB_TEXT); - if (subText == null && mStyle != null && mStyle.mSummaryTextSet + private void bindHeaderText(RemoteViews contentView) { + CharSequence headerText = mN.extras.getCharSequence(EXTRA_SUB_TEXT); + if (headerText == null && mStyle != null && mStyle.mSummaryTextSet && mStyle.hasSummaryInHeader()) { - subText = mStyle.mSummaryText; + headerText = mStyle.mSummaryText; + } + if (headerText == null + && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N + && mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) { + headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT); } - if (subText != null) { + if (headerText != null) { // TODO: Remove the span entirely to only have the string with propper formating. - contentView.setTextViewText(R.id.header_sub_text, processLegacyText(subText)); - contentView.setViewVisibility(R.id.header_sub_text, View.VISIBLE); - contentView.setViewVisibility(R.id.sub_text_divider, View.VISIBLE); + contentView.setTextViewText(R.id.header_text, processLegacyText(headerText)); + contentView.setViewVisibility(R.id.header_text, View.VISIBLE); + contentView.setViewVisibility(R.id.header_text_divider, View.VISIBLE); } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 571e982a906c..f15b8fe27b42 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2977,17 +2977,21 @@ public class DevicePolicyManager { * @return {@code true} if the package is set as always-on VPN controller; {@code false} * otherwise. * @throws SecurityException if {@code admin} is not a device or a profile owner. + * @throws NameNotFoundException if {@code vpnPackage} is not installed. + * @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being + * set as always-on, or if always-on VPN is not available. */ - public boolean setAlwaysOnVpnPackage(@NonNull ComponentName admin, - @Nullable String vpnPackage) { + public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage) + throws NameNotFoundException, UnsupportedOperationException { if (mService != null) { try { - return mService.setAlwaysOnVpnPackage(admin, vpnPackage); + if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage)) { + throw new NameNotFoundException(vpnPackage); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - return false; } /** @@ -4156,6 +4160,10 @@ public class DevicePolicyManager { * The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method; * if not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set the configuration for + * the parent profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param target Component name of the agent to be enabled. @@ -4176,7 +4184,7 @@ public class DevicePolicyManager { @NonNull ComponentName target, PersistableBundle configuration) { if (mService != null) { try { - mService.setTrustAgentConfiguration(admin, target, configuration); + mService.setTrustAgentConfiguration(admin, target, configuration, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4187,6 +4195,10 @@ public class DevicePolicyManager { * Gets configuration for the given trust agent based on aggregating all calls to * {@link #setTrustAgentConfiguration(ComponentName, ComponentName, PersistableBundle)} for * all device admins. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to retrieve the configuration set + * on the parent profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. If null, * this function returns a list of configurations for all admins that declare @@ -4207,7 +4219,8 @@ public class DevicePolicyManager { @NonNull ComponentName agent, int userHandle) { if (mService != null) { try { - return mService.getTrustAgentConfiguration(admin, agent, userHandle); + return mService.getTrustAgentConfiguration(admin, agent, userHandle, + mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 6ee56aa91296..1fb2283a42a8 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -228,9 +228,9 @@ interface IDevicePolicyManager { boolean getBluetoothContactSharingDisabledForUser(int userId); void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent, - in PersistableBundle args); + in PersistableBundle args, boolean parent); List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin, - in ComponentName agent, int userId); + in ComponentName agent, int userId, boolean parent); boolean addCrossProfileWidgetProvider(in ComponentName admin, String packageName); boolean removeCrossProfileWidgetProvider(in ComponentName admin, String packageName); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index cd67b3ee8a3e..4db45670dd85 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -17,6 +17,7 @@ package android.content; import android.accounts.Account; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -60,6 +61,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -289,6 +292,31 @@ public abstract class ContentResolver { /** @hide */ public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff; + /** @hide */ + @IntDef(flag = true, + value = { + NOTIFY_SYNC_TO_NETWORK, + NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NotifyFlags {} + + /** + * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: attempt to sync the change + * to the network. + */ + public static final int NOTIFY_SYNC_TO_NETWORK = 1<<0; + + /** + * Flag for {@link #notifyChange(Uri, ContentObserver, int)}: if set, this notification + * will be skipped if it is being delivered to the root URI of a ContentObserver that is + * using "notify for descendants." The purpose of this is to allow the provide to send + * a general notification of "something under X" changed that observers of that specific + * URI can receive, while also sending a specific URI under X. It would use this flag + * when sending the former, so that observers of "X and descendants" only see the latter. + */ + public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1; + // Always log queries which take 500ms+; shorter queries are // sampled accordingly. private static final boolean ENABLE_CONTENT_SAMPLE = false; @@ -1676,7 +1704,7 @@ public abstract class ContentResolver { * The observer that originated the change will only receive the notification if it * has requested to receive self-change notifications by implementing * {@link ContentObserver#deliverSelfNotifications()} to return true. - * @param syncToNetwork If true, attempt to sync the change to the network. + * @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}. * @see #requestSync(android.accounts.Account, String, android.os.Bundle) */ public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer, @@ -1690,6 +1718,32 @@ public abstract class ContentResolver { } /** + * Notify registered observers that a row was updated. + * To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}. + * By default, CursorAdapter objects will get this notification. + * If syncToNetwork is true, this will attempt to schedule a local sync using the sync + * adapter that's registered for the authority of the provided uri. No account will be + * passed to the sync adapter, so all matching accounts will be synchronized. + * + * @param uri The uri of the content that was changed. + * @param observer The observer that originated the change, may be <code>null</null>. + * The observer that originated the change will only receive the notification if it + * has requested to receive self-change notifications by implementing + * {@link ContentObserver#deliverSelfNotifications()} to return true. + * @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}. + * @see #requestSync(android.accounts.Account, String, android.os.Bundle) + */ + public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer, + @NotifyFlags int flags) { + Preconditions.checkNotNull(uri, "uri"); + notifyChange( + ContentProvider.getUriWithoutUserId(uri), + observer, + flags, + ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId())); + } + + /** * Notify registered observers within the designated user(s) that a row was updated. * * @hide @@ -1699,7 +1753,24 @@ public abstract class ContentResolver { try { getContentService().notifyChange( uri, observer == null ? null : observer.getContentObserver(), - observer != null && observer.deliverSelfNotifications(), syncToNetwork, + observer != null && observer.deliverSelfNotifications(), + syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0, + userHandle); + } catch (RemoteException e) { + } + } + + /** + * Notify registered observers within the designated user(s) that a row was updated. + * + * @hide + */ + public void notifyChange(Uri uri, ContentObserver observer, @NotifyFlags int flags, + @UserIdInt int userHandle) { + try { + getContentService().notifyChange( + uri, observer == null ? null : observer.getContentObserver(), + observer != null && observer.deliverSelfNotifications(), flags, userHandle); } catch (RemoteException e) { } diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl index d47e780fa4d2..3446e0315a1d 100644 --- a/core/java/android/content/IContentService.aidl +++ b/core/java/android/content/IContentService.aidl @@ -52,7 +52,7 @@ interface IContentService { * USER_CURRENT are properly interpreted. */ void notifyChange(in Uri uri, IContentObserver observer, - boolean observerWantsSelfNotifications, boolean syncToNetwork, + boolean observerWantsSelfNotifications, int flags, int userHandle); void requestSync(in Account account, String authority, in Bundle extras); diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index ed5dfa5393ec..22ab43bbb429 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -449,11 +449,12 @@ public class IntentFilter implements Parcelable { } /** - * Modify priority of this filter. The default priority is 0. Positive - * values will be before the default, lower values will be after it. - * Applications must use a value that is larger than - * {@link #SYSTEM_LOW_PRIORITY} and smaller than - * {@link #SYSTEM_HIGH_PRIORITY} . + * Modify priority of this filter. This only affects receiver filters. + * The priority of activity filters are set in XML and cannot be changed + * programatically. The default priority is 0. Positive values will be + * before the default, lower values will be after it. Applications should + * use a value that is larger than {@link #SYSTEM_LOW_PRIORITY} and + * smaller than {@link #SYSTEM_HIGH_PRIORITY} . * * @param priority The new priority value. * diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ea251f648034..fe8db9f6ad37 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1096,13 +1096,19 @@ public class PackageParser { pkg.mSignatures = null; pkg.mSigningKeys = null; - collectCertificates(pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags); + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); + try { + collectCertificates( + pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags); - if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { - for (int i = 0; i < pkg.splitCodePaths.length; i++) { - collectCertificates(pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], - parseFlags); + if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { + for (int i = 0; i < pkg.splitCodePaths.length; i++) { + collectCertificates( + pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], parseFlags); + } } + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } @@ -1118,6 +1124,7 @@ public class PackageParser { Certificate[][] allSignersCerts = null; Signature[] signatures = null; try { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV2"); allSignersCerts = ApkSignatureSchemeV2Verifier.verify(apkPath); signatures = convertToSignatures(allSignersCerts); // APK verified using APK Signature Scheme v2. @@ -1130,6 +1137,8 @@ public class PackageParser { "Failed to collect certificates from " + apkPath + " using APK Signature Scheme v2", e); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } if (verified) { @@ -1186,7 +1195,7 @@ public class PackageParser { } // APK's integrity needs to be verified using JAR signature scheme. - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "buildVerifyList"); + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV1"); final List<ZipEntry> toVerify = new ArrayList<>(); toVerify.add(manifestEntry); @@ -1208,7 +1217,6 @@ public class PackageParser { toVerify.add(entry); } } - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); if (!codeFound && requireCode) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, @@ -1218,7 +1226,6 @@ public class PackageParser { // Verify that entries are signed consistently with the first entry // we encountered. Note that for splits, certificates may have // already been populated during an earlier parse of a base APK. - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyEntries"); for (ZipEntry entry : toVerify) { final Certificate[][] entryCerts = loadCertificates(jarFile, entry); if (ArrayUtils.isEmpty(entryCerts)) { @@ -1300,7 +1307,12 @@ public class PackageParser { if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) { // TODO: factor signature related items out of Package object final Package tempPkg = new Package(null); - collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/); + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); + try { + collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } signatures = tempPkg.mSignatures; } else { signatures = null; @@ -5531,7 +5543,7 @@ public class PackageParser { return pi; } - public final static class Instrumentation extends Component { + public final static class Instrumentation extends Component<IntentInfo> { public final InstrumentationInfo info; public Instrumentation(final ParsePackageItemArgs args, final InstrumentationInfo _info) { diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index fbac58c039c6..47440de62827 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -16,9 +16,7 @@ package android.hardware.input; -import com.android.internal.inputmethod.InputMethodSubtypeHandle; import com.android.internal.os.SomeArgs; -import com.android.internal.util.ArrayUtils; import android.annotation.IntDef; import android.annotation.SdkConstant; diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java index 014e73fd8aeb..10fc8e6e366a 100644 --- a/core/java/android/hardware/input/InputManagerInternal.java +++ b/core/java/android/hardware/input/InputManagerInternal.java @@ -52,4 +52,11 @@ public abstract class InputManagerInternal { */ public abstract void onInputMethodSubtypeChanged(int userId, @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype); + + /** + * Toggles Caps Lock state for input device with specific id. + * + * @param deviceId The id of input device. + */ + public abstract void toggleCapsLock(int deviceId); } diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java index 878b7a0e8e10..3c7c962eaa12 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -231,6 +231,18 @@ public class Handler { mAsynchronous = async; } + /** {@hide} */ + public String getTraceName(Message message) { + final StringBuilder sb = new StringBuilder(); + sb.append(getClass().getName()).append(": "); + if (message.callback != null) { + sb.append(message.callback.getClass().getName()); + } else { + sb.append("#").append(message.what); + } + return sb.toString(); + } + /** * Returns a string representing the name of the specified message. * The default implementation will either return the class name of the @@ -739,8 +751,8 @@ public class Handler { message.callback.run(); } - final MessageQueue mQueue; final Looper mLooper; + final MessageQueue mQueue; final Callback mCallback; final boolean mAsynchronous; IMessenger mMessenger; diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java index 34c880f60520..b58ff1fd4755 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -72,6 +72,7 @@ public final class Looper { final Thread mThread; private Printer mLogging; + private long mTraceTag; /** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference @@ -139,13 +140,23 @@ public final class Looper { } // This must be in a local variable, in case a UI event sets the logger - Printer logging = me.mLogging; + final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } - msg.target.dispatchMessage(msg); + final long traceTag = me.mTraceTag; + if (traceTag != 0) { + Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); + } + try { + msg.target.dispatchMessage(msg); + } finally { + if (traceTag != 0) { + Trace.traceEnd(traceTag); + } + } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); @@ -208,6 +219,11 @@ public final class Looper { mLogging = printer; } + /** {@hide} */ + public void setTraceTag(long traceTag) { + mTraceTag = traceTag; + } + /** * Quits the looper. * <p> diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 720d3f7b860a..f2e316cf214f 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1178,23 +1178,7 @@ public class StorageManager { /** {@hide} */ public static File maybeTranslateEmulatedPathToInternal(File path) { - final IMountService mountService = IMountService.Stub.asInterface( - ServiceManager.getService("mount")); - try { - final VolumeInfo[] vols = mountService.getVolumes(0); - for (VolumeInfo vol : vols) { - if ((vol.getType() == VolumeInfo.TYPE_EMULATED - || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) { - final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(), - vol.getInternalPath(), path); - if (internalPath != null && internalPath.exists()) { - return internalPath; - } - } - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + // Disabled now that FUSE has been replaced by sdcardfs return path; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f4d63acdb4e8..2a3c3fe2e5c1 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8306,6 +8306,16 @@ public final class Settings { public static final String BOOT_COUNT = "boot_count"; /** + * Whether the safe boot is disallowed. + * + * <p>This setting should have the identical value as the corresponding user restriction. + * The purpose of the setting is to make the restriction available in early boot stages + * before the user restrictions are loaded. + * @hide + */ + public static final String SAFE_BOOT_DISALLOWED = "safe_boot_disallowed"; + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * diff --git a/core/java/android/service/vr/IVrManager.aidl b/core/java/android/service/vr/IVrManager.aidl new file mode 100644 index 000000000000..62ecab3583cd --- /dev/null +++ b/core/java/android/service/vr/IVrManager.aidl @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.service.vr; + +import android.service.vr.IVrStateCallbacks; + +/** @hide */ +interface IVrManager { + + /** + * Add a callback to be notified when VR mode state changes. + * + * @param cb the callback instance to add. + */ + void registerListener(in IVrStateCallbacks cb); + + /** + * Remove the callack from the current set of registered callbacks. + * + * @param cb the callback to remove. + */ + void unregisterListener(in IVrStateCallbacks cb); + + /** + * Return current VR mode state. + * + * @return {@code true} if VR mode is enabled. + */ + boolean getVrModeState(); + +} + diff --git a/core/java/android/service/vr/IVrStateCallbacks.aidl b/core/java/android/service/vr/IVrStateCallbacks.aidl new file mode 100644 index 000000000000..c4fdcd071fe5 --- /dev/null +++ b/core/java/android/service/vr/IVrStateCallbacks.aidl @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.service.vr; + +/** @hide */ +oneway interface IVrStateCallbacks { + + void onVrStateChanged(in boolean enabled); + +} diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java index 328fe99a7f93..7f0021d729d0 100644 --- a/core/java/android/text/BoringLayout.java +++ b/core/java/android/text/BoringLayout.java @@ -183,8 +183,10 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback if (includepad) { spacing = metrics.bottom - metrics.top; + mDesc = metrics.bottom; } else { spacing = metrics.descent - metrics.ascent; + mDesc = metrics.descent; } mBottom = spacing; @@ -208,8 +210,6 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback mTopPadding = metrics.top - metrics.ascent; mBottomPadding = metrics.bottom - metrics.descent; } - - mDesc = spacing + mBottomPadding + (includepad ? metrics.top : metrics.ascent); } /** diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 6a33579153bc..94ce57ac7cb9 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -1132,22 +1132,12 @@ public class StaticLayout extends Layout { @Override public int getLineTop(int line) { - int top = mLines[mColumns * line + TOP]; - if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount && - line != mLineCount) { - top += getBottomPadding(); - } - return top; + return mLines[mColumns * line + TOP]; } @Override public int getLineDescent(int line) { - int descent = mLines[mColumns * line + DESCENT]; - if (mMaximumVisibleLineCount > 0 && line >= mMaximumVisibleLineCount - 1 && // -1 intended - line != mLineCount) { - descent += getBottomPadding(); - } - return descent; + return mLines[mColumns * line + DESCENT]; } @Override diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index e0c6770ecb38..636384c616e0 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1870,6 +1870,11 @@ public class KeyEvent extends InputEvent implements Parcelable { return keyCode == KeyEvent.KEYCODE_META_LEFT || keyCode == KeyEvent.KEYCODE_META_RIGHT; } + /** @hide */ + public static final boolean isAltKey(int keyCode) { + return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT; + } + /** {@inheritDoc} */ @Override public final int getDeviceId() { diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java index cff9d8e93c98..37da8695a1ad 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -22,7 +22,6 @@ import android.graphics.Rect; import android.util.AttributeSet; import android.widget.ImageView; import android.widget.RemoteViews; -import android.widget.TextView; import java.util.ArrayList; @@ -37,7 +36,7 @@ public class NotificationHeaderView extends ViewGroup { private final int mChildMinWidth; private final int mContentEndMargin; private View mAppName; - private View mSubTextView; + private View mHeaderText; private OnClickListener mExpandClickListener; private HeaderTouchListener mTouchListener = new HeaderTouchListener(); private ImageView mExpandButton; @@ -73,11 +72,10 @@ public class NotificationHeaderView extends ViewGroup { protected void onFinishInflate() { super.onFinishInflate(); mAppName = findViewById(com.android.internal.R.id.app_name_text); - mSubTextView = findViewById(com.android.internal.R.id.header_sub_text); + mHeaderText = findViewById(com.android.internal.R.id.header_text); mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button); mIcon = findViewById(com.android.internal.R.id.icon); mProfileBadge = findViewById(com.android.internal.R.id.profile_badge); - mInfo = findViewById(com.android.internal.R.id.header_content_info); } @Override @@ -105,15 +103,7 @@ public class NotificationHeaderView extends ViewGroup { } if (totalWidth > givenWidth) { int overFlow = totalWidth - givenWidth; - // We are overflowing, lets shrink the info first - final int infoWidth = mInfo.getMeasuredWidth(); - if (mInfo.getVisibility() != GONE && infoWidth > mChildMinWidth) { - int newSize = infoWidth - Math.min(infoWidth - mChildMinWidth, overFlow); - int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST); - mInfo.measure(childWidthSpec, wrapContentHeightSpec); - overFlow -= infoWidth - newSize; - } - // still overflowing, lets shrink the app name now + // We are overflowing, lets shrink the app name first final int appWidth = mAppName.getMeasuredWidth(); if (overFlow > 0 && mAppName.getVisibility() != GONE && appWidth > mChildMinWidth) { int newSize = appWidth - Math.min(appWidth - mChildMinWidth, overFlow); @@ -121,13 +111,13 @@ public class NotificationHeaderView extends ViewGroup { mAppName.measure(childWidthSpec, wrapContentHeightSpec); overFlow -= appWidth - newSize; } - // still overflowing, finaly we shrink the subtext - if (overFlow > 0 && mSubTextView.getVisibility() != GONE) { + // still overflowing, finaly we shrink the header text + if (overFlow > 0 && mHeaderText.getVisibility() != GONE) { // we're still too big - final int subTextWidth = mSubTextView.getMeasuredWidth(); - int newSize = Math.max(0, subTextWidth - overFlow); + final int textWidth = mHeaderText.getMeasuredWidth(); + int newSize = Math.max(0, textWidth - overFlow); int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST); - mSubTextView.measure(childWidthSpec, wrapContentHeightSpec); + mHeaderText.measure(childWidthSpec, wrapContentHeightSpec); } } setMeasuredDimension(givenWidth, givenHeight); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 23b0df2db110..96f179b8db63 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -1397,4 +1397,9 @@ public interface WindowManagerPolicy { * is allowed, so for example, if DOCKED_RIGHT is not allowed, DOCKED_LEFT is allowed. */ public boolean isDockSideAllowed(int dockSide); + + /** + * Called when the configuration has changed, and it's safe to load new values from resources. + */ + public void onConfigurationChanged(); } diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java index 1536c29bee5b..d89c172be8a7 100644 --- a/core/java/android/view/animation/Animation.java +++ b/core/java/android/view/animation/Animation.java @@ -93,8 +93,12 @@ public abstract class Animation implements Cloneable { */ public static final int ZORDER_BOTTOM = -1; - private static final boolean USE_CLOSEGUARD - = SystemProperties.getBoolean("log.closeguard.Animation", false); + // Use a preload holder to isolate static initialization into inner class, which allows + // Animation and its subclasses to be compile-time initialized. + private static class NoImagePreloadHolder { + public static final boolean USE_CLOSEGUARD + = SystemProperties.getBoolean("log.closeguard.Animation", false); + } /** * Set by {@link #getTransformation(long, Transformation)} when the animation ends. @@ -859,7 +863,7 @@ public abstract class Animation implements Cloneable { if (!mStarted) { fireAnimationStart(); mStarted = true; - if (USE_CLOSEGUARD) { + if (NoImagePreloadHolder.USE_CLOSEGUARD) { guard.open("cancel or detach or getTransformation"); } } diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java index e3357a7738f2..0c5edc5f2f81 100644 --- a/core/java/android/widget/DatePicker.java +++ b/core/java/android/widget/DatePicker.java @@ -339,7 +339,9 @@ public class DatePicker extends FrameLayout { * * @return {@code true} if the calendar view is shown * @see #getCalendarView() + * @deprecated Not supported by Material-style {@code calendar} mode */ + @Deprecated public boolean getCalendarViewShown() { return mDelegate.getCalendarViewShown(); } @@ -347,13 +349,18 @@ public class DatePicker extends FrameLayout { /** * Returns the {@link CalendarView} used by this picker. * <p> - * <strong>Note:</strong> This method returns {@code null} when the + * <strong>Note:</strong> This method throws an + * {@link UnsupportedOperationException} when the * {@link android.R.styleable#DatePicker_datePickerMode} attribute is set * to {@code calendar}. * * @return the calendar view * @see #getCalendarViewShown() + * @deprecated Not supported by Material-style {@code calendar} mode + * @throws UnsupportedOperationException if called when the picker is + * displayed in {@code calendar} mode */ + @Deprecated public CalendarView getCalendarView() { return mDelegate.getCalendarView(); } @@ -367,7 +374,9 @@ public class DatePicker extends FrameLayout { * * @param shown {@code true} to show the calendar view, {@code false} to * hide it + * @deprecated Not supported by Material-style {@code calendar} mode */ + @Deprecated public void setCalendarViewShown(boolean shown) { mDelegate.setCalendarViewShown(shown); } @@ -380,7 +389,9 @@ public class DatePicker extends FrameLayout { * to {@code calendar}. * * @return {@code true} if the spinners are shown + * @deprecated Not supported by Material-style {@code calendar} mode */ + @Deprecated public boolean getSpinnersShown() { return mDelegate.getSpinnersShown(); } @@ -394,7 +405,9 @@ public class DatePicker extends FrameLayout { * * @param shown {@code true} to show the spinners, {@code false} to hide * them + * @deprecated Not supported by Material-style {@code calendar} mode */ + @Deprecated public void setSpinnersShown(boolean shown) { mDelegate.setSpinnersShown(shown); } diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java index 8ce2f9cb470c..97936e7c7c5b 100644 --- a/core/java/android/widget/DayPickerPagerAdapter.java +++ b/core/java/android/widget/DayPickerPagerAdapter.java @@ -148,18 +148,22 @@ class DayPickerPagerAdapter extends PagerAdapter { void setCalendarTextColor(ColorStateList calendarTextColor) { mCalendarTextColor = calendarTextColor; + notifyDataSetChanged(); } void setDaySelectorColor(ColorStateList selectorColor) { mDaySelectorColor = selectorColor; + notifyDataSetChanged(); } void setMonthTextAppearance(int resId) { mMonthTextAppearance = resId; + notifyDataSetChanged(); } void setDayOfWeekTextAppearance(int resId) { mDayOfWeekTextAppearance = resId; + notifyDataSetChanged(); } int getDayOfWeekTextAppearance() { @@ -168,6 +172,7 @@ class DayPickerPagerAdapter extends PagerAdapter { void setDayTextAppearance(int resId) { mDayTextAppearance = resId; + notifyDataSetChanged(); } int getDayTextAppearance() { diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 7055f783c584..440ef2162fc5 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1778,6 +1778,18 @@ public class Editor { if (translate) canvas.translate(0, -cursorOffsetVertical); } + void invalidateHandlesAndActionMode() { + if (mSelectionModifierCursorController != null) { + mSelectionModifierCursorController.invalidateHandles(); + } + if (mInsertionPointCursorController != null) { + mInsertionPointCursorController.invalidateHandle(); + } + if (mTextActionMode != null) { + mTextActionMode.invalidate(); + } + } + /** * Invalidates all the sub-display lists that overlap the specified character range */ @@ -3462,7 +3474,6 @@ public class Editor { popupBackground.getPadding(mTempRect); width += mTempRect.left + mTempRect.right; } - mSuggestionListView.getLayoutParams().width = width; mPopupWindow.setWidth(width); } @@ -4104,6 +4115,14 @@ public class Editor { setMeasuredDimension(getPreferredWidth(), getPreferredHeight()); } + @Override + public void invalidate() { + super.invalidate(); + if (isShowing()) { + positionAtCursorOffset(getCurrentCursorOffset(), true); + } + }; + private int getPreferredWidth() { return Math.max(mDrawable.getIntrinsicWidth(), mMinSize); } @@ -4170,7 +4189,12 @@ public class Editor { return mTextView.getOffsetAtCoordinate(line, x); } - protected void positionAtCursorOffset(int offset, boolean parentScrolled) { + /** + * @param offset Cursor offset. Must be in [-1, length]. + * @param forceUpdatePosition whether to force update the position. This should be true + * when If the parent has been scrolled, for example. + */ + protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) { // A HandleView relies on the layout, which may be nulled by external methods Layout layout = mTextView.getLayout(); if (layout == null) { @@ -4181,7 +4205,7 @@ public class Editor { layout = mTextView.getLayout(); boolean offsetChanged = offset != mPreviousOffset; - if (offsetChanged || parentScrolled) { + if (offsetChanged || forceUpdatePosition) { if (offsetChanged) { updateSelection(offset); addPositionToTouchUpFilter(offset); @@ -4782,13 +4806,9 @@ public class Editor { mPrevX = x; } - /** - * @param offset Cursor offset. Must be in [-1, length]. - * @param parentScrolled If the parent has been scrolled or not. - */ @Override - protected void positionAtCursorOffset(int offset, boolean parentScrolled) { - super.positionAtCursorOffset(offset, parentScrolled); + protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) { + super.positionAtCursorOffset(offset, forceUpdatePosition); mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset); } @@ -5014,6 +5034,12 @@ public class Editor { public boolean isActive() { return mHandle != null && mHandle.isShowing(); } + + public void invalidateHandle() { + if (mHandle != null) { + mHandle.invalidate(); + } + } } class SelectionModifierCursorController implements CursorController { @@ -5418,6 +5444,15 @@ public class Editor { public boolean isActive() { return mStartHandle != null && mStartHandle.isShowing(); } + + public void invalidateHandles() { + if (mStartHandle != null) { + mStartHandle.invalidate(); + } + if (mEndHandle != null) { + mEndHandle.invalidate(); + } + } } private class CorrectionHighlighter { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 4483b7bab3cd..48fd58b219db 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3350,7 +3350,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mShadowColor = color; // Will change text clip region - if (mEditor != null) mEditor.invalidateTextDisplayList(); + if (mEditor != null) { + mEditor.invalidateTextDisplayList(); + mEditor.invalidateHandlesAndActionMode(); + } invalidate(); } @@ -8306,6 +8309,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEditor != null) { if (oldStart >= 0) mEditor.invalidateTextDisplayList(mLayout, oldStart, oldEnd); if (newStart >= 0) mEditor.invalidateTextDisplayList(mLayout, newStart, newEnd); + mEditor.invalidateHandlesAndActionMode(); } } diff --git a/core/java/com/android/internal/os/BackgroundThread.java b/core/java/com/android/internal/os/BackgroundThread.java index d6f7b20189a8..cffba0177d14 100644 --- a/core/java/com/android/internal/os/BackgroundThread.java +++ b/core/java/com/android/internal/os/BackgroundThread.java @@ -18,6 +18,7 @@ package com.android.internal.os; import android.os.Handler; import android.os.HandlerThread; +import android.os.Trace; /** * Shared singleton background thread for each process. @@ -34,6 +35,7 @@ public final class BackgroundThread extends HandlerThread { if (sInstance == null) { sInstance = new BackgroundThread(); sInstance.start(); + sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER); sHandler = new Handler(sInstance.getLooper()); } } diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl index e330de24f6d6..171a264eea8b 100644 --- a/core/java/com/android/internal/policy/IKeyguardService.aidl +++ b/core/java/com/android/internal/policy/IKeyguardService.aidl @@ -50,9 +50,12 @@ oneway interface IKeyguardService { * Called when the device has finished going to sleep. * * @param why {@link #OFF_BECAUSE_OF_USER}, {@link #OFF_BECAUSE_OF_ADMIN}, - * or {@link #OFF_BECAUSE_OF_TIMEOUT}. + * or {@link #OFF_BECAUSE_OF_TIMEOUT}. + * @param cameraGestureTriggered whether the camera gesture was triggered between + * {@link #onStartedGoingToSleep} and this method; if it's been + * triggered, we shouldn't lock the device. */ - void onFinishedGoingToSleep(int reason); + void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered); /** * Called when the device has started waking up. diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index da223a64e2e8..1848fe88dea9 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -1460,6 +1460,7 @@ public final class FloatingToolbar { super(Preconditions.checkNotNull(popup).mContext); this.mPopup = popup; setScrollBarDefaultDelayBeforeFade(ViewConfiguration.getScrollDefaultDelay() * 3); + setScrollIndicators(View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM); } @Override diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index c4347f832bd5..25b487efdae6 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -17,9 +17,14 @@ package com.android.internal.widget; +import android.annotation.NonNull; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -85,6 +90,10 @@ public class ResolverDrawerLayout extends ViewGroup { private final float mMinFlingVelocity; private final OverScroller mScroller; private final VelocityTracker mVelocityTracker; + private final Drawable mScrollIndicatorDrawable; + private final Drawable mFakeForeground; + + private View mButtonBar; private OnDismissedListener mOnDismissedListener; private RunOnDismissedListener mRunOnDismissedListener; @@ -106,6 +115,8 @@ public class ResolverDrawerLayout extends ViewGroup { } }; + private final int[] mTempOffset = new int[2]; + public ResolverDrawerLayout(Context context) { this(context, null); } @@ -127,6 +138,9 @@ public class ResolverDrawerLayout extends ViewGroup { mMaxCollapsedHeight); a.recycle(); + mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); + mFakeForeground = new ColorDrawable(Color.TRANSPARENT); + mScroller = new OverScroller(context, AnimationUtils.loadInterpolator(context, android.R.interpolator.decelerate_quint)); mVelocityTracker = VelocityTracker.obtain(); @@ -138,6 +152,13 @@ public class ResolverDrawerLayout extends ViewGroup { setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); } + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + mButtonBar = findViewById(R.id.button_bar); + } + public void setSmallCollapsed(boolean smallCollapsed) { mSmallCollapsed = smallCollapsed; requestLayout(); @@ -202,8 +223,7 @@ public class ResolverDrawerLayout extends ViewGroup { } final boolean isCollapsedNew = mCollapseOffset != 0; if (isCollapsedOld != isCollapsedNew) { - notifyViewAccessibilityStateChangedIfNeeded( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + onCollapsedChanged(isCollapsedNew); } } else { // Start out collapsed at first unless we restored state for otherwise @@ -442,8 +462,7 @@ public class ResolverDrawerLayout extends ViewGroup { mTopOffset += dy; final boolean isCollapsedNew = newPos != 0; if (isCollapsedOld != isCollapsedNew) { - notifyViewAccessibilityStateChangedIfNeeded( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + onCollapsedChanged(isCollapsedNew); } postInvalidateOnAnimation(); return dy; @@ -451,6 +470,14 @@ public class ResolverDrawerLayout extends ViewGroup { return 0; } + private void onCollapsedChanged(boolean isCollapsed) { + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + + // Set a fake foreground so that we receive onDrawForeground(). + setForeground(isCollapsed ? mFakeForeground : null); + } + void dispatchOnDismissed() { if (mOnDismissedListener != null) { mOnDismissedListener.onDismissed(); @@ -709,6 +736,23 @@ public class ResolverDrawerLayout extends ViewGroup { } @Override + public void onDrawForeground(Canvas canvas) { + if (isCollapsed() && mButtonBar != null) { + // Draw the scroll indicator directly above the button bar. + final int height = mScrollIndicatorDrawable.getIntrinsicHeight(); + mButtonBar.getLocationInWindow(mTempOffset); + final int barTop = mTempOffset[1]; + getLocationInWindow(mTempOffset); + final int myTop = mTempOffset[1]; + final int top = (barTop - myTop) - height; + mScrollIndicatorDrawable.setBounds(0, top, getWidth(), top + height); + mScrollIndicatorDrawable.draw(canvas); + } + + super.onDrawForeground(canvas); + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int sourceWidth = MeasureSpec.getSize(widthMeasureSpec); int widthSize = sourceWidth; diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 1844a9870ada..f46f45cc5e5d 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -768,6 +768,22 @@ namespace PaintGlue { return false; } + // Returns true if the given string is exact one pair of regional indicators. + static bool isFlag(const jchar* str, size_t length) { + const jchar RI_LEAD_SURROGATE = 0xD83C; + const jchar RI_TRAIL_SURROGATE_MIN = 0xDDE6; + const jchar RI_TRAIL_SURROGATE_MAX = 0xDDFF; + + if (length != 4) { + return false; + } + if (str[0] != RI_LEAD_SURROGATE || str[2] != RI_LEAD_SURROGATE) { + return false; + } + return RI_TRAIL_SURROGATE_MIN <= str[1] && str[1] <= RI_TRAIL_SURROGATE_MAX && + RI_TRAIL_SURROGATE_MIN <= str[3] && str[3] <= RI_TRAIL_SURROGATE_MAX; + } + static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle, jint bidiFlags, jstring string) { const Paint* paint = reinterpret_cast<Paint*>(paintHandle); @@ -817,7 +833,26 @@ namespace PaintGlue { // in joining scripts, such as Arabic and Mongolian. return false; } - return nGlyphs > 0 && !layoutContainsNotdef(layout); + + if (nGlyphs == 0 || layoutContainsNotdef(layout)) { + return false; // The collection doesn't have a glyph. + } + + if (nChars == 2 && isFlag(str.get(), str.size())) { + // Some font may have a special glyph for unsupported regional indicator pairs. + // To return false for this case, need to compare the glyph id with the one of ZZ + // since ZZ is reserved for unknown or invalid territory. + // U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16. + static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF }; + Layout zzLayout; + MinikinUtils::doLayout(&zzLayout, paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4); + if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) { + // The font collection doesn't have a glyph for unknown flag. Just return true. + return true; + } + return zzLayout.getGlyphId(0) != layout.getGlyphId(0); + } + return true; } static jfloat doRunAdvance(const Paint* paint, Typeface* typeface, const jchar buf[], diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 88d75dd4c9fd..9a2e39c752de 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2997,6 +2997,11 @@ <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE" android:protectionLevel="signature" /> + <!-- Required to make calls to {@link android.service.vr.IVrManager}. + @hide --> + <permission android:name="android.permission.ACCESS_VR_MANAGER" + android:protectionLevel="signature" /> + <!-- Allows an application to whitelist tasks during lock task mode @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES" diff --git a/core/res/res/anim/slide_in_enter_micro.xml b/core/res/res/anim/slide_in_enter_micro.xml index 14a5290a66fe..c70874c626b8 100644 --- a/core/res/res/anim/slide_in_enter_micro.xml +++ b/core/res/res/anim/slide_in_enter_micro.xml @@ -19,7 +19,7 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="top"> - <translate android:fromYDelta="5%p" android:toXDelta="0" + <translate android:fromYDelta="5%p" android:toYDelta="0" android:duration="417" android:interpolator="@android:interpolator/launch_task_micro_ydelta" /> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml index 0bbaa24a9ad4..992e88e22ad9 100644 --- a/core/res/res/layout/notification_template_header.xml +++ b/core/res/res/layout/notification_template_header.xml @@ -42,7 +42,7 @@ android:singleLine="true" /> <TextView - android:id="@+id/sub_text_divider" + android:id="@+id/header_text_divider" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Material.Notification.Info" @@ -51,26 +51,7 @@ android:text="@string/notification_header_divider_symbol" android:visibility="gone"/> <TextView - android:id="@+id/header_sub_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.Material.Notification.Info" - android:layout_marginStart="2dp" - android:layout_marginEnd="2dp" - android:visibility="gone" - android:singleLine="true"/> - <TextView - android:id="@+id/content_info_divider" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.Material.Notification.Info" - android:layout_marginStart="2dp" - android:layout_marginEnd="2dp" - android:text="@string/notification_header_divider_symbol" - android:singleLine="true" - android:visibility="gone"/> - <TextView - android:id="@+id/header_content_info" + android:id="@+id/header_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Material.Notification.Info" diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml index 4b8640c91f70..fe43e1c5d8b8 100644 --- a/core/res/res/layout/resolver_list.xml +++ b/core/res/res/layout/resolver_list.xml @@ -30,33 +30,37 @@ android:layout_height="wrap_content" android:layout_alwaysShow="true" android:elevation="8dp" - android:background="@color/white" > - <TextView android:id="@+id/profile_button" - android:layout_width="wrap_content" - android:layout_height="48dp" - android:layout_marginEnd="8dp" - android:paddingStart="8dp" - android:paddingEnd="8dp" - android:visibility="gone" - style="?attr/borderlessButtonStyle" - android:textAppearance="?attr/textAppearanceButton" - android:textColor="@color/material_deep_teal_500" - android:gravity="center_vertical" - android:layout_alignParentTop="true" - android:layout_alignParentRight="true" - android:singleLine="true"/> - <TextView android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:minHeight="56dp" - android:textAppearance="?attr/textAppearanceMedium" - android:gravity="start|center_vertical" - android:paddingStart="?attr/dialogPreferredPadding" - android:paddingEnd="?attr/dialogPreferredPadding" - android:paddingTop="8dp" - android:layout_below="@id/profile_button" - android:layout_alignParentLeft="true" - android:paddingBottom="8dp" /> + android:background="@color/white"> + + <TextView + android:id="@+id/profile_button" + android:layout_width="wrap_content" + android:layout_height="48dp" + android:layout_marginEnd="8dp" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:visibility="gone" + style="?attr/borderlessButtonStyle" + android:textAppearance="?attr/textAppearanceButton" + android:textColor="@color/material_deep_teal_500" + android:gravity="center_vertical" + android:layout_alignParentTop="true" + android:layout_alignParentRight="true" + android:singleLine="true" /> + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minHeight="56dp" + android:textAppearance="?attr/textAppearanceMedium" + android:gravity="start|center_vertical" + android:paddingStart="?attr/dialogPreferredPadding" + android:paddingEnd="?attr/dialogPreferredPadding" + android:paddingTop="8dp" + android:layout_below="@id/profile_button" + android:layout_alignParentLeft="true" + android:paddingBottom="8dp" /> </RelativeLayout> <ListView @@ -68,21 +72,23 @@ android:background="@color/white" android:elevation="8dp" android:nestedScrollingEnabled="true" + android:scrollIndicators="top|bottom" android:divider="@null" /> - <TextView android:id="@+id/empty" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_alwaysShow="true" - android:text="@string/noApplications" - android:padding="32dp" - android:gravity="center" - android:visibility="gone" /> + <TextView + android:id="@+id/empty" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alwaysShow="true" + android:text="@string/noApplications" + android:padding="32dp" + android:gravity="center" + android:visibility="gone" /> <LinearLayout android:id="@+id/button_bar" android:visibility="gone" - style="?android:attr/buttonBarStyle" + style="?attr/buttonBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_ignoreOffset="true" @@ -97,26 +103,30 @@ android:paddingStart="12dp" android:paddingEnd="12dp" android:elevation="8dp"> - <Button android:id="@+id/button_once" - android:layout_width="wrap_content" - android:layout_gravity="start" - android:maxLines="2" - style="?android:attr/buttonBarNegativeButtonStyle" - android:minHeight="@dimen/alert_dialog_button_bar_height" - android:layout_height="wrap_content" - android:enabled="false" - android:text="@string/activity_resolver_use_once" - android:onClick="onButtonClick" /> - <Button android:id="@+id/button_always" - android:layout_width="wrap_content" - android:layout_gravity="end" - android:maxLines="2" - android:minHeight="@dimen/alert_dialog_button_bar_height" - style="?android:attr/buttonBarPositiveButtonStyle" - android:layout_height="wrap_content" - android:enabled="false" - android:text="@string/activity_resolver_use_always" - android:onClick="onButtonClick" /> + + <Button + android:id="@+id/button_once" + android:layout_width="wrap_content" + android:layout_gravity="start" + android:maxLines="2" + style="?attr/buttonBarNegativeButtonStyle" + android:minHeight="@dimen/alert_dialog_button_bar_height" + android:layout_height="wrap_content" + android:enabled="false" + android:text="@string/activity_resolver_use_once" + android:onClick="onButtonClick" /> + + <Button + android:id="@+id/button_always" + android:layout_width="wrap_content" + android:layout_gravity="end" + android:maxLines="2" + android:minHeight="@dimen/alert_dialog_button_bar_height" + style="?attr/buttonBarPositiveButtonStyle" + android:layout_height="wrap_content" + android:enabled="false" + android:text="@string/activity_resolver_use_always" + android:onClick="onButtonClick" /> </LinearLayout> </com.android.internal.widget.ResolverDrawerLayout> diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml index 31361e5f9c48..ed7ef5edd817 100644 --- a/core/res/res/layout/resolver_list_with_default.xml +++ b/core/res/res/layout/resolver_list_with_default.xml @@ -22,8 +22,7 @@ android:layout_height="match_parent" android:maxWidth="@dimen/resolver_max_width" android:maxCollapsedHeight="144dp" - android:id="@id/contentPanel" - > + android:id="@id/contentPanel"> <LinearLayout android:layout_width="match_parent" @@ -31,66 +30,75 @@ android:layout_alwaysShow="true" android:orientation="vertical" android:background="@color/white" - android:elevation="8dp" > + android:elevation="8dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="64dp" - android:orientation="horizontal" > + android:orientation="horizontal"> - <ImageView android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_gravity="start|top" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" - android:layout_marginTop="20dp" - android:scaleType="fitCenter" /> - <TextView android:id="@+id/title" - android:layout_width="0dp" - android:layout_weight="1" - android:layout_height="?android:attr/listPreferredItemHeight" - android:layout_marginStart="16dp" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="start|center_vertical" - android:paddingEnd="16dp" /> - <LinearLayout android:id="@+id/profile_button" - android:layout_width="wrap_content" - android:layout_height="48dp" - android:layout_marginTop="4dp" - android:layout_marginEnd="4dp" - android:paddingStart="8dp" - android:paddingEnd="8dp" - android:paddingTop="4dp" - android:paddingBottom="4dp" - android:focusable="true" - android:visibility="gone" - style="?attr/borderlessButtonStyle"> - <ImageView android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_gravity="start|center_vertical" - android:layout_marginEnd="?attr/listPreferredItemPaddingEnd" - android:layout_marginTop="12dp" - android:layout_marginBottom="12dp" - android:scaleType="fitCenter" /> - <TextView android:id="@id/text1" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="start|center_vertical" - android:layout_marginEnd="?attr/listPreferredItemPaddingEnd" - android:textAppearance="?attr/textAppearanceButton" - android:textColor="?attr/textColorPrimary" - android:minLines="1" - android:maxLines="1" - android:ellipsize="marquee" /> + <ImageView + android:id="@+id/icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="start|top" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:layout_marginTop="20dp" + android:scaleType="fitCenter" /> + + <TextView + android:id="@+id/title" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="?attr/listPreferredItemHeight" + android:layout_marginStart="16dp" + android:textAppearance="?attr/textAppearanceMedium" + android:gravity="start|center_vertical" + android:paddingEnd="16dp" /> + + <LinearLayout + android:id="@+id/profile_button" + android:layout_width="wrap_content" + android:layout_height="48dp" + android:layout_marginTop="4dp" + android:layout_marginEnd="4dp" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:paddingTop="4dp" + android:paddingBottom="4dp" + android:focusable="true" + android:visibility="gone" + style="?attr/borderlessButtonStyle"> + + <ImageView + android:id="@+id/icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="start|center_vertical" + android:layout_marginEnd="?attr/listPreferredItemPaddingEnd" + android:layout_marginTop="12dp" + android:layout_marginBottom="12dp" + android:scaleType="fitCenter" /> + + <TextView + android:id="@id/text1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="start|center_vertical" + android:layout_marginEnd="?attr/listPreferredItemPaddingEnd" + android:textAppearance="?attr/textAppearanceButton" + android:textColor="?attr/textColorPrimary" + android:minLines="1" + android:maxLines="1" + android:ellipsize="marquee" /> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/button_bar" android:visibility="gone" - style="?android:attr/buttonBarStyle" + style="?attr/buttonBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alwaysShow="true" @@ -104,30 +112,36 @@ android:paddingEnd="12dp" android:background="@color/white" android:elevation="8dp"> - <Button android:id="@+id/button_once" - android:layout_width="wrap_content" - android:layout_gravity="start" - android:maxLines="2" - style="?android:attr/buttonBarNegativeButtonStyle" - android:minHeight="@dimen/alert_dialog_button_bar_height" - android:layout_height="wrap_content" - android:enabled="false" - android:text="@string/activity_resolver_use_once" - android:onClick="onButtonClick" /> - <Button android:id="@+id/button_always" - android:layout_width="wrap_content" - android:layout_gravity="end" - android:maxLines="2" - android:minHeight="@dimen/alert_dialog_button_bar_height" - style="?android:attr/buttonBarPositiveButtonStyle" - android:layout_height="wrap_content" - android:enabled="false" - android:text="@string/activity_resolver_use_always" - android:onClick="onButtonClick" /> + + <Button + android:id="@+id/button_once" + android:layout_width="wrap_content" + android:layout_gravity="start" + android:maxLines="2" + style="?attr/buttonBarNegativeButtonStyle" + android:minHeight="@dimen/alert_dialog_button_bar_height" + android:layout_height="wrap_content" + android:enabled="false" + android:text="@string/activity_resolver_use_once" + android:onClick="onButtonClick" /> + + <Button + android:id="@+id/button_always" + android:layout_width="wrap_content" + android:layout_gravity="end" + android:maxLines="2" + android:minHeight="@dimen/alert_dialog_button_bar_height" + style="?attr/buttonBarPositiveButtonStyle" + android:layout_height="wrap_content" + android:enabled="false" + android:text="@string/activity_resolver_use_always" + android:onClick="onButtonClick" /> </LinearLayout> - <View android:layout_width="match_parent" - android:layout_height="1dp" - android:background="?android:attr/dividerVertical" /> + + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?attr/dividerVertical" /> </LinearLayout> <ListView @@ -140,6 +154,6 @@ android:elevation="8dp" android:nestedScrollingEnabled="true" android:divider="@null" - /> + android:scrollIndicators="top|bottom" /> </com.android.internal.widget.ResolverDrawerLayout> diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml index 73a8e044cca1..8a23529da4ef 100644 --- a/core/res/res/values-be-rBY/strings.xml +++ b/core/res/res/values-be-rBY/strings.xml @@ -238,7 +238,7 @@ <string name="safeMode" msgid="2788228061547930246">"Бяспечны рэжым"</string> <string name="android_system_label" msgid="6577375335728551336">"Сістэма Android"</string> <string name="user_owner_label" msgid="1119010402169916617">"Пераключыцца на асабісты"</string> - <string name="managed_profile_label" msgid="5289992269827577857">"Пераключыцца на рабочы"</string> + <string name="managed_profile_label" msgid="5289992269827577857">"Пераключыцца на працоўны"</string> <string name="permgrouplab_contacts" msgid="3657758145679177612">"Кантакты"</string> <string name="permgroupdesc_contacts" msgid="6951499528303668046">"атрымліваць доступ да вашых кантактаў"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"Месцазнаходжанне"</string> diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml index a8e0285e3d0a..ea666d975b05 100644 --- a/core/res/res/values-eu-rES/strings.xml +++ b/core/res/res/values-eu-rES/strings.xml @@ -1063,7 +1063,7 @@ <string name="select_input_method" msgid="8547250819326693584">"Aldatu teklatua"</string> <string name="show_ime" msgid="2506087537466597099">"Erakutsi pantailan teklatu fisikoa aktibo dagoen bitartean"</string> <string name="hardware" msgid="194658061510127999">"Erakutsi teklatu birtuala"</string> - <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguratu teklatua fisikoa"</string> + <string name="select_keyboard_layout_notification_title" msgid="597189518763083494">"Konfiguratu teklatu fisikoa"</string> <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index c216be8ca172..3b26e461f7b1 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -233,8 +233,8 @@ <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"内容已隐藏(根据政策规定)"</string> <string name="safeMode" msgid="2788228061547930246">"安全模式"</string> <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string> - <string name="user_owner_label" msgid="1119010402169916617">"切换为“个人”"</string> - <string name="managed_profile_label" msgid="5289992269827577857">"切换为“工作”"</string> + <string name="user_owner_label" msgid="1119010402169916617">"切换到“个人”"</string> + <string name="managed_profile_label" msgid="5289992269827577857">"切换到“工作”"</string> <string name="permgrouplab_contacts" msgid="3657758145679177612">"通讯录"</string> <string name="permgroupdesc_contacts" msgid="6951499528303668046">"访问您的通讯录"</string> <string name="permgrouplab_location" msgid="7275582855722310164">"位置信息"</string> @@ -1473,7 +1473,7 @@ <string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string> <string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string> <string name="package_deleted_device_owner" msgid="7650577387493101353">"已被管理员删除"</string> - <string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,节电助手会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n节电助手会在设备充电时自动关闭。"</string> + <string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,省电模式会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n省电模式会在设备充电时自动关闭。"</string> <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848"> <item quantity="other">%1$d 分钟(到<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item> <item quantity="one">1 分钟(到<xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index cae04adfb8b2..b4371c189d40 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2507,4 +2507,17 @@ <!-- True if the device supports Sustained Performance Mode--> <bool name="config_sustainedPerformanceModeSupported">false</bool> + + <!-- Controls how we deal with externally connected physical keyboards. + 0 - When using this device, it is not clear for users to recognize when the physical + keyboard is (should be) connected and when it is (should be) disconnected. Most of + phones and tablets with Bluetooth keyboard would fall into this category because the + connected Bluetooth keyboard may or may not be nearby the host device. + 1 - When using this device, it is clear for users to recognize when the physical + keyboard is (should be) connected and when it is (should be) disconnected. + Devices with wired USB keyboard is one clear example. Some 2-in-1 convertible + tablets with dedicated keyboards may have the same affordance to wired USB keyboard. + --> + <integer name="config_externalHardKeyboardBehavior">0</integer> + </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1e10f863f0fb..2215bd42db1e 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1744,6 +1744,7 @@ <java-symbol type="integer" name="config_defaultNotificationLedOff" /> <java-symbol type="integer" name="config_defaultNotificationLedOn" /> <java-symbol type="integer" name="config_deskDockKeepsScreenOn" /> + <java-symbol type="integer" name="config_externalHardKeyboardBehavior" /> <java-symbol type="integer" name="config_lightSensorWarmupTime" /> <java-symbol type="integer" name="config_lowBatteryCloseWarningBump" /> <java-symbol type="integer" name="config_lowBatteryWarningLevel" /> @@ -2419,13 +2420,11 @@ <java-symbol type="string" name="notification_hidden_text" /> <java-symbol type="string" name="notification_hidden_by_policy_text" /> <java-symbol type="id" name="app_name_text" /> - <java-symbol type="id" name="header_sub_text" /> + <java-symbol type="id" name="header_text" /> <java-symbol type="id" name="expand_button" /> <java-symbol type="id" name="notification_header" /> - <java-symbol type="id" name="header_content_info" /> <java-symbol type="id" name="time_divider" /> - <java-symbol type="id" name="sub_text_divider" /> - <java-symbol type="id" name="content_info_divider" /> + <java-symbol type="id" name="header_text_divider" /> <java-symbol type="id" name="text_line_1" /> <java-symbol type="drawable" name="ic_expand_notification" /> <java-symbol type="drawable" name="ic_collapse_notification" /> diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java index 59ffd566909f..eafe42723780 100644 --- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java +++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java @@ -16,13 +16,35 @@ package android.widget; -import android.app.Activity; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.Espresso.pressBack; +import static android.support.test.espresso.action.ViewActions.clearText; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.replaceText; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.RootMatchers.withDecorView; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static android.widget.espresso.DragHandleUtils.onHandleView; +import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem; +import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem; +import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup; +import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupContainsItem; +import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsDisplayed; +import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsNotDisplayed; +import static android.widget.espresso.SuggestionsPopupwindowUtils.clickSuggestionsPopupItem; +import static android.widget.espresso.SuggestionsPopupwindowUtils.onSuggestionsPopup; +import static android.widget.espresso.TextViewActions.clickOnTextAtIndex; +import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex; +import static org.hamcrest.Matchers.is; import android.content.res.TypedArray; +import android.support.test.espresso.NoMatchingViewException; +import android.support.test.espresso.ViewAssertion; import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.Suppress; import android.text.Selection; -import android.text.SpannableStringBuilder; +import android.text.Spannable; import android.text.Spanned; import android.text.TextPaint; import android.text.style.SuggestionSpan; @@ -42,55 +64,215 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 super(TextViewActivity.class); } + @Override + protected void setUp() throws Exception { + super.setUp(); + getActivity(); + } + + private void setSuggestionSpan(SuggestionSpan span, int start, int end) { + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + textView.post( + () -> { + final Spannable text = (Spannable) textView.getText(); + text.setSpan(span, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE); + Selection.setSelection(text, (start + end) / 2); + }); + getInstrumentation().waitForIdleSync(); + } + + @SmallTest + public void testOnTextContextMenuItem() { + final String text = "abc def ghi"; + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION); + setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); + + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE)); + getInstrumentation().waitForIdleSync(); + + assertSuggestionsPopupIsDisplayed(); + } + + @SmallTest + public void testSelectionActionMode() { + final String text = "abc def ghi"; + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION); + setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); + + onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('e'))); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.replace)); + sleepForFloatingToolbarPopup(); + clickFloatingToolbarItem( + getActivity().getString(com.android.internal.R.string.replace)); + + assertSuggestionsPopupIsDisplayed(); + } + + @SmallTest + public void testInsertionActionMode() { + final String text = "abc def ghi"; + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION); + setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); + + onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e'))); + onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.replace)); + clickFloatingToolbarItem( + getActivity().getString(com.android.internal.R.string.replace)); + + assertSuggestionsPopupIsDisplayed(); + } + + private void showSuggestionsPopup() { + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE)); + getInstrumentation().waitForIdleSync(); + assertSuggestionsPopupIsDisplayed(); + } + + @SmallTest + public void testSuggestionItems() { + final String text = "abc def ghi"; + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION); + setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); + + showSuggestionsPopup(); + + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("DEF"); + assertSuggestionsPopupContainsItem("Def"); + assertSuggestionsPopupContainsItem( + getActivity().getString(com.android.internal.R.string.delete)); + + // Select an item. + clickSuggestionsPopupItem("DEF"); + assertSuggestionsPopupIsNotDisplayed(); + onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi"))); + + showSuggestionsPopup(); + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("def"); + assertSuggestionsPopupContainsItem("Def"); + assertSuggestionsPopupContainsItem( + getActivity().getString(com.android.internal.R.string.delete)); + + // Delete + clickSuggestionsPopupItem( + getActivity().getString(com.android.internal.R.string.delete)); + assertSuggestionsPopupIsNotDisplayed(); + onView(withId(R.id.textview)).check(matches(withText("abc ghi"))); + } + + @SmallTest + public void testMisspelled() { + final String text = "abc def ghi"; + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_MISSPELLED); + setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); + + showSuggestionsPopup(); + + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("DEF"); + assertSuggestionsPopupContainsItem("Def"); + assertSuggestionsPopupContainsItem( + getActivity().getString(com.android.internal.R.string.addToDictionary)); + assertSuggestionsPopupContainsItem( + getActivity().getString(com.android.internal.R.string.delete)); + + // Click "Add to dictionary". + clickSuggestionsPopupItem( + getActivity().getString(com.android.internal.R.string.addToDictionary)); + // TODO: Check if add to dictionary dialog is displayed. + } + + @SmallTest + public void testEasyCorrect() { + final String text = "abc def ghi"; + + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + new String[]{"DEF", "Def"}, + SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED); + setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); + + onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e'))); + + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("DEF"); + assertSuggestionsPopupContainsItem("Def"); + assertSuggestionsPopupContainsItem( + getActivity().getString(com.android.internal.R.string.delete)); + + // Select an item. + clickSuggestionsPopupItem("DEF"); + assertSuggestionsPopupIsNotDisplayed(); + onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi"))); + + onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e'))); + assertSuggestionsPopupIsNotDisplayed(); + + showSuggestionsPopup(); + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("def"); + assertSuggestionsPopupContainsItem("Def"); + assertSuggestionsPopupContainsItem( + getActivity().getString(com.android.internal.R.string.delete)); + } + @SmallTest - @Suppress public void testTextAppearanceInSuggestionsPopup() { - final Activity activity = getActivity(); + final String text = "abc def ghi"; - final String sampleText = "abc def ghi"; final String[] singleWordCandidates = {"DEF", "Def"}; - final SuggestionSpan singleWordSuggestionSpan = new SuggestionSpan(activity, - singleWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION); - final int singleWordSpanStart = 4; - final int singleWordSpanEnd = 7; - + final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(), + singleWordCandidates, SuggestionSpan.FLAG_MISSPELLED); final String[] multiWordCandidates = {"ABC DEF GHI", "Abc Def Ghi"}; - final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(activity, - multiWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION); - final int multiWordSpanStart = 0; - final int multiWordSpanEnd = 11; + final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(getActivity(), + multiWordCandidates, SuggestionSpan.FLAG_MISSPELLED); - TypedArray array = activity.obtainStyledAttributes(com.android.internal.R.styleable.Theme); - int id = array.getResourceId( + final TypedArray array = + getActivity().obtainStyledAttributes(com.android.internal.R.styleable.Theme); + final int id = array.getResourceId( com.android.internal.R.styleable.Theme_textEditSuggestionHighlightStyle, 0); array.recycle(); - - TextAppearanceSpan expectedSpan = new TextAppearanceSpan(activity, id); - TextPaint tmpTp = new TextPaint(); + final TextAppearanceSpan expectedSpan = new TextAppearanceSpan(getActivity(), id); + final TextPaint tmpTp = new TextPaint(); expectedSpan.updateDrawState(tmpTp); final int expectedHighlightTextColor = tmpTp.getColor(); final float expectedHighlightTextSize = tmpTp.getTextSize(); - - final EditText editText = (EditText) activity.findViewById(R.id.textview); - final Editor editor = editText.getEditorForTesting(); - assertNotNull(editor); - - // Request to show SuggestionsPopupWindow. - Runnable showSuggestionWindowRunner = new Runnable() { - @Override - public void run() { - SpannableStringBuilder ssb = new SpannableStringBuilder(); - ssb.append(sampleText); - ssb.setSpan(singleWordSuggestionSpan, singleWordSpanStart, singleWordSpanEnd, - Spanned.SPAN_INCLUSIVE_INCLUSIVE); - ssb.setSpan(multiWordSuggestionSpan, multiWordSpanStart, multiWordSpanEnd, - Spanned.SPAN_INCLUSIVE_INCLUSIVE); - editText.setText(ssb); - - Selection.setSelection(editText.getText(), singleWordSpanStart, singleWordSpanEnd); - editText.onTextContextMenuItem(TextView.ID_REPLACE); - } - }; + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); // In this test, the SuggestionsPopupWindow looks like // abc def ghi @@ -103,96 +285,74 @@ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2 // | DELETE | // ----------------- // *XX* means that XX is highlighted. - Runnable popupVaridator = new Runnable() { - @Override - public void run() { - Editor.SuggestionsPopupWindow popupWindow = - editor.getSuggestionsPopupWindowForTesting(); - assertNotNull(popupWindow); - - LinearLayout linearLayout = (LinearLayout) popupWindow.getContentViewForTesting(); - assertNotNull(linearLayout); - - ListView listView = (ListView)linearLayout.findViewById( - com.android.internal.R.id.suggestionContainer); - assertNotNull(listView); - - int childNum = listView.getChildCount(); - assertEquals(singleWordCandidates.length + multiWordCandidates.length, childNum); - - for (int i = 0; i < singleWordCandidates.length; ++i) { - TextView textView = (TextView) listView.getChildAt(i); - assertNotNull(textView); - - Spanned spanned = (Spanned) textView.getText(); - assertNotNull(spanned); - - // Check that the suggestion item order is kept. - String expectedText = "abc " + singleWordCandidates[i] + " ghi"; - assertEquals(expectedText, spanned.toString()); - - // Check that the text is highlighted with correct color and text size. - TextAppearanceSpan[] taSpan = spanned.getSpans(singleWordSpanStart, - singleWordSpanEnd, TextAppearanceSpan.class); - assertEquals(1, taSpan.length); - TextPaint tp = new TextPaint(); - taSpan[0].updateDrawState(tp); - assertEquals(expectedHighlightTextColor, tp.getColor()); - assertEquals(expectedHighlightTextSize, tp.getTextSize()); - - // Check only center word is highlighted. - assertEquals(singleWordSpanStart, spanned.getSpanStart(taSpan[0])); - assertEquals(singleWordSpanEnd, spanned.getSpanEnd(taSpan[0])); - } + for (int i = 0; i < 2; i++) { + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1); + setSuggestionSpan(multiWordSuggestionSpan, 0, text.length()); - for (int i = 0; i < multiWordCandidates.length; ++i) { - int indexInListView = singleWordCandidates.length + i; - TextView textView = (TextView) listView.getChildAt(indexInListView); - assertNotNull(textView); - - Spanned spanned = (Spanned) textView.getText(); - assertNotNull(spanned); - - // Check that the suggestion item order is kept. - assertEquals(multiWordCandidates[i], spanned.toString()); - - // Check that the text is highlighted with correct color and text size. - TextAppearanceSpan[] taSpan = spanned.getSpans( - 0, multiWordCandidates[i].length(), TextAppearanceSpan.class); - assertEquals(1, taSpan.length); - TextPaint tp = new TextPaint(); - taSpan[0].updateDrawState(tp); - assertEquals(expectedHighlightTextColor, tp.getColor()); - assertEquals(expectedHighlightTextSize, tp.getTextSize()); - - // Check the whole text is highlighted. - assertEquals(multiWordSpanStart, spanned.getSpanStart(taSpan[0])); - assertEquals(multiWordSpanEnd, spanned.getSpanEnd(taSpan[0])); - } + showSuggestionsPopup(); + assertSuggestionsPopupIsDisplayed(); + assertSuggestionsPopupContainsItem("abc DEF ghi"); + assertSuggestionsPopupContainsItem("abc Def ghi"); + assertSuggestionsPopupContainsItem("ABC DEF GHI"); + assertSuggestionsPopupContainsItem("Abc Def Ghi"); + assertSuggestionsPopupContainsItem( + getActivity().getString(com.android.internal.R.string.delete)); - TextView deleteButton = (TextView)linearLayout.findViewById( - com.android.internal.R.id.deleteButton); - assertEquals(View.VISIBLE, deleteButton.getWindowVisibility()); - } - }; + onSuggestionsPopup().check(new ViewAssertion() { + @Override + public void check(View view, NoMatchingViewException e) { + final ListView listView = (ListView) view.findViewById( + com.android.internal.R.id.suggestionContainer); + assertNotNull(listView); + final int childNum = listView.getChildCount(); + assertEquals(singleWordCandidates.length + multiWordCandidates.length, + childNum); - // Show the SuggestionWindow and verify the contents. - activity.runOnUiThread(showSuggestionWindowRunner); - getInstrumentation().waitForIdleSync(); - activity.runOnUiThread(popupVaridator); - - // Request to hide the SuggestionPopupWindow and wait until it is hidden. - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - editText.setText(""); - } - }); - getInstrumentation().waitForIdleSync(); + for (int j = 0; j < childNum; j++) { + final TextView suggestion = (TextView) listView.getChildAt(j); + assertNotNull(suggestion); + final Spanned spanned = (Spanned) suggestion.getText(); + assertNotNull(spanned); - // Show and verify the contents again. - activity.runOnUiThread(showSuggestionWindowRunner); - getInstrumentation().waitForIdleSync(); - activity.runOnUiThread(popupVaridator); + // Check that the suggestion item order is kept. + final String expectedText; + if (j < singleWordCandidates.length) { + expectedText = "abc " + singleWordCandidates[j] + " ghi"; + } else { + expectedText = multiWordCandidates[j - singleWordCandidates.length]; + } + assertEquals(expectedText, spanned.toString()); + + // Check that the text is highlighted with correct color and text size. + final TextAppearanceSpan[] taSpan = spanned.getSpans( + text.indexOf('d'), text.indexOf('f') + 1, TextAppearanceSpan.class); + assertEquals(1, taSpan.length); + TextPaint tp = new TextPaint(); + taSpan[0].updateDrawState(tp); + assertEquals(expectedHighlightTextColor, tp.getColor()); + assertEquals(expectedHighlightTextSize, tp.getTextSize()); + + // Check the correct part of the text is highlighted. + final int expectedStart; + final int expectedEnd; + if (j < singleWordCandidates.length) { + expectedStart = text.indexOf('d'); + expectedEnd = text.indexOf('f') + 1; + } else { + expectedStart = 0; + expectedEnd = text.length(); + } + assertEquals(expectedStart, spanned.getSpanStart(taSpan[0])); + assertEquals(expectedEnd, spanned.getSpanEnd(taSpan[0])); + } + } + }); + pressBack(); + onView(withId(R.id.textview)) + .inRoot(withDecorView(is(getActivity().getWindow().getDecorView()))) + .perform(clearText()); + } } } diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java index 923b8299a60a..edb749b95b10 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java @@ -16,6 +16,10 @@ package android.widget; + +import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemDisabled; +import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemEnabled; +import static android.widget.espresso.ContextMenuUtils.assertContextMenuIsNotDisplayed; import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles; import static android.widget.espresso.DragHandleUtils.onHandleView; import static android.widget.espresso.TextViewActions.mouseClickOnTextAtIndex; @@ -41,11 +45,9 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText; import com.android.frameworks.coretests.R; -import android.support.test.espresso.Espresso; import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.SmallTest; import android.view.MotionEvent; -import android.widget.espresso.ContextMenuUtils; /** * Tests mouse interaction of the TextView widget from an Activity @@ -57,7 +59,8 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2< } @Override - public void setUp() { + public void setUp() throws Exception { + super.setUp(); getActivity(); } @@ -102,28 +105,28 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2< onView(withId(R.id.textview)).perform(click()); onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text)); - ContextMenuUtils.assertContextMenuIsNotDisplayed(); + assertContextMenuIsNotDisplayed(); onView(withId(R.id.textview)).perform( mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY)); - ContextMenuUtils.assertContextMenuContainsItemDisabled( + assertContextMenuContainsItemDisabled( getActivity().getString(com.android.internal.R.string.copy)); - ContextMenuUtils.assertContextMenuContainsItemEnabled( + assertContextMenuContainsItemEnabled( getActivity().getString(com.android.internal.R.string.undo)); // Hide context menu. pressBack(); - ContextMenuUtils.assertContextMenuIsNotDisplayed(); + assertContextMenuIsNotDisplayed(); onView(withId(R.id.textview)).perform( mouseDragOnText(text.indexOf("c"), text.indexOf("h"))); onView(withId(R.id.textview)).perform( mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY)); - ContextMenuUtils.assertContextMenuContainsItemEnabled( + assertContextMenuContainsItemEnabled( getActivity().getString(com.android.internal.R.string.copy)); - ContextMenuUtils.assertContextMenuContainsItemEnabled( + assertContextMenuContainsItemEnabled( getActivity().getString(com.android.internal.R.string.undo)); // Hide context menu. @@ -133,9 +136,9 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2< onView(withId(R.id.textview)).perform( mouseClickOnTextAtIndex(text.indexOf("i"), MotionEvent.BUTTON_SECONDARY)); - ContextMenuUtils.assertContextMenuContainsItemDisabled( + assertContextMenuContainsItemDisabled( getActivity().getString(com.android.internal.R.string.copy)); - ContextMenuUtils.assertContextMenuContainsItemEnabled( + assertContextMenuContainsItemEnabled( getActivity().getString(com.android.internal.R.string.undo)); // Hide context menu. diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index ecf88f1558a1..67ffd2b0ca3b 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -19,7 +19,6 @@ package android.widget; import static android.support.test.espresso.action.ViewActions.longClick; import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles; import static android.widget.espresso.DragHandleUtils.onHandleView; -import static android.widget.espresso.FloatingToolbarEspressoUtils.onFloatingToolBarItem; import static android.widget.espresso.TextViewActions.clickOnTextAtIndex; import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText; import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex; @@ -31,9 +30,10 @@ import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIn import static android.widget.espresso.TextViewAssertions.hasSelection; import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed; import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed; -import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup; import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem; import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem; +import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem; +import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.action.ViewActions.pressKey; @@ -67,7 +67,8 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV } @Override - public void setUp() { + public void setUp() throws Exception { + super.setUp(); getActivity(); } @@ -256,7 +257,8 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV onView(withId(R.id.textview)).perform(typeTextIntoFocusedView("test")); onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1)); - onFloatingToolBarItem(withText(com.android.internal.R.string.cut)).perform(click()); + clickFloatingToolbarItem( + getActivity().getString(com.android.internal.R.string.cut)); onView(withId(R.id.textview)).perform(longClick()); sleepForFloatingToolbarPopup(); diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java index 0f7f359447ad..838f4db76165 100644 --- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java +++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java @@ -17,6 +17,7 @@ package android.widget.espresso; import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.RootMatchers.withDecorView; import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; @@ -24,6 +25,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.isRoot; import static android.support.test.espresso.matcher.ViewMatchers.withTagValue; import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.is; @@ -34,8 +36,6 @@ import android.support.test.espresso.NoMatchingViewException; import android.support.test.espresso.UiController; import android.support.test.espresso.ViewAction; import android.support.test.espresso.ViewInteraction; -import android.support.test.espresso.action.ViewActions; -import android.support.test.espresso.matcher.ViewMatchers; import android.view.View; import com.android.internal.widget.FloatingToolbar; @@ -90,7 +90,7 @@ public class FloatingToolbarEspressoUtils { final int id = com.android.internal.R.id.overflow; onView(allOf(withId(id), isDisplayed())) .inRoot(withDecorView(hasDescendant(withId(id)))) - .perform(ViewActions.click()); + .perform(click()); onView(isRoot()).perform(SLEEP); } @@ -106,7 +106,7 @@ public class FloatingToolbarEspressoUtils { */ public static void assertFloatingToolbarContainsItem(String itemLabel) { try{ - onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel)))); + onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel)))); } catch (AssertionError e) { try{ toggleOverflow(); @@ -115,7 +115,7 @@ public class FloatingToolbarEspressoUtils { throw e; } try{ - onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel)))); + onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel)))); } finally { toggleOverflow(); } @@ -138,6 +138,21 @@ public class FloatingToolbarEspressoUtils { } /** + * Click specified item on the floating tool bar. + * + * @param itemLabel label of the item. + */ + public static void clickFloatingToolbarItem(String itemLabel) { + try{ + onFloatingToolBarItem(withText(itemLabel)).check(matches(isDisplayed())); + } catch (AssertionError e) { + // Try to find the item in the overflow menu. + toggleOverflow(); + } + onFloatingToolBarItem(withText(itemLabel)).perform(click()); + } + + /** * ViewAction to sleep to wait floating toolbar's animation. */ private static final ViewAction SLEEP = new ViewAction() { diff --git a/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java new file mode 100644 index 000000000000..b5a96ae6c49a --- /dev/null +++ b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.widget.espresso; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.RootMatchers.withDecorView; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import org.hamcrest.Matcher; + +import android.support.test.espresso.NoMatchingRootException; +import android.support.test.espresso.NoMatchingViewException; +import android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.espresso.ViewInteraction; +import android.support.test.espresso.action.GeneralLocation; +import android.support.test.espresso.action.Press; +import android.support.test.espresso.action.Tap; +import android.view.View; + +public final class SuggestionsPopupwindowUtils { + private static final int id = com.android.internal.R.id.suggestionWindowContainer; + + private SuggestionsPopupwindowUtils() {}; + + public static ViewInteraction onSuggestionsPopup() { + return onView(withId(id)).inRoot(withDecorView(hasDescendant(withId(id)))); + } + + private static ViewInteraction onSuggestionsPopupItem(Matcher<View> matcher) { + return onView(matcher).inRoot(withDecorView(hasDescendant(withId(id)))); + } + + /** + * Asserts that the suggestions popup is displayed on screen. + * + * @throws AssertionError if the assertion fails + */ + public static void assertSuggestionsPopupIsDisplayed() { + onSuggestionsPopup().check(matches(isDisplayed())); + } + + /** + * Asserts that the suggestions popup is not displayed on screen. + * + * @throws AssertionError if the assertion fails + */ + public static void assertSuggestionsPopupIsNotDisplayed() { + try { + onSuggestionsPopup().check(matches(isDisplayed())); + } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) { + return; + } + throw new AssertionError("Suggestions popup is displayed"); + } + + /** + * Asserts that the suggestions popup contains the specified item. + * + * @param itemLabel label of the item. + * @throws AssertionError if the assertion fails + */ + public static void assertSuggestionsPopupContainsItem(String itemLabel) { + onSuggestionsPopupItem(withText(itemLabel)).check(matches(isDisplayed())); + } + + /** + * Click on the specified item in the suggestions popup. + * + * @param itemLabel label of the item. + */ + public static void clickSuggestionsPopupItem(String itemLabel) { + onSuggestionsPopupItem(withText(itemLabel)).perform(new SuggestionItemClickAction()); + } + + /** + * Click action to avoid checking ViewClickAction#getConstraints(). + * TODO: Use Espresso.onData instead of this. + */ + private static final class SuggestionItemClickAction implements ViewAction { + private final ViewClickAction mViewClickAction; + + public SuggestionItemClickAction() { + mViewClickAction = + new ViewClickAction(Tap.SINGLE, GeneralLocation.VISIBLE_CENTER, Press.FINGER); + } + + @Override + public Matcher<View> getConstraints() { + return isDisplayed(); + } + + @Override + public String getDescription() { + return mViewClickAction.getDescription(); + } + + @Override + public void perform(UiController uiController, View view) { + mViewClickAction.perform(uiController, view); + } + } +} diff --git a/media/java/android/media/DrmInitData.java b/media/java/android/media/DrmInitData.java index 06fe6ffb0d06..170d9de9d50a 100644 --- a/media/java/android/media/DrmInitData.java +++ b/media/java/android/media/DrmInitData.java @@ -28,6 +28,12 @@ import java.util.UUID; public abstract class DrmInitData { /** + * Prevent public constuctor access + */ + /* package private */ DrmInitData() { + } + + /** * Retrieves initialization data for a given DRM scheme, specified by its UUID. * * @param schemeUuid The DRM scheme's UUID. diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index 14609b21d19d..69912ab12098 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -43,9 +43,9 @@ <activity android:name=".LauncherActivity" - android:theme="@android:style/Theme.NoDisplay" - android:icon="@mipmap/ic_launcher_download" - android:label="@string/downloads_label"> + android:label="@string/downloads_label" + android:icon="@mipmap/ic_launcher_downloads" + android:theme="@android:style/Theme.NoDisplay"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> @@ -54,21 +54,21 @@ <activity android:name=".FilesActivity" - android:theme="@style/DocumentsTheme" - android:icon="@mipmap/ic_launcher_download" android:label="@string/downloads_label" - android:documentLaunchMode="intoExisting"> + android:icon="@mipmap/ic_launcher_downloads" + android:documentLaunchMode="intoExisting" + android:theme="@style/DocumentsTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> <intent-filter> - <action android:name="android.intent.action.VIEW_DOWNLOADS" /> + <action android:name="android.provider.action.BROWSE" /> <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.document/root" /> </intent-filter> <intent-filter> - <action android:name="android.provider.action.BROWSE" /> + <action android:name="android.intent.action.VIEW_DOWNLOADS" /> <category android:name="android.intent.category.DEFAULT" /> - <data android:mimeType="vnd.android.document/root" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> diff --git a/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_downloads.png Binary files differindex f958bbd3c255..f958bbd3c255 100644 --- a/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png +++ b/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_downloads.png diff --git a/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_downloads.png Binary files differindex f2e937663c2c..f2e937663c2c 100644 --- a/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png +++ b/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_downloads.png diff --git a/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_downloads.png Binary files differindex 4dc533638757..4dc533638757 100644 --- a/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png +++ b/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_downloads.png diff --git a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_downloads.png Binary files differindex 8716290969da..8716290969da 100644 --- a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png +++ b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_downloads.png diff --git a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_downloads.png Binary files differindex f5be21991761..f5be21991761 100644 --- a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png +++ b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_downloads.png diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml index 1660e26af4f8..cf0643d8ceaa 100644 --- a/packages/DocumentsUI/res/values/colors.xml +++ b/packages/DocumentsUI/res/values/colors.xml @@ -31,6 +31,7 @@ <color name="accent">@*android:color/accent_material_light</color> <color name="accent_dark">@*android:color/accent_material_dark</color> <color name="action_mode">@color/material_grey_400</color> + <color name="status_bar_color">@*android:color/material_blue_grey_950</color> <color name="band_select_background">#88ffffff</color> <color name="band_select_border">#44000000</color> diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml index 6590bbeda892..f0cab08723a8 100644 --- a/packages/DocumentsUI/res/values/config.xml +++ b/packages/DocumentsUI/res/values/config.xml @@ -20,13 +20,15 @@ <!-- Intentionally unset. Vendors should set this in an overlay. --> <string name="trusted_quick_viewer_package" translatable="false"></string> + + <!-- overridden for RTL langs --> <bool name="list_divider_inset_left">true</bool> - <!-- Indicates if the home directory should be hidden in the roots list, that is presented - in the drawer/left side panel ) --> - <bool name="home_root_hidden">true</bool> - <!-- Indicates if the advanced roots like internal storage should be shown in the roots list. - When enabled there is no menu option to toggle internal storage visibility. --> - <bool name="advanced_roots_shown">false</bool> + + <!-- Flags setup as productivity oriented in which case Downloads app will be presented + as Files app. Including showing of the Documents and "advanced" roots. --> + <bool name="productivity_device">false</bool> + <!-- Indicates if search view is taking the whole toolbar space --> <bool name="full_bar_search_view">true</bool> + </resources> diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml index a1eee3d1748d..eb99a0d6f879 100644 --- a/packages/DocumentsUI/res/values/strings.xml +++ b/packages/DocumentsUI/res/values/strings.xml @@ -18,9 +18,6 @@ <!-- Title of the documents application [CHAR LIMIT=32] --> <string name="app_label">Documents</string> - <!-- Title of the standalone files activity. [CHAR LIMIT=32] --> - <string name="files_label">Files</string> - <!-- Title of the standalone downloads activity. [CHAR LIMIT=32] --> <string name="downloads_label">Downloads</string> diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml index b0996aa6941c..9f09ebc480e5 100644 --- a/packages/DocumentsUI/res/values/styles.xml +++ b/packages/DocumentsUI/res/values/styles.xml @@ -30,6 +30,7 @@ <item name="android:colorAccent">@color/accent</item> <item name="colorActionMode">@color/action_mode</item> <item name="android:queryBackground">@color/menu_search_background</item> + <item name="android:statusBarColor">@color/status_bar_color</item> <item name="android:listDivider">@*android:drawable/list_divider_material</item> diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java index d6c742a00511..4ee37a5988cd 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java @@ -19,10 +19,9 @@ package com.android.documentsui; import static com.android.documentsui.Shared.DEBUG; import static com.android.documentsui.Shared.EXTRA_BENCHMARK; import static com.android.documentsui.State.ACTION_CREATE; +import static com.android.documentsui.State.ACTION_GET_CONTENT; import static com.android.documentsui.State.ACTION_OPEN; import static com.android.documentsui.State.ACTION_OPEN_TREE; -import static com.android.documentsui.State.ACTION_GET_CONTENT; -import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION; import static com.android.documentsui.State.MODE_GRID; import android.app.Activity; @@ -37,14 +36,12 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; -import android.os.MessageQueue; import android.os.MessageQueue.IdleHandler; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Root; import android.support.annotation.CallSuper; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; @@ -104,16 +101,6 @@ public abstract class BaseActivity extends Activity @CallSuper @Override public void onCreate(Bundle icicle) { - // This flag is being set here as a result of the bug. When the flag was set in the - // styles.xml keyboard was messing the layout of dialogs (create dir, rename). - // Attempts were made to keep the flag in the main theme and to override it in the dialog - // layout xml or to create separate style for dialog and assign it in styles.xml. - // None of this brought successful results. - // Setting the flag works here most probably because of the timing when it is set. Also the - // setting might not affect the dialogs that are created in new windows or it affects them - // in the different way that having this in the style. - getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); - // Record the time when onCreate is invoked for metric. mStartTime = new Date().getTime(); @@ -143,7 +130,6 @@ public abstract class BaseActivity extends Activity mSearchManager = new SearchViewManager(this, icicle); DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar); - Display.adjustToolbar(toolbar, this); setActionBar(toolbar); mNavigator = new NavigationView( mDrawer, @@ -228,8 +214,7 @@ public abstract class BaseActivity extends Activity includeState(state); // Advanced roots are shown by deafult without menu option if forced by config or intent. - state.showAdvanced = getResources().getBoolean(R.bool.advanced_roots_shown) - || intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false); + state.showAdvanced = Shared.shouldShowDeviceRoot(this, intent); // Menu option is shown for whitelisted intents if advanced roots are not shown by default. state.showAdvancedOption = !state.showAdvanced && (state.action == ACTION_OPEN || @@ -478,11 +463,11 @@ public abstract class BaseActivity extends Activity * Method can be overridden if the change of the behavior of the the child activity is needed. */ public Uri getDefaultRoot() { - return Shared.isHomeRootHidden(this) - ? DocumentsContract.buildRootUri("com.android.providers.downloads.documents", - "downloads") - : DocumentsContract.buildHomeUri(); - } + return Shared.shouldShowDocumentsRoot(this, getIntent()) + ? DocumentsContract.buildHomeUri() + : DocumentsContract.buildRootUri( + "com.android.providers.downloads.documents", "downloads"); + } void setDisplayAdvancedDevices(boolean display) { mState.showAdvanced = display; diff --git a/packages/DocumentsUI/src/com/android/documentsui/Display.java b/packages/DocumentsUI/src/com/android/documentsui/Display.java index d46a3eac94e9..8b13222dcce7 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Display.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Display.java @@ -20,8 +20,6 @@ import android.app.Activity; import android.content.Context; import android.graphics.Point; import android.util.TypedValue; -import android.view.WindowManager; -import android.widget.Toolbar; /* * Convenience class for getting display related attributes @@ -47,41 +45,12 @@ public final class Display { * Returns action bar height in raw pixels. */ public static float actionBarHeight(Context context) { - int height = 0; + int actionBarHeight = 0; TypedValue tv = new TypedValue(); if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { - height = TypedValue.complexToDimensionPixelSize(tv.data, + actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); } - return height; - } - - /* - * Returns status bar height in raw pixels. - */ - private static int statusBarHeight(Context context) { - int height = 0; - int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", - "android"); - if (resourceId > 0) { - height = context.getResources().getDimensionPixelSize(resourceId); - } - return height; - } - - /* - * Adjusts toolbar for the layout with translucent status bar. Increases the - * height of the toolbar and adds padding at the top to accommodate status bar visible above - * toolbar. - */ - public static void adjustToolbar(Toolbar toolbar, Activity activity) { - if ((activity.getWindow().getAttributes().flags - & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) { - int statusBarHeight = Display.statusBarHeight(activity); - toolbar.getLayoutParams().height = (int) (Display.actionBarHeight(activity) - + statusBarHeight); - toolbar.setPadding(toolbar.getPaddingLeft(), statusBarHeight, toolbar.getPaddingRight(), - toolbar.getPaddingBottom()); - } + return actionBarHeight; } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 5788420a053c..40b54d34eb03 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -203,8 +203,8 @@ public class DocumentsActivity extends BaseActivity { mState.action == ACTION_PICK_COPY_DESTINATION) { title = getResources().getString(R.string.title_save); } else { - // If all else fails, just call it "Downloads". - title = getResources().getString(R.string.downloads_label); + // If all else fails, just call it "Documents". + title = getResources().getString(R.string.app_label); } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java index 7a4099ae791e..14e6b69bfc19 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java @@ -84,7 +84,7 @@ abstract class DrawerController implements DrawerListener { View drawer = activity.findViewById(R.id.drawer_roots); Toolbar toolbar = (Toolbar) activity.findViewById(R.id.roots_toolbar); - Display.adjustToolbar(toolbar, activity); + drawer.getLayoutParams().width = calculateDrawerWidth(activity); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java index f07201172ff8..527eb7804fb7 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java @@ -180,7 +180,10 @@ public class FilesActivity extends BaseActivity { @Override public String getDrawerTitle() { - return getResources().getString(R.string.downloads_label); + Intent intent = getIntent(); + return (intent != null && intent.hasExtra(Intent.EXTRA_TITLE)) + ? intent.getStringExtra(Intent.EXTRA_TITLE) + : getTitle().toString(); } @Override diff --git a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java index 7930c28fc6c2..5cb6ca347896 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java @@ -87,9 +87,24 @@ public class LauncherActivity extends Activity { startActivity(intent); } - static final Intent createLaunchIntent(Context context) { - Intent intent = new Intent(context, FilesActivity.class); + static final Intent createLaunchIntent(Activity activity) { + Intent intent = new Intent(activity, FilesActivity.class); intent.setData(buildLaunchUri()); + + // Relay any config overrides bits present in the original intent. + Intent original = activity.getIntent(); + if (original != null) { + if (original.hasExtra(Shared.EXTRA_PRODUCTIVITY_MODE)) { + intent.putExtra( + Shared.EXTRA_PRODUCTIVITY_MODE, + original.getBooleanExtra(Shared.EXTRA_PRODUCTIVITY_MODE, false)); + } + if (original.hasExtra(Intent.EXTRA_TITLE)) { + intent.putExtra( + Intent.EXTRA_TITLE, + original.getStringExtra(Intent.EXTRA_TITLE)); + } + } return intent; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index 5f665c0e4dd5..8bbcc306af9a 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -17,8 +17,8 @@ package com.android.documentsui; import static com.android.documentsui.Shared.DEBUG; -import static com.android.documentsui.State.ACTION_OPEN_TREE; +import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; @@ -319,7 +319,8 @@ public class RootsFragment extends Fragment { for (final RootInfo root : roots) { final RootItem item = new RootItem(root); - if (root.isHome() && Shared.isHomeRootHidden(context)) { + if (root.isHome() && + !Shared.shouldShowDocumentsRoot(context, ((Activity) context).getIntent())) { continue; } else if (root.isLibrary()) { if (DEBUG) Log.d(TAG, "Adding " + root + " as library."); diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java index 2c60d4a3212f..1ba836a7fa4a 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java @@ -16,19 +16,16 @@ package com.android.documentsui; +import android.app.AlertDialog; import android.content.Context; +import android.content.Intent; import android.content.res.Configuration; +import android.provider.DocumentsContract; import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.Time; import android.view.WindowManager; -import com.android.documentsui.State.ActionType; - -import static com.android.documentsui.State.ACTION_OPEN_TREE; - -import android.app.AlertDialog; - import java.text.Collator; import java.util.ArrayList; import java.util.List; @@ -45,10 +42,21 @@ public final class Shared { "com.android.documentsui.PICK_COPY_DESTINATION"; /** + * Extra flag allowing app to be opened in productivity mode (less downloadsy). + * Useful developers and the likes. When set to true overrides the default + * config value of productivity_device. + */ + public static final String EXTRA_PRODUCTIVITY_MODE = "com.android.documentsui.PRODUCTIVITY"; + + /** * Extra boolean flag for {@link ACTION_PICK_COPY_DESTINATION}, which * specifies if the destination directory needs to create new directory or not. */ public static final String EXTRA_DIRECTORY_COPY = "com.android.documentsui.DIRECTORY_COPY"; + + /** + * Extra flag used to store the current stack so user opens in right spot. + */ public static final String EXTRA_STACK = "com.android.documentsui.STACK"; /** @@ -175,10 +183,33 @@ public final class Shared { } /* - * Indicates if the home directory should be hidden in the roots list. + * Returns true if app is running in "productivity mode". */ - public static boolean isHomeRootHidden(Context context) { - return context.getResources().getBoolean(R.bool.home_root_hidden); + public static boolean productivityMode(Context context) { + return context.getResources().getBoolean(R.bool.productivity_device); } + /* + * Returns true if app is running in "productivity mode". + */ + private static boolean isProductivityMode(Context context, Intent intent) { + return intent.getBooleanExtra( + Shared.EXTRA_PRODUCTIVITY_MODE, + context.getResources().getBoolean(R.bool.productivity_device)); + } + + /* + * Returns true if "Documents" root should be shown. + */ + public static boolean shouldShowDocumentsRoot(Context context, Intent intent) { + return isProductivityMode(context, intent); + } + + /* + * Returns true if device root should be shown. + */ + public static boolean shouldShowDeviceRoot(Context context, Intent intent) { + return isProductivityMode(context, intent) + || intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false); + } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java index c7d60e3d1133..f239eb45552b 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/State.java +++ b/packages/DocumentsUI/src/com/android/documentsui/State.java @@ -123,9 +123,6 @@ public class State implements android.os.Parcelable { /** Instance state for every shown directory */ public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>(); - /** UI selection */ - public Selection selectedDocuments = new Selection(); - /** Currently copying file */ public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<>(); @@ -202,7 +199,6 @@ public class State implements android.os.Parcelable { out.writeInt(external ? 1 : 0); DurableUtils.writeToParcel(out, stack); out.writeMap(dirState); - out.writeParcelable(selectedDocuments, 0); out.writeList(selectedDocumentsForCopy); out.writeList(excludedAuthorities); out.writeInt(openableOnly ? 1 : 0); @@ -233,7 +229,6 @@ public class State implements android.os.Parcelable { state.external = in.readInt() != 0; DurableUtils.readFromParcel(in, state.stack); in.readMap(state.dirState, loader); - state.selectedDocuments = in.readParcelable(loader); in.readList(state.selectedDocumentsForCopy, loader); in.readList(state.excludedAuthorities, loader); state.openableOnly = in.readInt() != 0; diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java index 630f35901b0c..1c85a8aba0b1 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -45,6 +45,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.os.Parcel; import android.os.Parcelable; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; @@ -226,7 +227,8 @@ public class DirectoryFragment extends Fragment mStateKey = buildStateKey(mRoot, mDocument); mQuery = args.getString(Shared.EXTRA_QUERY); mType = args.getInt(Shared.EXTRA_TYPE); - mSelection = args.getParcelable(Shared.EXTRA_SELECTION); + final Selection selection = args.getParcelable(Shared.EXTRA_SELECTION); + mSelection = selection != null ? selection : new Selection(); mSearchMode = args.getBoolean(Shared.EXTRA_SEARCH_MODE); mIconHelper = new IconHelper(context, MODE_GRID); @@ -290,14 +292,25 @@ public class DirectoryFragment extends Fragment outState.putParcelable(Shared.EXTRA_ROOT, mRoot); outState.putParcelable(Shared.EXTRA_DOC, mDocument); outState.putString(Shared.EXTRA_QUERY, mQuery); - outState.putParcelable(Shared.EXTRA_SELECTION, mSelection); - outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode); + // Workaround. To avoid crash, write only up to 512 KB of selection. + // If more files are selected, then the selection will be lost. + final Parcel parcel = Parcel.obtain(); + try { + mSelection.writeToParcel(parcel, 0); + if (parcel.dataSize() <= 512 * 1024) { + outState.putParcelable(Shared.EXTRA_SELECTION, mSelection); + } + } finally { + parcel.recycle(); + } + + outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode); } @Override public void onActivityResult(@RequestCode int requestCode, int resultCode, Intent data) { - switch(requestCode) { + switch (requestCode) { case REQUEST_COPY_DESTINATION: handleCopyResult(resultCode, data); break; @@ -490,24 +503,19 @@ public class DirectoryFragment extends Fragment @Override public void onSelectionChanged() { mSelectionManager.getSelection(mSelected); - TypedValue color = new TypedValue(); if (mSelected.size() > 0) { if (DEBUG) Log.d(TAG, "Maybe starting action mode."); if (mActionMode == null) { if (DEBUG) Log.d(TAG, "Yeah. Starting action mode."); mActionMode = getActivity().startActionMode(this); } - getActivity().getTheme().resolveAttribute(R.attr.colorActionMode, color, true); updateActionMenu(); } else { if (DEBUG) Log.d(TAG, "Finishing action mode."); if (mActionMode != null) { mActionMode.finish(); } - getActivity().getTheme().resolveAttribute( - android.R.attr.colorPrimaryDark, color, true); } - getActivity().getWindow().setStatusBarColor(color.data); if (mActionMode != null) { final String title = Shared.getQuantityString(getActivity(), diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java index f2949196f2a1..69f0e677eb04 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java @@ -22,8 +22,10 @@ import static com.android.documentsui.StubProvider.ROOT_1_ID; import android.app.DownloadManager; import android.app.DownloadManager.Request; import android.content.Context; +import android.content.Intent; import android.net.Uri; import android.os.RemoteException; +import android.provider.DocumentsContract; import android.support.test.uiautomator.Configurator; import android.support.test.uiautomator.UiObject; import android.test.suitebuilder.annotation.LargeTest; @@ -69,11 +71,10 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> { ROOT_1_ID); // Separate logic for "Documents" root, which presence depends on the config setting - boolean homeRootHidden = context.getResources().getBoolean(R.bool.home_root_hidden); - if (homeRootHidden) { - bots.roots.assertRootsAbsent("Documents"); - } else { + if (Shared.shouldShowDocumentsRoot(context, new Intent(DocumentsContract.ACTION_BROWSE))) { bots.roots.assertRootsPresent("Documents"); + } else { + bots.roots.assertRootsAbsent("Documents"); } } diff --git a/packages/Keyguard/res/drawable/ic_backspace_24dp.xml b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml index 47c8d14330c0..1e4022ea402b 100644 --- a/packages/Keyguard/res/drawable/ic_backspace_24dp.xml +++ b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml @@ -15,6 +15,7 @@ Copyright (C) 2014 The Android Open Source Project --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" + android:autoMirrored="true" android:height="24dp" android:viewportWidth="48.0" android:viewportHeight="48.0"> diff --git a/packages/Keyguard/res/values/attrs.xml b/packages/Keyguard/res/values/attrs.xml index 96a5bcc5fcbc..7cfe6316084f 100644 --- a/packages/Keyguard/res/values/attrs.xml +++ b/packages/Keyguard/res/values/attrs.xml @@ -32,6 +32,9 @@ <declare-styleable name="PasswordTextView"> <attr name="scaledTextSize" format="integer" /> + <attr name="android:gravity" /> + <attr name="dotSize" format="dimension" /> + <attr name="charPadding" format="dimension" /> </declare-styleable> <declare-styleable name="CarrierText"> diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java index ef8bb0be0d14..2ff7e121721a 100644 --- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java +++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java @@ -71,6 +71,10 @@ public class NumPadKey extends ViewGroup { } public NumPadKey(Context context, AttributeSet attrs, int defStyle) { + this(context, attrs, defStyle, R.layout.keyguard_num_pad_key); + } + + protected NumPadKey(Context context, AttributeSet attrs, int defStyle, int contentResource) { super(context, attrs, defStyle); setFocusable(true); @@ -92,7 +96,7 @@ public class NumPadKey extends ViewGroup { mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.keyguard_num_pad_key, this, true); + inflater.inflate(contentResource, this, true); mDigitText = (TextView) findViewById(R.id.digit_text); mDigitText.setText(Integer.toString(mDigit)); @@ -113,7 +117,11 @@ public class NumPadKey extends ViewGroup { } } - setBackground(mContext.getDrawable(R.drawable.ripple_drawable)); + a = context.obtainStyledAttributes(attrs, android.R.styleable.View); + if (!a.hasValueOrEmpty(android.R.styleable.View_background)) { + setBackground(mContext.getDrawable(R.drawable.ripple_drawable)); + } + a.recycle(); setContentDescription(mDigitText.getText().toString()); } diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java index 50e7ecb92ffc..6eea81bf4014 100644 --- a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java +++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java @@ -33,6 +33,7 @@ import android.provider.Settings; import android.text.InputType; import android.text.TextUtils; import android.util.AttributeSet; +import android.view.Gravity; import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -81,6 +82,7 @@ public class PasswordTextView extends View { * The raw text size, will be multiplied by the scaled density when drawn */ private final int mTextHeightRaw; + private final int mGravity; private ArrayList<CharState> mTextChars = new ArrayList<>(); private String mText = ""; private Stack<CharState> mCharPool = new Stack<>(); @@ -118,6 +120,12 @@ public class PasswordTextView extends View { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PasswordTextView); try { mTextHeightRaw = a.getInt(R.styleable.PasswordTextView_scaledTextSize, 0); + mGravity = a.getInt(R.styleable.PasswordTextView_android_gravity, Gravity.CENTER); + mDotSize = a.getDimensionPixelSize(R.styleable.PasswordTextView_dotSize, + getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size)); + mCharPadding = a.getDimensionPixelSize(R.styleable.PasswordTextView_charPadding, + getContext().getResources().getDimensionPixelSize( + R.dimen.password_char_padding)); } finally { a.recycle(); } @@ -125,9 +133,6 @@ public class PasswordTextView extends View { mDrawPaint.setTextAlign(Paint.Align.CENTER); mDrawPaint.setColor(0xffffffff); mDrawPaint.setTypeface(Typeface.create("sans-serif-light", 0)); - mDotSize = getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size); - mCharPadding = getContext().getResources().getDimensionPixelSize(R.dimen - .password_char_padding); mShowPassword = Settings.System.getInt(mContext.getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, 1) == 1; mAppearInterpolator = AnimationUtils.loadInterpolator(mContext, @@ -142,11 +147,23 @@ public class PasswordTextView extends View { @Override protected void onDraw(Canvas canvas) { float totalDrawingWidth = getDrawingWidth(); - float currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2; + float currentDrawPosition; + if ((mGravity & Gravity.START) != 0) { + if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + currentDrawPosition = getWidth() - getPaddingRight() - totalDrawingWidth; + } else { + currentDrawPosition = getPaddingLeft(); + } + } else { + currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2; + } int length = mTextChars.size(); Rect bounds = getCharBounds(); int charHeight = (bounds.bottom - bounds.top); - float yPosition = getHeight() / 2; + float yPosition = + (getHeight() - getPaddingBottom() - getPaddingTop()) / 2 + getPaddingTop(); + canvas.clipRect(getPaddingLeft(), getPaddingTop(), + getWidth()-getPaddingRight(), getHeight()-getPaddingBottom()); float charLength = bounds.right - bounds.left; for (int i = 0; i < length; i++) { CharState charState = mTextChars.get(i); diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml index a87afe0a77a9..248d0c05934a 100644 --- a/packages/PrintSpooler/res/layout/print_activity_controls.xml +++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml @@ -239,7 +239,8 @@ android:singleLine="true" android:ellipsize="end" android:visibility="visible" - android:inputType="textNoSuggestions"> + android:inputType="number" + android:digits="0123456789 ,-"> </com.android.printspooler.widget.CustomErrorEditText> </LinearLayout> diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index cde0fa3b4896..e7aebddf5aa8 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -62,7 +62,6 @@ import android.printservice.PrintServiceInfo; import android.provider.DocumentsContract; import android.text.Editable; import android.text.TextUtils; -import android.text.TextUtils.SimpleStringSplitter; import android.text.TextWatcher; import android.util.ArrayMap; import android.util.ArraySet; @@ -117,8 +116,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class PrintActivity extends Activity implements RemotePrintDocument.UpdateResultCallbacks, PrintErrorFragment.OnActionListener, PageAdapter.ContentCallbacks, @@ -165,22 +162,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat private static final int MIN_COPIES = 1; private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES); - private static final Pattern PATTERN_DIGITS = Pattern.compile("[\\d]+"); - - private static final Pattern PATTERN_ESCAPE_SPECIAL_CHARS = Pattern.compile( - "(?=[]\\[+&|!(){}^\"~*?:\\\\])"); - - private static final Pattern PATTERN_PAGE_RANGE = Pattern.compile( - "[\\s]*[0-9]+[\\-]?[\\s]*[0-9]*[\\s]*?(([,])" - + "[\\s]*[0-9]+[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*|[\\s]*)+"); - private boolean mIsOptionsUiBound = false; private final PrinterAvailabilityDetector mPrinterAvailabilityDetector = new PrinterAvailabilityDetector(); - private final SimpleStringSplitter mStringCommaSplitter = new SimpleStringSplitter(','); - private final OnFocusChangeListener mSelectAllOnFocusListener = new SelectAllOnFocusListener(); private PrintSpoolerProvider mSpoolerProvider; @@ -1493,9 +1479,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat cancelPrint(); } } else if (view == mMoreOptionsButton) { - // The selected pages is only applied once the user leaves the text field. A click - // on this button, does not count as leaving. - updateSelectedPagesFromTextField(); + if (mPageRangeEditText.getError() == null) { + // The selected pages is only applied once the user leaves the text field. A click + // on this button, does not count as leaving. + updateSelectedPagesFromTextField(); + } if (mCurrentPrinter != null) { startAdvancedPrintOptionsActivity(mCurrentPrinter); @@ -1918,42 +1906,10 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat } if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) { - List<PageRange> pageRanges = new ArrayList<>(); - mStringCommaSplitter.setString(mPageRangeEditText.getText().toString()); - - while (mStringCommaSplitter.hasNext()) { - String range = mStringCommaSplitter.next().trim(); - if (TextUtils.isEmpty(range)) { - continue; - } - final int dashIndex = range.indexOf('-'); - final int fromIndex; - final int toIndex; - - if (dashIndex > 0) { - fromIndex = Integer.parseInt(range.substring(0, dashIndex).trim()) - 1; - // It is possible that the dash is at the end since the input - // verification can has to allow the user to keep entering if - // this would lead to a valid input. So we handle this. - if (dashIndex < range.length() - 1) { - String fromString = range.substring(dashIndex + 1, range.length()).trim(); - toIndex = Integer.parseInt(fromString) - 1; - } else { - toIndex = fromIndex; - } - } else { - fromIndex = toIndex = Integer.parseInt(range) - 1; - } - - PageRange pageRange = new PageRange(Math.min(fromIndex, toIndex), - Math.max(fromIndex, toIndex)); - pageRanges.add(pageRange); - } - - PageRange[] pageRangesArray = new PageRange[pageRanges.size()]; - pageRanges.toArray(pageRangesArray); + PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info; + final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0; - return PageRangeUtils.normalize(pageRangesArray); + return PageRangeUtils.parsePageRanges(mPageRangeEditText.getText(), pageCount); } return PageRange.ALL_PAGES_ARRAY; @@ -2785,7 +2741,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat editText.setSelection(editText.getText().length()); } - if (view == mPageRangeEditText && !hasFocus) { + if (view == mPageRangeEditText && !hasFocus && mPageRangeEditText.getError() == null) { updateSelectedPagesFromTextField(); } } @@ -2805,18 +2761,12 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat @Override public void afterTextChanged(Editable editable) { final boolean hadErrors = hasErrors(); - String text = editable.toString(); - if (TextUtils.isEmpty(text)) { - if (mPageRangeEditText.getError() == null) { - mPageRangeEditText.setError(""); - updateOptionsUi(); - } - return; - } + PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info; + final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0; + PageRange[] ranges = PageRangeUtils.parsePageRanges(editable, pageCount); - String escapedText = PATTERN_ESCAPE_SPECIAL_CHARS.matcher(text).replaceAll("////"); - if (!PATTERN_PAGE_RANGE.matcher(escapedText).matches()) { + if (ranges.length == 0) { if (mPageRangeEditText.getError() == null) { mPageRangeEditText.setError(""); updateOptionsUi(); @@ -2824,30 +2774,6 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat return; } - PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info; - final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0; - - // The range - Matcher matcher = PATTERN_DIGITS.matcher(text); - while (matcher.find()) { - String numericString = text.substring(matcher.start(), matcher.end()).trim(); - if (TextUtils.isEmpty(numericString)) { - continue; - } - final int pageIndex = Integer.parseInt(numericString); - if (pageIndex < 1 || pageIndex > pageCount) { - if (mPageRangeEditText.getError() == null) { - mPageRangeEditText.setError(""); - updateOptionsUi(); - } - return; - } - } - - // We intentionally do not catch the case of the from page being - // greater than the to page. When computing the requested pages - // we just swap them if necessary. - if (mPageRangeEditText.getError() != null) { mPageRangeEditText.setError(null); updateOptionsUi(); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java index cee16c8b29e9..fcc9f6a36171 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java @@ -18,12 +18,11 @@ package com.android.printspooler.ui; import android.app.Activity; import android.app.LoaderManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentSender.SendIntentException; import android.content.Loader; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager.NameNotFoundException; import android.database.DataSetObserver; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -34,6 +33,7 @@ import android.print.PrinterInfo; import android.printservice.PrintServiceInfo; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; import android.util.TypedValue; import android.view.ContextMenu; @@ -80,8 +80,8 @@ public final class SelectPrinterActivity extends Activity implements private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE"; - /** If there are any enabled print services */ - private boolean mHasEnabledPrintServices; + /** The currently enabled print services by their ComponentName */ + private ArrayMap<ComponentName, PrintServiceInfo> mEnabledPrintServices; private PrinterRegistry mPrinterRegistry; @@ -100,6 +100,8 @@ public final class SelectPrinterActivity extends Activity implements setContentView(R.layout.select_printer_activity); + mEnabledPrintServices = new ArrayMap<>(); + mPrinterRegistry = new PrinterRegistry(this, null, LOADER_ID_PRINT_REGISTRY, LOADER_ID_PRINT_REGISTRY_INT); @@ -317,7 +319,7 @@ public final class SelectPrinterActivity extends Activity implements } TextView titleView = (TextView) findViewById(R.id.title); View progressBar = findViewById(R.id.progress_bar); - if (!mHasEnabledPrintServices) { + if (mEnabledPrintServices.size() > 0) { titleView.setText(R.string.print_no_print_services); progressBar.setVisibility(View.GONE); } else if (adapter.getUnfilteredCount() <= 0) { @@ -346,11 +348,16 @@ public final class SelectPrinterActivity extends Activity implements @Override public void onLoadFinished(Loader<List<PrintServiceInfo>> loader, - List<PrintServiceInfo> data) { - if (data == null || data.isEmpty()) { - mHasEnabledPrintServices = false; - } else { - mHasEnabledPrintServices = true; + List<PrintServiceInfo> services) { + mEnabledPrintServices.clear(); + + if (services != null && !services.isEmpty()) { + final int numServices = services.size(); + for (int i = 0; i < numServices; i++) { + PrintServiceInfo service = services.get(i); + + mEnabledPrintServices.put(service.getComponentName(), service); + } } onPrintServicesUpdate(); @@ -533,14 +540,12 @@ public final class SelectPrinterActivity extends Activity implements CharSequence title = printer.getName(); Drawable icon = printer.loadIcon(SelectPrinterActivity.this); - CharSequence printServiceLabel; - try { - PackageInfo packageInfo = getPackageManager().getPackageInfo( - printer.getId().getServiceName().getPackageName(), 0); + PrintServiceInfo service = mEnabledPrintServices.get(printer.getId().getServiceName()); - printServiceLabel = packageInfo.applicationInfo.loadLabel(getPackageManager()); - } catch (NameNotFoundException e) { - printServiceLabel = null; + CharSequence printServiceLabel = null; + if (service != null) { + printServiceLabel = service.getResolveInfo().loadLabel(getPackageManager()) + .toString(); } CharSequence description = printer.getDescription(); diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java index 2b317b3cbef0..7425c033a7a4 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java +++ b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java @@ -18,7 +18,9 @@ package com.android.printspooler.util; import android.print.PageRange; import android.print.PrintDocumentInfo; +import android.util.Pair; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -155,6 +157,167 @@ public final class PageRangeUtils { } /** + * Return the next position after {@code pos} that is not a space character. + * + * @param s The string to parse + * @param pos The starting position + * + * @return The position of the first space character + */ + private static int readWhiteSpace(CharSequence s, int pos) { + while (pos < s.length() && s.charAt(pos) == ' ') { + pos++; + } + + return pos; + } + + /** + * Read a number from a string at a certain position. + * + * @param s The string to parse + * @param pos The starting position + * + * @return The position after the number + the number read or null if the number was not found + */ + private static Pair<Integer, Integer> readNumber(CharSequence s, int pos) { + Integer result = 0; + while (pos < s.length() && s.charAt(pos) >= '0' && s.charAt(pos) <= '9') { + // Number cannot start with 0 + if (result == 0 && s.charAt(pos) == '0') { + break; + } + result = result * 10 + (s.charAt(pos) - '0'); + // Abort on overflow + if (result < 0) { + break; + } + pos++; + } + + // 0 is not a valid page number + if (result == 0) { + return new Pair<>(pos, null); + } else { + return new Pair<>(pos, result); + } + } + + /** + * Read a single character from a string at a certain position. + * + * @param s The string to parse + * @param pos The starting position + * @param expectedChar The character to read + * + * @return The position after the character + the character read or null if the character was + * not found + */ + private static Pair<Integer, Character> readChar(CharSequence s, int pos, char expectedChar) { + if (pos < s.length() && s.charAt(pos) == expectedChar) { + return new Pair<>(pos + 1, expectedChar); + } else { + return new Pair<>(pos, null); + } + } + + /** + * Read a page range character from a string at a certain position. + * + * @param s The string to parse + * @param pos The starting position + * @param maxPageNumber The highest page number to accept. + * + * @return The position after the page range + the page range read or null if the page range was + * not found + */ + private static Pair<Integer, PageRange> readRange(CharSequence s, int pos, int maxPageNumber) { + Pair<Integer, Integer> retInt; + Pair<Integer, Character> retChar; + + Character comma; + if (pos == 0) { + // When we reading the first range, we do not want to have a comma + comma = ','; + } else { + retChar = readChar(s, pos, ','); + pos = retChar.first; + comma = retChar.second; + } + + pos = readWhiteSpace(s, pos); + + retInt = readNumber(s, pos); + pos = retInt.first; + Integer start = retInt.second; + + pos = readWhiteSpace(s, pos); + + retChar = readChar(s, pos, '-'); + pos = retChar.first; + Character separator = retChar.second; + + pos = readWhiteSpace(s, pos); + + retInt = readNumber(s, pos); + pos = retInt.first; + Integer end = retInt.second; + + pos = readWhiteSpace(s, pos); + + if (comma != null && + // range, maybe unbounded + ((separator != null && (start != null || end != null)) || + // single page + (separator == null && start != null && end == null))) { + if (start == null) { + start = 1; + } + + if (end == null) { + if (separator == null) { + end = start; + } else { + end = maxPageNumber; + } + } + + if (start <= end && start >= 1 && end <= maxPageNumber) { + return new Pair<>(pos, new PageRange(start - 1, end - 1)); + } + } + + return new Pair<>(pos, null); + } + + /** + * Parse a string into an array of page ranges. + * + * @param s The string to parse + * @param maxPageNumber The highest page number to accept. + * + * @return The parsed ranges or null if the string could not be parsed. + */ + public static PageRange[] parsePageRanges(CharSequence s, int maxPageNumber) { + ArrayList<PageRange> ranges = new ArrayList<>(); + + int pos = 0; + while (pos < s.length()) { + Pair<Integer, PageRange> retRange = readRange(s, pos, maxPageNumber); + + if (retRange.second == null) { + ranges.clear(); + break; + } + + ranges.add(retRange.second); + pos = retRange.first; + } + + return PageRangeUtils.normalize(ranges.toArray(new PageRange[ranges.size()])); + } + + /** * Offsets a the start and end of page ranges with the given value. * * @param pageRanges The page ranges to offset. diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 9cf9dc979c2a..c44f0d06bd65 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – sowat <xliff:g id="TIME">%2$s</xliff:g> oor"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol op WS"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol oor USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol vanaf draadloos"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laai tans op WS"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laai tans oor USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laai tans draadloos"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Laai nie"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laai nie"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Vol"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 40e5a31c87fc..cd05135def5c 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ይህ ባህሪ የሙከራ ነውና አፈጻጸም ላይ ተጽዕኖ ሊኖረው ይችላል።"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> ገደማ ቀርቷል"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ገደማ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> እስከሚሞላ ድረስ"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በኤሲ ላይ እስከሚሞላ ድረስ"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በዩኤስቢ ላይ እስከሚሞላ ድረስ"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በገመድ አልባ ላይ እስከሚሞላ ድረስ"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"ያልታወቀ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"በኤሲ ሃይል በመሙላት ላይ"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"በዩኤስቢ ሃይል በመሙላት ላይ"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"በገመድ አልባ ሃይል በመሙላት ላይ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ባትሪ እየሞላ አይደለም"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ኃይል እየሞላ አይደለም"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ሙሉነው"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index e21b02c706df..b3f55eb03fd1 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"هذه الميزة تجريبية وقد تؤثر في الأداء."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"يتبقى <xliff:g id="TIME">%1$s</xliff:g> تقريبًا"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال باستخدام التيار المتردد"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال عبر USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال بالشحن اللاسلكي"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"غير معروف"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"شحن"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"جارٍ الشحن بتيار متردد"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"جارٍ الشحن عبر USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"جارٍ الشحن لاسلكيًا"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"لا يتم الشحن"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"لا يتم الشحن"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ممتلئة"</string> diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml index ca06e664fca9..9a099aff3a7f 100644 --- a/packages/SettingsLib/res/values-az-rAZ/strings.xml +++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya eksperimentaldır və performansa təsir edə bilər."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> dolana qədər"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC üzərindən dolana qədər"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB üzərindən dolana qədər"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> naqilsiz üzərindən dolana qədər"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Dəyişən cərəyanda qidalanır"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB üzərindən qidalanır"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Naqilsiz qidalanır"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Doldurulmur"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Enerji doldurulmur"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Tam"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 4bd9b0381cac..85b6ac2fb13b 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na performanse."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo oko <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni punjačem"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni preko USB-a"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni bežično"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Punjenje preko punjača"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string> diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml index a70fc6996b97..c8098ec22300 100644 --- a/packages/SettingsLib/res/values-be-rBY/strings.xml +++ b/packages/SettingsLib/res/values-be-rBY/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Гэтая функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Засталося прыблізна <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося прыблізна <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі ад сеткі пер. току"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі па USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўн. зарадкі бесправадным шляхам"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Невядома"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарадка"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зар. ад сеткі пер. току"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарадка па USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бесправадная зарадка"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не зараджаецца"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не зараджаецца"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Поўная"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index e0641b1b45ac..35b24bf23129 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Прибл. оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – приблизително оставащо време: <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане при променлив ток"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане през USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно безжично зареждане"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарежда се"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зареждане при AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зареждане през USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично зареждане"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не се зарежда"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се зарежда"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Пълна"</string> diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml index 5ca7d033ccac..14c2c9549fc5 100644 --- a/packages/SettingsLib/res/values-bn-rBD/strings.xml +++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml @@ -296,17 +296,26 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"এই বৈশিষ্ট্যটি পরীক্ষামূলক এবং এটি কার্য-সম্পাদনা প্রভাবিত করতে পারে।"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"প্রায় <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - আনুমানিক <xliff:g id="TIME">%2$s</xliff:g> বাকি আছে"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string> + <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ACতে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string> + <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB এর মাধ্যমে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string> + <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেতার যোগে সম্পূর্ণ হতে <xliff:g id="TIME">%2$s</xliff:g> বাকি"</string> + <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"অজানা"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC তে চার্জ হচ্ছে"</string> + <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB এর মাধ্যমে চার্জ হচ্ছে"</string> + <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"তারবিহীনভাবে চার্জ হচ্ছে"</string> + <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"চার্জ হচ্ছে"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"চার্জ হচ্ছে না"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"চার্জ হচ্ছে না"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"পূর্ণ"</string> diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml index ce0f40994906..f9c7fcad3907 100644 --- a/packages/SettingsLib/res/values-bs-rBA/strings.xml +++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna te može utjecati na performanse."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo vreme je otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja na el. napajanju"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije preko USB-a"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije bežičnim punjenjem"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Puni se"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Puni se na punjaču"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 5106f5bd4f77..a07074071b55 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -296,17 +296,26 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Aquesta funció és experimental i pot afectar el rendiment."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Temps restant aproximat: <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: falten aproximadament <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g>; temps restant: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string> + <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega per CA"</string> + <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega per USB"</string> + <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega sense fil"</string> + <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconegut"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"S\'està carregant"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Càrrega: corr. alt."</string> + <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"S\'està carregant"</string> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Càrrega per USB"</string> + <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"S\'està carregant"</string> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Càrrega sense fils"</string> + <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"S\'està carregant"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No s\'està carregant"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 3d3dd6fb1877..040c9f06255f 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g> (přibližně)"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá přibližně <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití ze zásuvky"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití přes USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití bezdrátově"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjení z adaptéru"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjení přes USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrátové nabíjení"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíjí se"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíjí se"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 1f354b7f1bea..ddad673dfc86 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -296,17 +296,26 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funktion er eksperimentel og kan påvirke ydeevnen."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> tilbage"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tilbage"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tilbage"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet"</string> + <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med adapter"</string> + <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med USB"</string> + <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til fuldt opladet med trådløs"</string> + <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukendt"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Oplader"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Opladning med AC"</string> + <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Oplader"</string> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladning via USB"</string> + <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Oplader"</string> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Trådløs opladning"</string> + <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Oplader"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Oplader ikke"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Oplader ikke"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fuld"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 404b72b24dc8..514228faea41 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierbei handelt es sich um eine experimentelle Funktion. Dies kann sich auf die Leistung auswirken."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g> verbleibend"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch etwa <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei Stromanschluss voll in <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – über USB voll in <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei kabellosem Laden voll in <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laden über Netzteil"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laden über USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kabelloses Laden"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Wird nicht geladen"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wird nicht geladen"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Voll"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 52988f67741b..8df693ae3b54 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Αυτή η λειτουργία είναι πειραματική και ενδεχομένως να επηρεάσει τις επιδόσεις."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Απομένουν περίπου <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - απομένουν περίπου <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση με φορτιστή AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση μέσω USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη ασύρματη φόρτιση"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Άγνωστο"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Φόρτιση"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Φόρτιση με AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Φόρτιση μέσω USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ασύρματη φόρτιση"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Δεν φορτίζει"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Δεν φορτίζει"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Πλήρης"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index b2df062b6f11..466291aff7ff 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index b2df062b6f11..466291aff7ff 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index b2df062b6f11..466291aff7ff 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"This feature is experimental and may affect performance."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Approx. <xliff:g id="TIME">%1$s</xliff:g> left"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Not charging"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Not charging"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Full"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index dd7ee4d6823d..9bc2cf414d25 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Falta <xliff:g id="TIME">%1$s</xliff:g> aproximadamente"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g>: alrededor de <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por CA"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga inalámbrica"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carga en CA"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carga con USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carga inalámbrica"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando."</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se realiza la carga"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Cargado"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 0cc6cb6fa83c..ec0cafea2792 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -34,7 +34,7 @@ <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string> <string name="wifi_connected_no_internet" msgid="3149853966840874992">"Conexión sin Internet"</string> - <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectada"</string> + <string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string> <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string> <string name="bluetooth_connecting" msgid="8555009514614320497">"Estableciendo conexión…"</string> <string name="bluetooth_connected" msgid="6038755206916626419">"Conectado"</string> @@ -296,17 +296,26 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar al rendimiento."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Tiempo restante (aproximado): <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quedan <xliff:g id="TIME">%2$s</xliff:g> aproximadamente"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tiempo restante: <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería"</string> + <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería con CA"</string> + <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería por USB"</string> + <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la batería con Wi-Fi"</string> + <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Cargando en CA"</string> + <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Cargando"</string> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string> + <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Cargando"</string> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando de forma inalámbrica"</string> + <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Cargando"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"No se está cargando"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"No se está cargando"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string> diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml index a275b1a8c9af..29a1aea1e20d 100644 --- a/packages/SettingsLib/res/values-et-rEE/strings.xml +++ b/packages/SettingsLib/res/values-et-rEE/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"See funktsioon on katseline ja võib mõjutada toimivust."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Umbes <xliff:g id="TIME">%1$s</xliff:g> on jäänud"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – jäänud on umbes <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (vahelduvvool)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (USB)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (juhtmeta laad.)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laad. vahelduvv.-v."</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laadimine USB kaudu"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Juhtmevaba laadimine"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ei lae"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei lae"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Täis"</string> diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml index 2556224e0dce..4f55e350fbe0 100644 --- a/packages/SettingsLib/res/values-eu-rES/strings.xml +++ b/packages/SettingsLib/res/values-eu-rES/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> inguru guztiz kargatu arte"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> inguru. <xliff:g id="TIME">%2$s</xliff:g> geratzen d(ir)a"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> korrontearen bidez guztiz kargatu arte"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB bidez guztiz kargatu arte"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> haririk gabe guztiz kargatu arte"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzea"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"KA bidez kargatzen"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB bidez kargatzen"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hari gabe kargatzen"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ez da kargatzen ari"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ez da kargatzen ari"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Beteta"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 1e67182a4bda..e9d63fddd521 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"این قابلیت آزمایشی است و ممکن است عملکرد را تحت تأثیر قرار دهد."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> باقی مانده است"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی مانده است"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل با جریان متناوب"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل از طریق USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل بهطور بیسیم"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"ناشناس"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"در حال شارژ شدن"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"شارژ با جریان متناوب"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"شارژ از طریق USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"شارژ به صورت بیسیم"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"شارژ نمیشود"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"شارژ نمیشود"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"پر"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 3d8ac9887163..5531d270e1f3 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (laturilataus)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (USB-lataus)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (WiFi-lataus)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laturilataus"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-lataus"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Langaton lataus"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ei laturissa"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ei laturissa"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Täynnä"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 4eb3a427d0d4..df6bdc64b394 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut toucher les performances."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> %% – Temps restant : environ <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (charge complète sur c.a. dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% par USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% avec chargeur sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge (c.a.)"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge par USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"N\'est pas en charge"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"N\'est pas en charge"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Pleine"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index efb10ecedeb6..ee40b2a42ff2 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>."</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <xliff:g id="TIME">%2$s</xliff:g> environ"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sur secteur dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% via USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge sur secteur"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge via USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Pas en charge"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Débranchée"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"pleine"</string> diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml index 3d61e215208c..4a0451e42aad 100644 --- a/packages/SettingsLib/res/values-gl-rES/strings.xml +++ b/packages/SettingsLib/res/values-gl-rES/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Duración aproximada de <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - faltan aproximadamente <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con CA"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga co modo sen fíos"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Cargando con CA"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando sen fíos"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Non se está cargando"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non está cargando"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string> diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml index 628b4be81c46..becda2852f46 100644 --- a/packages/SettingsLib/res/values-gu-rIN/strings.xml +++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"અંદાજે. <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - આશરે <xliff:g id="TIME">%2$s</xliff:g> બાકી"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"સંપૂર્ણ થવામાં <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>, AC પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>, USB પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> વાયરલેસ દ્વારા પૂર્ણ થાય ત્યાં સુધી"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC પર ચાર્જિંગ"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB થી ચાર્જિંગ"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"વાયરલેસથી ચાર્જિંગ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ચાર્જ થઈ રહ્યું નથી"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ચાર્જ થઈ રહ્યું નથી"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"પૂર્ણ"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 047c7db08f80..6dffdd9d7269 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यह सुविधा प्रायोगिक है और निष्पादन को प्रभावित कर सकती है."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> शेष"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग <xliff:g id="TIME">%2$s</xliff:g> शेष"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूरी होने तक"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC पर पूरी होने तक"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB पर पूरी होने तक"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेस से पूरी होने तक"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हो रही है"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC से चार्ज हो रही"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB पर चार्ज हो रही"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस रूप से चार्ज हो रही"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज नहीं हो रही है"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज नहीं हो रही है"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"पूरी"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index f5ad6d2323a1..1edb01544831 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -296,17 +296,26 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova je značajka eksperimentalna i može utjecati na performanse."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još približno <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Još <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – još približno <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – još <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string> + <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti strujnim napajanjem"</string> + <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti putem USB-a"</string> + <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti bežičnim putem"</string> + <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Punjenje punjačem"</string> + <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Punjenje"</string> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje putem USB-a"</string> + <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Punjenje"</string> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string> + <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Punjenje"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ne puni se"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ne puni se"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puna"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 7279c9cfc2f8..060599cfa10e 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -296,17 +296,26 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ez egy kísérleti funkció, és hatással lehet a teljesítményre."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kb. <xliff:g id="TIME">%1$s</xliff:g> van hátra"</string> + <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> van hátra"</string> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – kb. <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string> + <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> van hátra"</string> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttség eléréséig"</string> + <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig hálózatról"</string> + <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes feltöltésig USB-ről"</string> + <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig vezeték nélkül"</string> + <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ismeretlen"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Töltés"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Hálózati töltés"</string> + <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Töltés"</string> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-s töltés"</string> + <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Töltés"</string> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Nem vezetékes töltés"</string> + <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Töltés"</string> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nem tölt"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nem töltődik"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Feltöltve"</string> diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml index 23d83a272ce4..63c433668aea 100644 --- a/packages/SettingsLib/res/values-hy-rAM/strings.xml +++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Սա փորձնական գործառույթ է և կարող է ազդել աշխատանքի վրա:"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Մնացել է մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - մնաց մոտավորապես <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը հոսանքից"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը USB-ով"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը անլար ցանցից"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Անհայտ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Լիցքավորում"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Լիցքավորում AC-ով"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Լիցքավորում USB-ով"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Անլար լիցքավորում"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Չի լիցքավորվում"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Չի լիցքավորվում"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Լիցքավորված"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 24fd0f17c4b9..c86c76842eaa 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira tersisa <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira tersisa. <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh pada AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh melalui USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh dari nirkabel"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengisi daya pada AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Isi daya lewat USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Isi daya nirkabel"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengisi daya"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengisi daya"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string> diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml index e22dbe036782..1fc0dc0763da 100644 --- a/packages/SettingsLib/res/values-is-rIS/strings.xml +++ b/packages/SettingsLib/res/values-is-rIS/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu með hleðslutæki"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu í gegnum USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu þráðlaust"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Hleðslutæki tengt"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Hleður um USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hleður þráðlaust"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ekki í hleðslu"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ekki í hleðslu"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fullhlaðin"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 84ff78a4a21c..78cd29b854b0 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Circa <xliff:g id="TIME">%1$s</xliff:g> rimanenti"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tempo rimanente: <xliff:g id="TIME">%2$s</xliff:g> circa"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite CA"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lla carica completa con wireless"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"In carica tramite CA"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"In carica tramite USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"In carica, wireless"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Non in carica"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Non in carica"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Carica"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 74ea37200f52..16e0f44d8e6f 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"נשארו <xliff:g id="TIME">%1$s</xliff:g> בערך"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> בקירוב עד לסיום"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בזרם חילופין"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי ב-USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בטעינה אלחוטית"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"טוען"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"טוען בזרם חילופין"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"טוען ב-USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"טוען באופן אלחוטי"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"לא בטעינה"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"לא טוען"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"מלא"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 2556d994c469..ce405dffd86a 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"この機能は試験運用機能であり、パフォーマンスに影響することがあります。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"あと約 <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 残り約<xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(AC)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(USB)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(ワイヤレス)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACで充電しています"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBで充電しています"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"無線で充電しています"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"充電していません"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"充電していません"</string> <!-- String.format failed for translation --> diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml index 29e9459e241b..20a1d2a351ae 100644 --- a/packages/SettingsLib/res/values-ka-rGE/strings.xml +++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ეს ფუნქცია საცდელია და შეიძლება გავლენა იქონიოს შესრულებაზე."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"დარჩენილია დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"დაახლ. <xliff:g id="LEVEL">%1$s</xliff:g> დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> სრულ დატენვამდე"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ელკვებით სრულ დატენვამდე"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB-თი სრულ დატენვამდე"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> უსადენოდან სრულ დატენვამდე"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"უცნობი"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"იტენება"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"დატენვა ელკვებაზე"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"დატენვა USB-ზე"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"დატენვა უსადენოდ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"არ იტენება"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"არ იტენება"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ბატარეა დატენილია"</string> diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml index fdd3f955e930..e71c8d0ca6d4 100644 --- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml +++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бұл мүмкіндік эксперименттік болып табылады және өнімділікке әсер етуі мүмкін."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> қалды"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - айнымалы токпен толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB арқылы толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - сымсыз толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгісіз"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядталуда"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Айнымалы токпен зар."</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB арқылы зарядтау"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Сымсыз зарядтау"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Зарядталу орындалып жатқан жоқ"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Зарядталып тұрған жоқ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Толық"</string> diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml index 2cafa294f00e..687b71b17ade 100644 --- a/packages/SettingsLib/res/values-km-rKH/strings.xml +++ b/packages/SettingsLib/res/values-km-rKH/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"លក្ខណៈនេះគឺជាការពិសោធន៍ ហើយអាចប៉ះពាល់ការអនុវត្ត។"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"បដិសេធដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"នៅសល់ប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ប្រហែល <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញ"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញរចន្តឆ្លាស់"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញតាមយូអេសប៊ី"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញពីឥតខ្សែ"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"មិនស្គាល់"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"កំពុងបញ្ចូលថ្ម"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"បញ្ចូលថ្មតាម AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"បញ្ចូលថ្មតាមយូអេសប៊ី"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"បញ្ចូលថ្មដោយឥតខ្សែ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"មិនកំពុងបញ្ចូលថ្ម"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"មិនបញ្ចូលថ្ម"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ពេញ"</string> diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml index 6d13b354d8c0..713d9b3a73af 100644 --- a/packages/SettingsLib/res/values-kn-rIN/strings.xml +++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ಇದು ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಕಾರ್ಯಕ್ಷಮತೆ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"ಸುಮಾರು <xliff:g id="TIME">%1$s</xliff:g> ಉಳಿದಿದೆ"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"ಸುಮಾರು <xliff:g id="LEVEL">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g> ಉಳಿದಿದೆ"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ನಲ್ಲಿ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ಮೂಲಕ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ವೈರ್ಲೆಸ್ನಿಂದ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"ಅಜ್ಞಾತ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ನಲ್ಲಿ ಚಾರ್ಜ್"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ಮೂಲಕ ಚಾರ್ಜ್"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ನಿಸ್ತಂತುವಾಗಿ ಚಾರ್ಜ್"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ಭರ್ತಿ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 035793ec0930..348141ed75ca 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"실험실 기능이며 성능에 영향을 줄 수 있습니다."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"약 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 대략 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(AC 전원)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(USB)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(무선)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"알 수 없음"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"충전 중"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"충전 중(AC 전원)"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"충전 중(USB)"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"충전 중(무선)"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"충전 안함"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"충전 안함"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"충전 완료"</string> diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml index 8c43312c34d1..2016f0497820 100644 --- a/packages/SettingsLib/res/values-ky-rKG/strings.xml +++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бул сынамык мүмкүнчүлүк болгондуктан, иштин майнаптуулугуна таасир этиши мүмкүн."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> калды"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - болжол менен <xliff:g id="TIME">%2$s</xliff:g> саат калды"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> толгончо"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC аркылуу толгончо"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB аркылуу толгончо"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> зымсыз кубаттоо аркылуу толгончо"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Белгисиз"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Кубатталууда"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ӨА кубатталууда"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB\'ден кубатталууда"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Зымсыз кубатталууда"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Кубат алган жок"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Кубатталган жок"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Толук"</string> diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml index f158d44dadcf..7e6db5ee29b6 100644 --- a/packages/SettingsLib/res/values-lo-rLA/strings.xml +++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ຄຸນສົມບັດນີ້ກຳລັງຢູ່ໃນການທົດລອງແລະອາດມີຜົນຕໍ່ປະສິດທິພາບ."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"ຍັງເຫຼືອປະມານ <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ເຫຼືອປະມານ <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມ"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມໂດຍສາກດ້ວຍໄຟ AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມໂດຍສາກດ້ວຍ USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມໂດຍສາກແບບໄຮ້ສາຍ"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"ບໍ່ຮູ້ຈັກ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ກຳລັງສາກຜ່ານໝໍ້ໄຟ"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"ກຳລັງສາກຜ່ານ USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ກຳລັງສາກໄຮ້ສາຍ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ບໍ່ໄດ້ສາກໄຟ"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ບໍ່ໄດ້ສາກໄຟ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ເຕັມ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index d5cea8efc460..d49876e69b16 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naud. kint. sr."</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naudojant USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo belaid. ryš."</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Įkr. naud. kint. sr."</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Įkraunama naud. USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Įkraunama be laidų"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nekraunama"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nekraunama"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Visiškai įkrautas"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index ea6f4f9627e8..6cd9cfd5da38 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> — aptuvenais atlikušais laiks: <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai maiņstrāvas uzlādei"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai USB uzlādei"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai bezvadu uzlādei"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Maiņstrāvas uzlāde"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB uzlāde"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezvadu uzlāde"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenotiek uzlāde"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenotiek uzlāde"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Pilns"</string> diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml index e954cdf12bb6..f8f65ec8bd52 100644 --- a/packages/SettingsLib/res/values-mk-rMK/strings.xml +++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Функцијата е експериментална и може да влијае на изведбата."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Преостанаа прибл. <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостанува приближно <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна на AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна преку USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна, безжично"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Полнење на струја"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Полнење преку УСБ"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично полнење"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не се полни"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не се полни"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Целосна"</string> diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml index a4b3877bfe01..7350b7fe10a0 100644 --- a/packages/SettingsLib/res/values-ml-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ഈ ഫീച്ചർ പരീക്ഷണാത്മകമായതിനാൽ പ്രകടനത്തെ ബാധിച്ചേക്കാം."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - AC-യിൽ പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - വയർലെസ് വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"അജ്ഞാതം"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ചാർജ്ജുചെയ്യുന്നു"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-യിൽ ചാർജ്ജുചെയ്യുന്നു"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-യിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"വയർലെസ്സ് കണക്ഷനിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ചാർജ്ജുചെയ്യുന്നില്ല"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ചാർജ്ജുചെയ്യുന്നില്ല"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"നിറഞ്ഞു"</string> diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml index d989ef86d7dc..7eeae06da0c0 100644 --- a/packages/SettingsLib/res/values-mn-rMN/strings.xml +++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Энэ функц туршилтынх бөгөөд ажиллагаанд нөлөөлж болзошгүй."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"АС-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"USB-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"утасгүй цэнэглэгчээр дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Тодорхойгүй"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Цэнэглэж байна"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-р цэнэглэж байна"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-р цэнэглэж байна"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Кабльгүйгээр цэнэглэж байна"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Цэнэглэхгүй байна"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Цэнэглэхгүй байна"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Дүүрэн"</string> diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml index d363874ae69b..0521ba1a888d 100644 --- a/packages/SettingsLib/res/values-mr-rIN/strings.xml +++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"हे वैशिष्ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"अंदाजे. <xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - अंदाजे. <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण होण्यात"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC वरून पूर्ण होण्यात"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB वरून पूर्ण होण्यात"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसवरून पूर्ण होण्यात"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC वर चार्ज करीत आहे"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB वरून चार्ज करीत आहे"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस वरून चार्ज करीत आहे"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज होत नाही"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज होत नाही"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string> diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml index ea79a468bbc2..a8be0e5b9791 100644 --- a/packages/SettingsLib/res/values-ms-rMY/strings.xml +++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira. <xliff:g id="TIME">%2$s</xliff:g> yang tinggal"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh di AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh melalui USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh dari wayarles"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengecas pada AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Mengecas melalui USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Mengecas tanpa wayar"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Tidak mengecas"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Tidak mengecas"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Penuh"</string> diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml index 74e0f29b809f..220deffc42f3 100644 --- a/packages/SettingsLib/res/values-my-rMM/strings.xml +++ b/packages/SettingsLib/res/values-my-rMM/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ဒီအင်္ဂါရပ်မှာ စမ်းသပ်မှု ဖြစ်၍ လုပ်ကိုင်မှုကို အကျိုးသက်ရောက်နိုင်သည်။"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"ခန့်မှန်းခြေ <xliff:g id="TIME">%1$s</xliff:g> ကျန်ပါသည်"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ခန့်မှန်းခြေ။ <xliff:g id="TIME">%2$s</xliff:g> ကျန်ရှိနေ"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> အပြည့်အထိ"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> လျှပ်စစ်ဖြင့် အပြည့်အထိ"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ဖြင့် အပြည့်အထိ"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ကြိုးမဲ့ဖြင့် အပြည့်အထိ"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"အကြောင်းအရာ မသိရှိ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"အားသွင်းနေပါသည်"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"လျှပ်စစ်ဖြင့် အားသွင်းနေ"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBဖြင့် အားသွင်းနေ"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ကြိုးမဲ့ အားသွင်းနေ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"အားသွင်းမနေပါ"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"အားသွင်းမနေပါ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"အပြည့်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 1a0b4683fc82..a1407ace2d00 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funksjonen er eksperimentell og kan påvirke ytelsen."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> igjen"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> med vekselstrøm"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via trådløs lading"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Lader via strømuttak"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Lader via USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Lader trådløst"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Lader ikke"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Lader ikke"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string> diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml index a001cab2651f..83e2e74a3b40 100644 --- a/packages/SettingsLib/res/values-ne-rNP/strings.xml +++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी छ"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - लगभग। <xliff:g id="TIME">%2$s</xliff:g> बायाँ"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पूर्ण नभए सम्म"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC मा पूर्ण नभए सम्म"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB मा पूर्ण नभए सम्म"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसबाट पूर्ण नभए सम्म"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC मा चार्ज गर्दै"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB मा चार्ज गर्दै"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"बिना तार चार्ज गर्दै"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"चार्ज भइरहेको छैन"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"चार्ज हुँदै छैन"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"पूर्ण"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 301e3276a5f5..55017d837cc5 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> resterend"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ca. <xliff:g id="TIME">%2$s</xliff:g> resterend"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via wisselstroom"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via draadloos"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Opladen via netvoeding"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladen via USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Draadloos opladen"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Wordt niet opgeladen"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Wordt niet opgeladen"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Volledig"</string> diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml index c792ec93834c..eb1eaacfbc8f 100644 --- a/packages/SettingsLib/res/values-pa-rIN/strings.xml +++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਪੂਰੀ ਹੋਣ ਤੱਕ"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਵਾਇਰਲੈਸ ਤੋਂ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜਿੰਗ"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ਤੇ ਚਾਰਜਿੰਗ"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ਤੇ ਚਾਰਜਿੰਗ"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ਵਾਇਰਲੈਸ ਤੌਰ ਤੇ ਚਾਰਜਿੰਗ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"ਪੂਰੀ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 8aad98b140a7..1e56cfd07b32 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Pozostało około <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostało ok. <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania z gniazdka"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania przez USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania bezprzewodowo"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Ładowanie zasilaczem"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Ładowanie przez USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ład. bezprzewodowe"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nie podłączony"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nie podłączony"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Naładowana"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index c05458bc4998..93f333aa9d2e 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 402bc860a7b7..dda00fe91287 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta funcionalidade é experimental e pode afetar o desempenho."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Resta(m) aproximadamente <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) aprox. <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de CA"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até ficar compl. por rede s/ fios"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"A carregar por CA"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"A carregar por USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"A carregar sem fios"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está a carregar"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está a carregar"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Completo"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index c05458bc4998..93f333aa9d2e 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Não está carregando"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Não está carregando"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Cheio"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index d5e07690382b..3c46d4142e4f 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – timp rămas: aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă la c.a."</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă prin USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă wireless"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Încarcă"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Se încarcă la C.A."</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Se încarcă prin USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Se încarcă fără fir"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nu se încarcă"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nu încarcă"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Complet"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 7ad9f160d70e..f4929de01bc2 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Это экспериментальная функция, она может снизить производительность устройства."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Осталось примерно <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – осталось около <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (от сети)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (через USB)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (беспроводная)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Идет зарядка"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зарядка от сети"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарядка через USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Беспроводная зарядка"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряжается"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряжается"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Батарея заряжена"</string> diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml index 4c73219f95e4..99f018bbdc5e 100644 --- a/packages/SettingsLib/res/values-si-rLK/strings.xml +++ b/packages/SettingsLib/res/values-si-rLK/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්රියාකාරිත්වයට බලපෑ හැක."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"දළ වශයෙන් <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරිය"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආසන්න <xliff:g id="TIME">%2$s</xliff:g> වම"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"AC හි <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"USB හරහ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"රේඩියෝව වෙතින් <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පූර්ණ වන තෙක්"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC හි ආරෝපණය වෙමින්"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB හරහා ආරෝපණය වෙමින්"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"රැහැන් රහිතව ආරෝපණය වෙමින්"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ආරෝපණය නොවේ"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ආරෝපණය නොවෙමින්"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"පූර්ණ"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index e5c9805fc5ae..4dffdefe6064 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zostáva cca. <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostáva približne <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia zo zásuvky"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia cez USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia bezdrôtovo"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjanie"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjanie zo zásuvky"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjanie cez USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrôtové nabíjanie"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nenabíja sa"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nenabíja sa"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Nabitá"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 8257e3c76e48..676a3ab20331 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To je preskusna funkcija in lahko vpliva na učinkovitost delovanja."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Še približno <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek napajalnika"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek USB-ja"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek brezž. pol."</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Polnj. prek iz. toka"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Polnj. prek USB-ja"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Brezžično polnjenje"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Se ne polni"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Se ne polni"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Poln"</string> diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml index 4a673480d095..c18e63950e79 100644 --- a/packages/SettingsLib/res/values-sq-rAL/strings.xml +++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ky funksion është eksperimental dhe mund të ndikojë në veprimtari."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Afërsisht <xliff:g id="TIME">%1$s</xliff:g> të mbetura"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - afërsisht <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të jetë e plotë"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet në AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet me USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet nga lidhja pa tel"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Po ngarkohet"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Po ngarkohet në AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Po ngarkohet me USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Po ngarkohet me valë"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Nuk po ngarkohet"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Nuk po ngarkohet"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"E mbushur"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index eaf7ac5464f7..c0791fcf1a5c 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ова функција је експериментална и може да утиче на перформансе."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Још отприлике <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – преостало око <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни пуњачем"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни преко USB-а"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни бежично"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Пуњење"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Пуњење преко пуњача"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Пуњење преко USB-а"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бежично пуњење"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не пуни се"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не пуни се"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Пуно"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index b01967260807..60c42a53c98f 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca <xliff:g id="TIME">%1$s</xliff:g> kvar"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca <xliff:g id="TIME">%2$s</xliff:g> kvar"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via laddare"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via trådlös laddning"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laddas via adapter"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laddas via USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laddas trådlöst"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Laddar inte"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Laddar inte"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Fullt"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 3daa90f70ad8..5de7686e0067 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takriban <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>%% - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa isiyotumia waya"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Inachaji kupitia AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Inachaji kupitia USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Inachaji bila kutumia waya"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Haichaji"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Haichaji"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Imejaa"</string> diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml index 574d105fdd50..a5f04d090291 100644 --- a/packages/SettingsLib/res/values-ta-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"இது சோதனை முறையிலான அம்சம், இது செயல்திறனைப் பாதிக்கலாம்."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"தோராயமாக <xliff:g id="TIME">%1$s</xliff:g> உள்ளது"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"தோராயம்: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> உள்ளது"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"முழு சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"முழு AC சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"முழு USB சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"முழு வயர்லெஸ் சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"அறியப்படாத"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"சார்ஜ் ஏற்றப்படுகிறது"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC மூலம் சார்ஜாகிறது"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB மூலம் சார்ஜாகிறது"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"வயர்லெஸில் சார்ஜாகிறது"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"சார்ஜ் செய்யப்படவில்லை"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"சார்ஜ் ஏறவில்லை"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"முழுமை"</string> diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml index 238911264f47..fe40766aa36e 100644 --- a/packages/SettingsLib/res/values-te-rIN/strings.xml +++ b/packages/SettingsLib/res/values-te-rIN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"సుమారు <xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - సుమారు <xliff:g id="TIME">%2$s</xliff:g> మిగిలి ఉంది"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ACలో పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB ద్వారా పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - వైర్లెస్ నుండి పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACలో ఛార్జ్ అవుతోంది"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ద్వారా ఛార్జ్ అవుతోంది"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"వైర్లెస్ ద్వారా ఛార్జ్ అవుతోంది"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ఛార్జ్ కావడం లేదు"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ఛార్జ్ కావడం లేదు"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"నిండింది"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 0f6f78cb2417..c58692f46411 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"คุณลักษณะนี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"เหลืออีกประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - เหลือประมาณ <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็ม"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่านระบบไร้สาย"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"ไม่ทราบ"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"กำลังชาร์จ"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"กำลังชาร์จไฟ AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"กำลังชาร์จผ่าน USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"กำลังชาร์จแบบไร้สาย"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"ไม่ได้ชาร์จ"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"ไม่ได้ชาร์จ"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"เต็ม"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index ef3dde79a0dd..093256c6ef3c 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ang feature na ito ay pinag-eeksperimentuhan at maaaring makaapekto sa pagganap."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> na lang ang natitira"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - humigit kumulang <xliff:g id="TIME">%2$s</xliff:g> ang natitira"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno mula sa wireless"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nagcha-charge sa AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nagcha-charge sa USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Wireless nag-charge"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Hindi nagcha-charge"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hindi nagkakarga"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Puno"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 4b7490d700f0..1947d39776a1 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - prize takılı, tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB üzerinden şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - kablosuzdan tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ile şarj oluyor"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ile şarj oluyor"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kablosuz şarj oluyor"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Şarj olmuyor"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Şarj etmiyor"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Dolu"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 5e044c3b2839..0ed6cc0b93ad 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Це експериментальна функція. Вона може вплинути на продуктивність."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Залишилося приблизно <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – залишилось близько <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження з розетки"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження через USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного з бездротового зарядження"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Невідомо"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядж-ся"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Заряджання з розетки"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Заряджання через USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Заряджання без дроту"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Не заряджається"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Не заряджається"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Акумулятор заряджено"</string> diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml index 6d3c6c4c037f..99a0f2becfcf 100644 --- a/packages/SettingsLib/res/values-ur-rPK/strings.xml +++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"تقریبا <xliff:g id="TIME">%1$s</xliff:g> باقی ہیں"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریبا <xliff:g id="TIME">%2$s</xliff:g> باقی"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> پورا ہونے تک"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC پر پورا ہونے تک"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB پر پورا ہونے تک"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> وائرلیس سے پورا ہونے تک"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC پر چارج ہو رہی ہے"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB پر چارج ہورہی ہے"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"وائرلیس چارجنگ"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"چارج نہیں ہو رہا ہے"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"چارج نہیں ہو رہا ہے"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"مکمل"</string> diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml index ec04120f9f03..b9c024351fd9 100644 --- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml +++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, to‘lguncha"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, o‘zgaruvchan tok orqali to‘lguncha"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, USB orqali to‘lguncha"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, simsiz quvvatlash orqali to‘lguncha"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Quvvat olmoqda (AC)"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Quvvat olmoqda (USB)"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Simsiz quvvat olmoqda"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Quvvat olmayapti"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Quvvatlanmayapti"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index dd1d482c4ca0..0c3dc899ce32 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn khoảng <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy khi cắm vào nguồn AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy qua USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy từ không dây"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Sạc trên AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Sạc qua USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Sạc không dây"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Hiện không sạc"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Hiện không sạc"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Đầy"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 4117ae143f84..2b8ce652fc93 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"此功能为实验性功能,可能会影响性能。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"还剩大约 <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还可用大约<xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(交流电充电)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(USB充电)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(无线充电)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"正在充电"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在通过交流电源充电"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在通过USB充电"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在无线充电"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"未在充电"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"未在充电"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"电量充足"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 1fb4c5ea7f49..8dd0417846d1 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會影響效能。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"尚餘大約 <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 尚餘大約 <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過插頭充電)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過 USB 充電)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (無線充電)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 充電"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"未開始充電"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"電量已滿"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 9c85f0e54952..dd59954d3ffa 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會對效能造成影響。"</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"還剩大約 <xliff:g id="TIME">%1$s</xliff:g>"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - 大約還剩 <xliff:g id="TIME">%2$s</xliff:g>"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (AC)"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (USB)"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (無線充電)"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 變壓器充電"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"非充電中"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"非充電中"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"電力充足"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 6017d68bfb37..610cac477886 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -296,17 +296,35 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="4400068916452346544">"Cishe ngu-<xliff:g id="TIME">%1$s</xliff:g> osele"</string> + <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) --> + <skip /> <string name="power_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - isilinganiso esingu-<xliff:g id="TIME">%2$s</xliff:g> esisele"</string> + <!-- no translation found for power_discharging_duration_short (4192244429001842403) --> + <skip /> <string name="power_charging" msgid="1779532561355864267">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_charging_duration" msgid="2853265177761520490">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale"</string> + <!-- no translation found for power_charging_duration_short (1098603958472207920) --> + <skip /> <string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ku-AC"</string> + <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) --> + <skip /> <string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ngaphezulu kwe-USB"</string> + <!-- no translation found for power_charging_duration_usb_short (941854728040426399) --> + <skip /> <string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale kusukela kokungenantambo"</string> + <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) --> + <skip /> <string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string> <string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string> <string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Iyashaja ku-AC"</string> + <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) --> + <skip /> <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Iyashaja ngaphezulu kwe-USB"</string> + <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) --> + <skip /> <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Iyashaja ngaphandle kwentambo"</string> + <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) --> + <skip /> <string name="battery_info_status_discharging" msgid="310932812698268588">"Ayishaji"</string> <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Ayishaji"</string> <string name="battery_info_status_full" msgid="2824614753861462808">"Kugcwele"</string> diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index c131fa5d547c..7ca76141a84c 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -463,7 +463,6 @@ public class BugreportProgressService extends Service { .setContentTitle(title) .setTicker(title) .setContentText(name) - .setContentInfo(percentageText) .setProgress(info.max, info.progress, false) .setOngoing(true) .setContentIntent(infoPendingIntent) @@ -958,7 +957,7 @@ public class BugreportProgressService extends Service { .setDeleteIntent(newCancelIntent(context, info)); if (!TextUtils.isEmpty(info.name)) { - builder.setContentInfo(info.name); + builder.setSubText(info.name); } Log.v(TAG, "Sending 'Share' notification for ID " + info.id + ": " + title); diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 7222cff32cf7..9e2442cc2357 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -184,6 +184,14 @@ android:exported="true" /> + <!-- Recents depends on every user having their own SystemUI process, so on user switch, + ensure that the process is created by starting this service. + --> + <service android:name="SystemUISecondaryUserService" + android:exported="true" + android:permission="com.android.systemui.permission.SELF" /> + + <!-- started from PhoneWindowManager TODO: Should have an android:permission attribute --> <service android:name=".screenshot.TakeScreenshotService" diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml new file mode 100644 index 000000000000..6519673de871 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path android:pathData="M0 0h24v24H0z" /> + <path android:fillColor="@color/ksh_key_item_color" + android:pathData="M22 3H7c-.69 0-1.23 .35 -1.59 .88 L0 12l5.41 8.11c.36 .53 .9 .89 +1.59 .89 h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 +12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_down.xml b/packages/SystemUI/res/drawable/ic_ksh_key_down.xml new file mode 100644 index 000000000000..25a2560c938b --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ksh_key_down.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2016 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path android:fillColor="@color/ksh_key_item_color" + android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" /> + <path android:pathData="M0-.75h24v24H0z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml b/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml new file mode 100644 index 000000000000..599f35001293 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2016 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path android:pathData="M0 0h24v24H0z" /> + <path android:fillColor="@color/ksh_key_item_color" + android:pathData="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_left.xml b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml new file mode 100644 index 000000000000..038187e86acb --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2016 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path android:fillColor="@color/ksh_key_item_color" + android:pathData="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" /> + <path android:pathData="M0 0h24v24H0z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml new file mode 100644 index 000000000000..1e2195edaf21 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2016 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path android:fillColor="@color/ksh_key_item_color" + android:pathData="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 +3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27 .28 v.79l5 4.99L20.49 +19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 +14z" /> + <path android:pathData="M0 0h24v24H0z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_right.xml b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml new file mode 100644 index 000000000000..f2d73150705a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2016 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path android:fillColor="@color/ksh_key_item_color" + android:pathData="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" /> + <path android:pathData="M0 0h24v24H0z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_up.xml b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml new file mode 100644 index 000000000000..36a83b1d1e82 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2016 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path android:fillColor="@color/ksh_key_item_color" + android:pathData="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" /> + <path android:pathData="M0 0h24v24H0z" /> +</vector> diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml new file mode 100644 index 000000000000..0cecb96fd022 --- /dev/null +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + ~ Copyright (C) 2016 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<ImageView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="@dimen/ksh_item_padding" + android:layout_marginStart="@dimen/ksh_item_margin_start" + android:scaleType="fitXY" + android:background="@color/ksh_key_item_background"/> diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml index 5002c1298eb2..1215029bdda0 100644 --- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml @@ -17,9 +17,9 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="4dp" - android:padding="4dp" - android:background="#EEEEEE" - android:textColor="#8C000000" + android:padding="@dimen/ksh_item_padding" + android:layout_marginStart="@dimen/ksh_item_margin_start" + android:background="@color/ksh_key_item_background" + android:textColor="@color/ksh_key_item_color" android:singleLine="true" - android:textSize="14sp"/> + android:textSize="@dimen/ksh_item_text_size"/> diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml index 224a0a0fd859..60112be21175 100644 --- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml +++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml @@ -112,21 +112,6 @@ <ImageView android:layout_width="match_parent" android:layout_height="match_parent" - android:scaleType="matrix" - android:src="@drawable/screen_pinning_light_bg_circ" /> - - <ImageView - android:layout_width="match_parent" - android:layout_height="match_parent" - android:paddingEnd="@dimen/screen_pinning_request_inner_padding" - android:paddingStart="@dimen/screen_pinning_request_inner_padding" - android:paddingTop="@dimen/screen_pinning_request_inner_padding" - android:scaleType="matrix" - android:src="@drawable/screen_pinning_bg_circ" /> - - <ImageView - android:layout_width="match_parent" - android:layout_height="match_parent" android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding" android:paddingStart="@dimen/screen_pinning_request_nav_side_padding" android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding" diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml index 1e5193ff9925..ebad7a4085be 100644 --- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml +++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml @@ -43,21 +43,6 @@ <ImageView android:layout_height="match_parent" android:layout_width="match_parent" - android:scaleType="matrix" - android:src="@drawable/screen_pinning_light_bg_circ" /> - - <ImageView - android:layout_height="match_parent" - android:layout_width="match_parent" - android:scaleType="matrix" - android:paddingLeft="@dimen/screen_pinning_request_inner_padding" - android:paddingTop="@dimen/screen_pinning_request_inner_padding" - android:paddingBottom="@dimen/screen_pinning_request_inner_padding" - android:src="@drawable/screen_pinning_bg_circ" /> - - <ImageView - android:layout_height="match_parent" - android:layout_width="match_parent" android:scaleType="center" android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding" android:paddingTop="@dimen/screen_pinning_request_nav_side_padding" diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml index f1be67241413..c5398a2cb6e2 100644 --- a/packages/SystemUI/res/values-bs-rBA/strings.xml +++ b/packages/SystemUI/res/values-bs-rBA/strings.xml @@ -531,30 +531,18 @@ <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Početak"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Nedavni ekrani"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Nazad"</string> - <!-- no translation found for keyboard_shortcut_group_system_notifications (8366964080041773224) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_shortcuts_helper (4892255911160332762) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_switch_input (2334164096341310324) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications (9129465955073449206) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_assist (9095441910537146013) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_browser (6465985474000766533) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_contacts (2064197111278436375) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_email (6257036897441939004) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_im (1892749399083161405) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_music (4775559515850922780) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_youtube (6555453761294723317) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_calendar (9043614299194991263) --> - <skip /> + <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Obavještenja"</string> + <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Skracenice tastature"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Promijeni način unosa"</string> + <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplikacije"</string> + <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Pomoć"</string> + <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Preglednik"</string> + <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontakti"</string> + <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-pošta"</string> + <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string> + <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzika"</string> + <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendar"</string> <string name="tuner_full_zen_title" msgid="4540823317772234308">"Prikazati sa kontrolama jačine zvuka"</string> <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Ne ometaj"</string> <string name="volume_dnd_silent" msgid="4363882330723050727">"Prečica za dugmad za Jačinu zvuka"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 7c2da101e623..322197e1c990 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -534,7 +534,7 @@ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"میانبرهای صفحهکلید"</string> <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"تغییر روش ورودی"</string> <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"برنامهها"</string> - <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"همیار"</string> + <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"دستیار"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"مرورگر"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"مخاطبین"</string> <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"رایانامه"</string> diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml index c8f6649606bf..45c3626b0c6e 100644 --- a/packages/SystemUI/res/values-gl-rES/strings.xml +++ b/packages/SystemUI/res/values-gl-rES/strings.xml @@ -530,30 +530,18 @@ <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Inicio"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recentes"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Volver"</string> - <!-- no translation found for keyboard_shortcut_group_system_notifications (8366964080041773224) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_shortcuts_helper (4892255911160332762) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_switch_input (2334164096341310324) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications (9129465955073449206) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_assist (9095441910537146013) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_browser (6465985474000766533) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_contacts (2064197111278436375) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_email (6257036897441939004) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_im (1892749399083161405) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_music (4775559515850922780) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_youtube (6555453761294723317) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_calendar (9043614299194991263) --> - <skip /> + <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificacións"</string> + <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Atallos de teclado"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Cambiar de método de entrada"</string> + <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicacións"</string> + <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistente"</string> + <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string> + <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string> + <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string> + <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string> + <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string> + <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string> <string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostrar cos controis de volume"</string> <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Non molestar"</string> <string name="volume_dnd_silent" msgid="4363882330723050727">"Atallo dos botóns de volume"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 220250bdbfb8..eed5f36ae95c 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -402,7 +402,7 @@ <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheten forblir låst til du låser den opp manuelt"</string> <string name="hidden_notifications_title" msgid="7139628534207443290">"Motta varsler raskere"</string> <string name="hidden_notifications_text" msgid="2326409389088668981">"Se dem før du låser opp"</string> - <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nei, takk"</string> + <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nei takk"</string> <string name="hidden_notifications_setup" msgid="41079514801976810">"Konfigurer"</string> <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string> <string name="volume_zen_end_now" msgid="3179845345429841822">"Avslutt nå"</string> @@ -411,7 +411,7 @@ <string name="screen_pinning_title" msgid="3273740381976175811">"Skjermen er låst"</string> <string name="screen_pinning_description" msgid="3577937698406151604">"På denne måten blir skjermen synlig frem til du låser den opp. Trykk og hold inne Tilbake for å låse opp."</string> <string name="screen_pinning_positive" msgid="3783985798366751226">"Skjønner"</string> - <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei, takk"</string> + <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei takk"</string> <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string> <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Den vises igjen neste gang du slår den på i innstillingene."</string> <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Skjul"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 0e818c49d497..81d0456e5bda 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -531,30 +531,18 @@ <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Ecran de pornire"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Recente"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Înapoi"</string> - <!-- no translation found for keyboard_shortcut_group_system_notifications (8366964080041773224) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_shortcuts_helper (4892255911160332762) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_switch_input (2334164096341310324) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications (9129465955073449206) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_assist (9095441910537146013) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_browser (6465985474000766533) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_contacts (2064197111278436375) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_email (6257036897441939004) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_im (1892749399083161405) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_music (4775559515850922780) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_youtube (6555453761294723317) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_calendar (9043614299194991263) --> - <skip /> + <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Notificări"</string> + <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Comenzi rapide de la tastatură"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Comutați metoda de introducere a textului"</string> + <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Aplicații"</string> + <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Asistent"</string> + <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Browser"</string> + <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Agendă"</string> + <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"E-mail"</string> + <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string> + <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Muzică"</string> + <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</string> <string name="tuner_full_zen_title" msgid="4540823317772234308">"Afișează cu comenzile de volum"</string> <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nu deranja"</string> <string name="volume_dnd_silent" msgid="4363882330723050727">"Comandă rapidă din butoanele de volum"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 1baa67d1c1e7..86f0ec4c2ba9 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -532,30 +532,18 @@ <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"Главный экран"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Недавние"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string> - <!-- no translation found for keyboard_shortcut_group_system_notifications (8366964080041773224) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_shortcuts_helper (4892255911160332762) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_switch_input (2334164096341310324) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications (9129465955073449206) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_assist (9095441910537146013) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_browser (6465985474000766533) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_contacts (2064197111278436375) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_email (6257036897441939004) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_im (1892749399083161405) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_music (4775559515850922780) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_youtube (6555453761294723317) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_calendar (9043614299194991263) --> - <skip /> + <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Уведомления"</string> + <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Быстрые клавиши"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Сменить способ ввода"</string> + <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Приложения"</string> + <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Помощник"</string> + <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Браузер"</string> + <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакты"</string> + <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Эл. почта"</string> + <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string> + <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка."</string> + <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календарь"</string> <string name="tuner_full_zen_title" msgid="4540823317772234308">"Показывать при нажатии кнопок регулировки громкости"</string> <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Не беспокоить"</string> <string name="volume_dnd_silent" msgid="4363882330723050727">"Кнопки регулировки громкости"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index d5593447655f..a25b9f125cc2 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -34,14 +34,14 @@ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string> <string name="battery_low_title" msgid="6456385927409742437">"电池电量偏低"</string> <string name="battery_low_percent_format" msgid="2900940511201380775">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>。节电助手已开启。"</string> + <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>。省电模式已开启。"</string> <string name="invalid_charger" msgid="4549105996740522523">"不支持USB充电功能。\n只能使用随附的充电器充电。"</string> <string name="invalid_charger_title" msgid="3515740382572798460">"不支持USB充电。"</string> <string name="invalid_charger_text" msgid="5474997287953892710">"仅限使用设备随附的充电器。"</string> <string name="battery_low_why" msgid="4553600287639198111">"设置"</string> - <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"要开启节电助手吗?"</string> + <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"要开启省电模式吗?"</string> <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"开启"</string> - <string name="battery_saver_start_action" msgid="5576697451677486320">"开启节电助手"</string> + <string name="battery_saver_start_action" msgid="5576697451677486320">"开启省电模式"</string> <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string> <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string> <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自动旋转屏幕"</string> @@ -373,9 +373,9 @@ <string name="user_remove_user_title" msgid="4681256956076895559">"是否移除用户?"</string> <string name="user_remove_user_message" msgid="1453218013959498039">"此用户的所有应用和数据均将被删除。"</string> <string name="user_remove_user_remove" msgid="7479275741742178297">"移除"</string> - <string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已开启"</string> + <string name="battery_saver_notification_title" msgid="237918726750955859">"省电模式已开启"</string> <string name="battery_saver_notification_text" msgid="820318788126672692">"降低性能并限制后台流量"</string> - <string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭节电助手"</string> + <string name="battery_saver_notification_action_text" msgid="109158658238110382">"关闭省电模式"</string> <string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>将开始截取您的屏幕上显示的所有内容。"</string> <string name="media_projection_remember_text" msgid="3103510882172746752">"不再显示"</string> <string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string> @@ -497,8 +497,8 @@ <string name="color_revert_title" msgid="4746666545480534663">"确认设置"</string> <string name="color_revert_message" msgid="9116001069397996691">"部分颜色设置可能会导致此设备无法使用。请点击“确定”确认这些颜色设置,否则,系统将在 10 秒后重置这些设置。"</string> <string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string> - <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用节电助手"</string> - <string name="battery_detail_switch_title" msgid="6285872470260795421">"节电助手"</string> + <string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用省电模式"</string> + <string name="battery_detail_switch_title" msgid="6285872470260795421">"省电模式"</string> <string name="battery_detail_switch_summary" msgid="9049111149407626804">"降低性能并限制后台流量"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"<xliff:g id="NAME">%1$s</xliff:g>按钮"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> @@ -530,30 +530,18 @@ <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"主屏幕"</string> <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"最近"</string> <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"返回"</string> - <!-- no translation found for keyboard_shortcut_group_system_notifications (8366964080041773224) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_shortcuts_helper (4892255911160332762) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_system_switch_input (2334164096341310324) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications (9129465955073449206) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_assist (9095441910537146013) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_browser (6465985474000766533) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_contacts (2064197111278436375) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_email (6257036897441939004) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_im (1892749399083161405) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_music (4775559515850922780) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_youtube (6555453761294723317) --> - <skip /> - <!-- no translation found for keyboard_shortcut_group_applications_calendar (9043614299194991263) --> - <skip /> + <string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"通知"</string> + <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"键盘快捷键"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"切换输入法"</string> + <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"应用"</string> + <string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"辅助应用"</string> + <string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"浏览器"</string> + <string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"通讯录"</string> + <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"电子邮件"</string> + <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"即时通讯"</string> + <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"音乐"</string> + <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string> + <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"日历"</string> <string name="tuner_full_zen_title" msgid="4540823317772234308">"与音量控件一起显示"</string> <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"请勿打扰"</string> <string name="volume_dnd_silent" msgid="4363882330723050727">"音量按钮快捷键"</string> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index b9aa26b0c785..b874e7c051db 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -169,6 +169,8 @@ <color name="ksh_system_group_color">#ff00bcd4</color> <color name="ksh_application_group_color">#fff44336</color> <color name="ksh_keyword_color">#d9000000</color> + <color name="ksh_key_item_color">@color/material_grey_600</color> + <color name="ksh_key_item_background">#eeeeee</color> <!-- Background color of edit overflow --> <color name="qs_edit_overflow_bg">#455A64</color> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index fd051b1b371f..6ce2a5dfb16c 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -178,7 +178,7 @@ <!-- Recents: The relative range of visible tasks from the current scroll position while the stack is focused. --> <item name="recents_layout_focused_range_min" format="float" type="integer">-3</item> - <item name="recents_layout_focused_range_max" format="float" type="integer">3</item> + <item name="recents_layout_focused_range_max" format="float" type="integer">2</item> <!-- Recents: The relative range of visible tasks from the current scroll position while the stack is not focused. --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index c094da9db43a..75e57b0bffd9 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -561,6 +561,9 @@ <!-- Keyboard shortcuts helper --> <dimen name="ksh_layout_width">@dimen/match_parent</dimen> + <dimen name="ksh_item_text_size">14sp</dimen> + <dimen name="ksh_item_padding">4dp</dimen> + <dimen name="ksh_item_margin_start">4dp</dimen> <!-- Recents Layout --> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index c0a565db34c7..e83819179c24 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -329,7 +329,7 @@ public class SwipeHelper implements Gefingerpoken { */ public void dismissChild(final View view, float velocity, boolean useAccelerateInterpolator) { dismissChild(view, velocity, null /* endAction */, 0 /* delay */, - useAccelerateInterpolator, 0 /* fixedDuration */); + useAccelerateInterpolator, 0 /* fixedDuration */, false /* isDismissAll */); } /** @@ -341,17 +341,22 @@ public class SwipeHelper implements Gefingerpoken { * @param fixedDuration If not 0, this exact duration will be taken */ public void dismissChild(final View animView, float velocity, final Runnable endAction, - long delay, boolean useAccelerateInterpolator, long fixedDuration) { + long delay, boolean useAccelerateInterpolator, long fixedDuration, + boolean isDismissAll) { final boolean canBeDismissed = mCallback.canChildBeDismissed(animView); float newPos; boolean isLayoutRtl = animView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - if (velocity < 0 - || (velocity == 0 && getTranslation(animView) < 0) - // if we use the Menu to dismiss an item in landscape, animate up - || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y) - // if the language is rtl we prefer swiping to the left - || (velocity == 0 && getTranslation(animView) == 0 && isLayoutRtl)) { + // if we use the Menu to dismiss an item in landscape, animate up + boolean animateUpForMenu = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll) + && mSwipeDirection == Y; + // if the language is rtl we prefer swiping to the left + boolean animateLeftForRtl = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll) + && isLayoutRtl; + boolean animateLeft = velocity < 0 + || (velocity == 0 && getTranslation(animView) < 0 && !isDismissAll); + + if (animateLeft || animateLeftForRtl || animateUpForMenu) { newPos = -getSize(animView); } else { newPos = getSize(animView); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index b2b612787fd2..455a69fcc77b 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -123,6 +123,17 @@ public class SystemUIApplication extends Application { startServicesIfNeeded(SERVICES); } + /** + * Ensures that all the Secondary user SystemUI services are running. If they are already + * running, this is a no-op. This is needed to conditinally start all the services, as we only + * need to have it in the main process. + * + * <p>This method must only be called from the main thread.</p> + */ + void startSecondaryUserServicesIfNeeded() { + startServicesIfNeeded(SERVICES_PER_USER); + } + private void startServicesIfNeeded(Class<?>[] services) { if (mServicesStarted) { return; diff --git a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java new file mode 100644 index 000000000000..f619bfbcd047 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +import android.app.ActivityManager; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.os.Process; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +public class SystemUISecondaryUserService extends Service { + + @Override + public void onCreate() { + super.onCreate(); + ((SystemUIApplication) getApplication()).startSecondaryUserServicesIfNeeded(); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + SystemUI[] services = ((SystemUIApplication) getApplication()).getServices(); + if (args == null || args.length == 0) { + for (SystemUI ui: services) { + pw.println("dumping service: " + ui.getClass().getName()); + ui.dump(fd, pw, args); + } + } else { + String svc = args[0]; + for (SystemUI ui: services) { + String name = ui.getClass().getName(); + if (name.endsWith(svc)) { + ui.dump(fd, pw, args); + } + } + } + } +} + diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index d2c60efd1282..84d359926c50 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -115,9 +115,9 @@ public class KeyguardService extends Service { } @Override // Binder interface - public void onFinishedGoingToSleep(int reason) { + public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) { checkPermission(); - mKeyguardViewMediator.onFinishedGoingToSleep(reason); + mKeyguardViewMediator.onFinishedGoingToSleep(reason, cameraGestureTriggered); } @Override // Binder interface diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index a5dfc4b2ad85..e00bf6cc792d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -747,7 +747,7 @@ public class KeyguardViewMediator extends SystemUI { notifyStartedGoingToSleep(); } - public void onFinishedGoingToSleep(int why) { + public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) { if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")"); synchronized (this) { mDeviceInteractive = false; @@ -758,6 +758,16 @@ public class KeyguardViewMediator extends SystemUI { notifyFinishedGoingToSleep(); + if (cameraGestureTriggered) { + Log.i(TAG, "Camera gesture was triggered, preventing Keyguard locking."); + + // Just to make sure, make sure the device is awake. + mContext.getSystemService(PowerManager.class).wakeUp(SystemClock.uptimeMillis(), + "com.android.systemui:CAMERA_GESTURE_PREVENT_LOCK"); + mPendingLock = false; + mPendingReset = false; + } + if (mPendingReset) { resetStateLocked(); mPendingReset = false; @@ -771,7 +781,7 @@ public class KeyguardViewMediator extends SystemUI { // We do not have timeout and power button instant lock setting for profile lock. // So we use the personal setting if there is any. But if there is no device // we need to make sure we lock it immediately when the screen is off. - if (!mLockLater) { + if (!mLockLater && !cameraGestureTriggered) { doKeyguardForChildProfilesLocked(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 2ba40449707a..e8e17b1d15c3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -105,7 +105,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta public void saveSpecs(QSTileHost host) { List<String> newSpecs = new ArrayList<>(); - for (int i = 0; mTiles.get(i) != null; i++) { + for (int i = 0; i < mTiles.size() && mTiles.get(i) != null; i++) { newSpecs.add(mTiles.get(i).spec); } host.changeTiles(mCurrentSpecs, newSpecs); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 8060e07801bb..b1d955573d19 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -78,6 +78,9 @@ import com.android.systemui.recents.views.RecentsView; import com.android.systemui.recents.views.SystemBarScrimViews; import com.android.systemui.statusbar.BaseStatusBar; +import java.io.FileDescriptor; +import java.io.PrintWriter; + /** * The main Recents activity that is started from AlternateRecentsComponent. */ @@ -733,4 +736,20 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD }); return true; } + + @Override + public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + super.dump(prefix, fd, writer, args); + String id = Integer.toHexString(System.identityHashCode(this)); + + writer.print(prefix); writer.print(TAG); + writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N"); + writer.print(" [0x"); writer.print(id); writer.print("]"); + writer.println(); + + if (mRecentsView != null) { + mRecentsView.dump(prefix, writer); + } + EventBus.getDefault().dump(prefix, writer); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 4dae7460f30a..aba05aa38619 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -144,7 +144,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Task launching Rect mTaskStackBounds = new Rect(); - Rect mLastTaskViewBounds = new Rect(); TaskViewTransform mTmpTransform = new TaskViewTransform(); int mStatusBarHeight; int mNavBarHeight; @@ -169,8 +168,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } }); - protected Bitmap mThumbnailTransitionBitmapCache; - Task mThumbnailTransitionBitmapCacheKey; + protected Bitmap mThumbTransitionBitmapCache; public RecentsImpl(Context context) { mContext = context; @@ -186,7 +184,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Initialize the static configuration resources reloadHeaderBarLayout(); - updateHeaderBarLayout(null /* stack */); // When we start, preload the data associated with the previous recent tasks. // We can use a new plan since the caches will be the same. @@ -201,12 +198,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void onBootCompleted() { - updateHeaderBarLayout(null /* stack */); + // Do nothing } public void onConfigurationChanged() { reloadHeaderBarLayout(); - updateHeaderBarLayout(null /* stack */); } /** @@ -368,9 +364,14 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener loader.preloadTasks(sInstanceLoadPlan, topTask.id, topTaskHome.value); TaskStack stack = sInstanceLoadPlan.getTaskStack(); if (stack.getTaskCount() > 0) { - // We try and draw the thumbnail transition bitmap in parallel before - // toggle/show recents is called - preCacheThumbnailTransitionBitmapAsync(topTask, stack, mDummyStackView); + // Only preload the icon (but not the thumbnail since it may not have been taken for + // the pausing activity) + preloadIcon(topTask); + + // At this point, we don't know anything about the stack state. So only calculate + // the dimensions of the thumbnail that we need for the transition into Recents, but + // do not draw it until we construct the activity options when we start Recents + updateHeaderBarLayout(stack); } } } @@ -601,21 +602,30 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener if (stack != null) { stackLayout.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right, mTaskStackBounds); + stackLayout.reset(); stackLayout.initialize(windowRect, mTaskStackBounds, TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); - } - Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds(); - if (!taskViewBounds.equals(mLastTaskViewBounds)) { - mLastTaskViewBounds.set(taskViewBounds); + Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds(); int taskViewWidth = taskViewBounds.width(); synchronized (mHeaderBarLock) { - mHeaderBar.measure( - View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY), - View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY)); + if (mHeaderBar.getMeasuredWidth() != taskViewWidth || + mHeaderBar.getMeasuredHeight() != mTaskBarHeight) { + mHeaderBar.measure( + View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY)); + } mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight); } + + // Update the transition bitmap to match the new header bar height + if (mThumbTransitionBitmapCache == null || + (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) || + (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) { + mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth, + mTaskBarHeight, Bitmap.Config.ARGB_8888); + } } } @@ -652,40 +662,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } /** - * Caches the header thumbnail used for a window animation asynchronously into - * {@link #mThumbnailTransitionBitmapCache}. - */ - private void preCacheThumbnailTransitionBitmapAsync(ActivityManager.RunningTaskInfo topTask, - TaskStack stack, TaskStackView stackView) { - preloadIcon(topTask); - - // Update the header bar if necessary - updateHeaderBarLayout(stack); - - // Update the destination rect - final Task toTask = new Task(); - final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask); - ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() { - @Override - public void run() { - final Bitmap transitionBitmap = drawThumbnailTransitionBitmap(toTask, toTransform); - if (transitionBitmap != null) { - mHandler.post(new Runnable() { - @Override - public void run() { - mThumbnailTransitionBitmapCache = transitionBitmap; - mThumbnailTransitionBitmapCacheKey = toTask; - } - }); - } else { - Log.e(TAG, "Could not load thumbnail for task: " + toTask + " at transform: " + - toTransform); - } - } - }); - } - - /** * Creates the activity options for a unknown state->recents transition. */ protected ActivityOptions getUnknownTransitionActivityOptions() { @@ -724,9 +700,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener if (task.isFreeformTask()) { mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task, stackScroller.getStackScroll(), mTmpTransform, null); + Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform, + mThumbTransitionBitmapCache); Rect toTaskRect = new Rect(); mTmpTransform.rect.round(toTaskRect); - Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform); specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect)); } } @@ -738,9 +715,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Update the destination rect Task toTask = new Task(); TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask); - RectF toTaskRect = toTransform.rect; - Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform); + Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform, + mThumbTransitionBitmapCache); if (thumbnail != null) { + RectF toTaskRect = toTransform.rect; return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, thumbnail, (int) toTaskRect.left, (int) toTaskRect.top, (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null); @@ -750,22 +728,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } } - private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask, - TaskViewTransform toTransform) { - Bitmap thumbnail; - if (mThumbnailTransitionBitmapCacheKey != null - && mThumbnailTransitionBitmapCacheKey.key != null - && mThumbnailTransitionBitmapCacheKey.key.equals(toTask.key)) { - thumbnail = mThumbnailTransitionBitmapCache; - mThumbnailTransitionBitmapCacheKey = null; - mThumbnailTransitionBitmapCache = null; - } else { - preloadIcon(topTask); - thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform); - } - return thumbnail; - } - /** * Returns the transition rect for the given task id. */ @@ -793,26 +755,19 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener /** * Draws the header of a task used for the window animation into a bitmap. */ - private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform) { + private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform, + Bitmap thumbnail) { SystemServicesProxy ssp = Recents.getSystemServices(); if (toTransform != null && toTask.key != null) { - Bitmap thumbnail; synchronized (mHeaderBarLock) { - int toHeaderWidth = (int) toTransform.rect.width(); - int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale); - if (toHeaderWidth <= 0 || toHeaderHeight <= 0) { - return null; - } boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode(); mHeaderBar.onTaskViewSizeChanged((int) toTransform.rect.width(), (int) toTransform.rect.height()); - thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight, - Bitmap.Config.ARGB_8888); if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { thumbnail.eraseColor(0xFFff0000); } else { + thumbnail.eraseColor(0); Canvas c = new Canvas(thumbnail); - c.scale(toTransform.scale, toTransform.scale); // Workaround for b/27815919, reset the callback so that we do not trigger an // invalidate on the header bar as a result of updating the icon Drawable icon = mHeaderBar.getIconView().getDrawable(); @@ -854,6 +809,18 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener boolean hasRecentTasks = stack.getTaskCount() > 0; boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks; + // Update the launch state that we need in updateHeaderBarLayout() + launchState.launchedFromHome = !useThumbnailTransition; + launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking; + launchState.launchedViaDockGesture = mLaunchedWhileDocking; + launchState.launchedViaDragGesture = mDraggingInRecents; + launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1; + launchState.launchedWithAltTab = mTriggeredFromAltTab; + + // Preload the icon (this will be a null-op if we have preloaded the icon already in + // preloadRecents()) + preloadIcon(topTask); + // Update the header bar if necessary updateHeaderBarLayout(stack); @@ -861,44 +828,27 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener TaskStackLayoutAlgorithm.VisibilityReport stackVr = mDummyStackView.computeStackVisibilityReport(); - // Update the launch state - launchState.launchedFromHome = false; - launchState.launchedFromApp = mLaunchedWhileDocking; - launchState.launchedViaDockGesture = mLaunchedWhileDocking; - launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1; - launchState.launchedWithAltTab = mTriggeredFromAltTab; + // Update the remaining launch state launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks; launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails; - launchState.launchedViaDragGesture = mDraggingInRecents; if (!animate) { startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1)); return; } + ActivityOptions opts; if (useThumbnailTransition) { - launchState.launchedFromApp = true; - // Try starting with a thumbnail transition - ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView); - if (opts != null) { - startRecentsActivity(opts); - } else { - // Fall through below to the non-thumbnail transition - useThumbnailTransition = false; - } - } - - if (!useThumbnailTransition) { - launchState.launchedFromHome = true; - + opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView); + } else { // If there is no thumbnail transition, but is launching from home into recents, then // use a quick home transition - ActivityOptions opts = hasRecentTasks - ? getHomeTransitionActivityOptions() - : getUnknownTransitionActivityOptions(); - startRecentsActivity(opts); + opts = hasRecentTasks + ? getHomeTransitionActivityOptions() + : getUnknownTransitionActivityOptions(); } + startRecentsActivity(opts); mLastToggleTime = SystemClock.elapsedRealtime(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java index 0d56ae98a165..38ad1c710716 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java @@ -30,6 +30,7 @@ import android.util.MutableBoolean; import com.android.systemui.recents.misc.ReferenceCountedTrigger; +import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -652,19 +653,43 @@ public class EventBus extends BroadcastReceiver { /** * @return a dump of the current state of the EventBus */ - public String dump() { + public void dump(String prefix, PrintWriter writer) { + writer.println(dumpInternal(prefix)); + } + + public String dumpInternal(String prefix) { + String innerPrefix = prefix + " "; + String innerInnerPrefix = innerPrefix + " "; StringBuilder output = new StringBuilder(); + output.append(prefix); output.append("Registered class types:"); output.append("\n"); - for (Class<?> clz : mSubscriberTypeMap.keySet()) { - output.append("\t"); + ArrayList<Class<?>> subsciberTypes = new ArrayList<>(mSubscriberTypeMap.keySet()); + Collections.sort(subsciberTypes, new Comparator<Class<?>>() { + @Override + public int compare(Class<?> o1, Class<?> o2) { + return o1.getSimpleName().compareTo(o2.getSimpleName()); + } + }); + for (int i = 0; i < subsciberTypes.size(); i++) { + Class<?> clz = subsciberTypes.get(i); + output.append(innerPrefix); output.append(clz.getSimpleName()); output.append("\n"); } + output.append(prefix); output.append("Event map:"); output.append("\n"); - for (Class<?> clz : mEventTypeMap.keySet()) { - output.append("\t"); + ArrayList<Class<?>> classes = new ArrayList<>(mEventTypeMap.keySet()); + Collections.sort(classes, new Comparator<Class<?>>() { + @Override + public int compare(Class<?> o1, Class<?> o2) { + return o1.getSimpleName().compareTo(o2.getSimpleName()); + } + }); + for (int i = 0; i < classes.size(); i++) { + Class<?> clz = classes.get(i); + output.append(innerPrefix); output.append(clz.getSimpleName()); output.append(" -> "); output.append("\n"); @@ -673,7 +698,7 @@ public class EventBus extends BroadcastReceiver { Object subscriber = handler.subscriber.getReference(); if (subscriber != null) { String id = Integer.toHexString(System.identityHashCode(subscriber)); - output.append("\t\t"); + output.append(innerInnerPrefix); output.append(subscriber.getClass().getSimpleName()); output.append(" [0x" + id + ", #" + handler.priority + "]"); output.append("\n"); diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index e28612a3cff6..69d98af5a2b2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -243,4 +243,14 @@ public class Utilities { public static float dpToPx(Resources res, float dp) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics()); } + + /** + * Returns a lightweight dump of a rect. + */ + public static String dumpRect(Rect r) { + if (r == null) { + return "N:0,0-0,0"; + } + return r.left + "," + r.top + "-" + r.right + "," + r.bottom; + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java index 6668079340ec..24eeaf27f032 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -29,6 +29,7 @@ import com.android.systemui.recents.Recents; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.Utilities; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Objects; @@ -37,6 +38,9 @@ import java.util.Objects; * A task represents the top most task in the system's task stack. */ public class Task { + + public static final String TAG = "Task"; + /* Task callbacks */ public interface TaskCallbacks { /* Notifies when a task has been bound */ @@ -100,7 +104,8 @@ public class Task { @Override public String toString() { - return "t" + id + ", s" + stackId + ", u" + userId; + return "id=" + id + " stackId=" + stackId + " user=" + userId + " lastActiveTime=" + + lastActiveTime; } private void updateHashCode() { @@ -306,4 +311,13 @@ public class Task { public String toString() { return "[" + key.toString() + "] " + title; } + + public void dump(String prefix, PrintWriter writer) { + writer.print(prefix); writer.print(key); + if (affiliationTaskId != key.id) { + writer.print(" "); writer.print("affTaskId=" + affiliationTaskId); + } + writer.print(" "); writer.print(title); + writer.println(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index df3f56c7c3ac..fbb59870b237 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -55,6 +55,7 @@ import com.android.systemui.recents.views.AnimationProps; import com.android.systemui.recents.views.DropTarget; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -208,6 +209,8 @@ class FilteredTaskList { */ public class TaskStack { + private static final String TAG = "TaskStack"; + /** Task stack callbacks */ public interface TaskStackCallbacks { /** @@ -725,7 +728,9 @@ public class TaskStack { /** Finds the task with the specified task id. */ public Task findTaskWithId(int taskId) { ArrayList<Task> tasks = computeAllTasksList(); - for (Task task : tasks) { + int taskCount = tasks.size(); + for (int i = 0; i < taskCount; i++) { + Task task = tasks.get(i); if (task.key.id == taskId) { return task; } @@ -880,7 +885,10 @@ public class TaskStack { ArraySet<ComponentName> existingComponents = new ArraySet<>(); ArraySet<ComponentName> removedComponents = new ArraySet<>(); ArrayList<Task.TaskKey> taskKeys = getTaskKeys(); - for (Task.TaskKey t : taskKeys) { + int taskKeyCount = taskKeys.size(); + for (int i = 0; i < taskKeyCount; i++) { + Task.TaskKey t = taskKeys.get(i); + // Skip if this doesn't apply to the current user if (t.userId != userId) continue; @@ -903,8 +911,10 @@ public class TaskStack { @Override public String toString() { String str = "Stack Tasks (" + mStackTaskList.size() + "):\n"; - for (Task t : mStackTaskList.getTasks()) { - str += " " + t.toString() + "\n"; + ArrayList<Task> tasks = mStackTaskList.getTasks(); + int taskCount = tasks.size(); + for (int i = 0; i < taskCount; i++) { + str += " " + tasks.get(i).toString() + "\n"; } return str; } @@ -921,4 +931,17 @@ public class TaskStack { } return map; } + + public void dump(String prefix, PrintWriter writer) { + String innerPrefix = prefix + " "; + + writer.print(prefix); writer.print(TAG); + writer.print(" numStackTasks="); writer.print(mStackTaskList.size()); + writer.println(); + ArrayList<Task> tasks = mStackTaskList.getTasks(); + int taskCount = tasks.size(); + for (int i = 0; i < taskCount; i++) { + tasks.get(i).dump(innerPrefix, writer); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java index c1b47dcbb4e0..fb62affd6cee 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java @@ -124,7 +124,7 @@ public class RecentsTvImpl extends RecentsImpl{ */ private ActivityOptions getThumbnailTransitionActivityOptionsForTV( ActivityManager.RunningTaskInfo topTask) { - Bitmap thumbnail = mThumbnailTransitionBitmapCache; + Bitmap thumbnail = mThumbTransitionBitmapCache; Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext); if (thumbnail != null) { return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index ef81f9ee2817..21a43d5c3e52 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -74,6 +74,8 @@ import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecC import com.android.systemui.stackdivider.WindowManagerProxy; import com.android.systemui.statusbar.FlingAnimationUtils; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -83,6 +85,8 @@ import java.util.List; */ public class RecentsView extends FrameLayout { + private static final String TAG = "RecentsView"; + private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135; private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200; private static final float DEFAULT_SCRIM_ALPHA = 0.33f; @@ -758,4 +762,22 @@ public class RecentsView extends FrameLayout { top + mStackActionButton.getMeasuredHeight()); return actionButtonRect; } + + public void dump(String prefix, PrintWriter writer) { + String innerPrefix = prefix + " "; + String id = Integer.toHexString(System.identityHashCode(this)); + + writer.print(prefix); writer.print(TAG); + writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N"); + writer.print(" insets="); writer.print(Utilities.dumpRect(mSystemInsets)); + writer.print(" [0x"); writer.print(id); writer.print("]"); + writer.println(); + + if (mStack != null) { + mStack.dump(innerPrefix, writer); + } + if (mTaskStackView != null) { + mTaskStackView.dump(innerPrefix, writer); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java index 1c433d8eb31c..fe91f421c202 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java @@ -456,7 +456,8 @@ public class TaskStackAnimationHelper { TaskStack stack = mStackView.getStack(); final float curScroll = stackScroller.getStackScroll(); - final float newScroll = stackLayout.getStackScrollForTask(newFocusedTask); + final float newScroll = stackScroller.getBoundedStackScroll( + stackLayout.getStackScrollForTask(newFocusedTask)); boolean willScrollToFront = newScroll > curScroll; boolean willScroll = Float.compare(newScroll, curScroll) != 0; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index 9eab0f60584f..b75a91e8c42b 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -29,6 +29,7 @@ import android.view.ViewDebug; import com.android.systemui.R; import com.android.systemui.recents.Recents; +import com.android.systemui.recents.RecentsActivity; import com.android.systemui.recents.RecentsActivityLaunchState; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsDebugFlags; @@ -38,6 +39,7 @@ import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -108,6 +110,8 @@ class Range { */ public class TaskStackLayoutAlgorithm { + private static final String TAG = "TaskStackLayoutAlgorithm"; + // The distribution of view bounds alpha // XXX: This is a hack because you can currently set the max alpha to be > 1f public static final float OUTLINE_ALPHA_MIN_VALUE = 0f; @@ -530,8 +534,12 @@ public class TaskStackLayoutAlgorithm { ? stack.indexOfStackTask(launchTask) : mNumStackTasks - 1; if (getInitialFocusState() == STATE_FOCUSED) { + int maxBottomOffset = mStackBottomOffset + mTaskRect.height(); + float maxBottomNormX = getNormalizedXFromFocusedY(maxBottomOffset, FROM_BOTTOM); + mFocusedRange.offset(0f); mMinScrollP = 0; - mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1); + mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) - + Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX))); if (launchState.launchedFromHome) { mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP); } else { @@ -555,7 +563,10 @@ public class TaskStackLayoutAlgorithm { Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX))); boolean scrollToFront = launchState.launchedFromHome || launchState.launchedViaDockGesture; - if (scrollToFront) { + if (launchState.launchedWithAltTab) { + mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP); + mInitialNormX = null; + } else if (scrollToFront) { mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP); mInitialNormX = null; } else { @@ -652,8 +663,9 @@ public class TaskStackLayoutAlgorithm { * Returns the default focus state. */ public int getInitialFocusState() { + RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); RecentsDebugFlags debugFlags = Recents.getDebugFlags(); - if (debugFlags.isPagingEnabled()) { + if (debugFlags.isPagingEnabled() || launchState.launchedWithAltTab) { return STATE_FOCUSED; } else { return STATE_UNFOCUSED; @@ -675,7 +687,6 @@ public class TaskStackLayoutAlgorithm { } /** - * * Returns the current stack state. */ public StackState getStackState() { @@ -1027,6 +1038,18 @@ public class TaskStackLayoutAlgorithm { } /** + * Returns the normalized x on the focused curve given an absolute Y position (relative to the + * stack height). + */ + private float getNormalizedXFromFocusedY(float y, @AnchorSide int fromSide) { + float offset = (fromSide == FROM_TOP) + ? mStackRect.height() - y + : y; + float offsetPct = offset / mStackRect.height(); + return mFocusedCurveInterpolator.getX(offsetPct); + } + + /** * Creates a new path for the focused curve. */ private Path constructFocusedCurve() { @@ -1036,10 +1059,13 @@ public class TaskStackLayoutAlgorithm { float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height(); float bottomPeekHeightPct = (float) (mStackBottomOffset + mFocusedBottomPeekHeight) / mStackRect.height(); + float minBottomPeekHeightPct = (float) (mFocusedTopPeekHeight + mTaskRect.height() - + mMinMargin) / mStackRect.height(); Path p = new Path(); p.moveTo(0f, 1f); p.lineTo(0.5f, 1f - topPeekHeightPct); - p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), bottomPeekHeightPct); + p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), Math.max(1f - minBottomPeekHeightPct, + bottomPeekHeightPct)); p.lineTo(1f, 0f); return p; } @@ -1133,4 +1159,44 @@ public class TaskStackLayoutAlgorithm { mBackOfStackTransform.visible = true; mFrontOfStackTransform.visible = true; } -} + + public void dump(String prefix, PrintWriter writer) { + String innerPrefix = prefix + " "; + + writer.print(prefix); writer.print(TAG); + writer.write(" numStackTasks="); writer.write(mNumStackTasks); + writer.println(); + + writer.print(innerPrefix); + writer.print("insets="); writer.print(Utilities.dumpRect(mSystemInsets)); + writer.print(" stack="); writer.print(Utilities.dumpRect(mStackRect)); + writer.print(" task="); writer.print(Utilities.dumpRect(mTaskRect)); + writer.print(" freeform="); writer.print(Utilities.dumpRect(mFreeformRect)); + writer.print(" actionButton="); writer.print(Utilities.dumpRect(mStackActionButtonRect)); + writer.println(); + + writer.print(innerPrefix); + writer.print("minScroll="); writer.print(mMinScrollP); + writer.print(" maxScroll="); writer.print(mMaxScrollP); + writer.print(" initialScroll="); writer.print(mInitialScrollP); + writer.println(); + + writer.print(innerPrefix); + writer.print("focusState="); writer.print(mFocusState); + writer.println(); + + if (mTaskIndexOverrideMap.size() > 0) { + for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) { + int taskId = mTaskIndexOverrideMap.keyAt(i); + float x = mTaskIndexMap.get(taskId); + float overrideX = mTaskIndexOverrideMap.get(taskId, 0f); + + writer.print(innerPrefix); + writer.print("taskId= "); writer.print(taskId); + writer.print(" x= "); writer.print(x); + writer.print(" overrideX= "); writer.print(overrideX); + writer.println(); + } + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 5416a4897666..13c8403ab0ab 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -90,6 +90,7 @@ import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -102,6 +103,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task> { + private static final String TAG = "TaskStackView"; + private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super"; private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE = "saved_instance_state_layout_focused_state"; @@ -2067,4 +2070,37 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mScreenPinningEnabled = ssp.getSystemSetting(getContext(), Settings.System.LOCK_TO_APP_ENABLED) != 0; } + + public void dump(String prefix, PrintWriter writer) { + String innerPrefix = prefix + " "; + String id = Integer.toHexString(System.identityHashCode(this)); + + writer.print(prefix); writer.print(TAG); + writer.print(" hasDefRelayout="); + writer.print(mDeferredTaskViewLayoutAnimation != null ? "Y" : "N"); + writer.print(" clipDirty="); writer.print(mTaskViewsClipDirty ? "Y" : "N"); + writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N"); + writer.print(" initialState="); writer.print(mInitialState); + writer.print(" inMeasureLayout="); writer.print(mInMeasureLayout ? "Y" : "N"); + writer.print(" enterAnimCompleted="); writer.print(mEnterAnimationComplete ? "Y" : "N"); + writer.print(" touchExplorationOn="); writer.print(mTouchExplorationEnabled ? "Y" : "N"); + writer.print(" screenPinningOn="); writer.print(mScreenPinningEnabled ? "Y" : "N"); + writer.print(" numIgnoreTasks="); writer.print(mIgnoreTasks.size()); + writer.print(" numViewPool="); writer.print(mViewPool.getViews().size()); + writer.print(" stableStackBounds="); writer.print(Utilities.dumpRect(mStableStackBounds)); + writer.print(" stackBounds="); writer.print(Utilities.dumpRect(mStackBounds)); + writer.print(" stableWindow="); writer.print(Utilities.dumpRect(mStableWindowRect)); + writer.print(" window="); writer.print(Utilities.dumpRect(mWindowRect)); + writer.print(" [0x"); writer.print(id); writer.print("]"); + writer.println(); + + if (mFocusedTask != null) { + writer.print(innerPrefix); + writer.print("Focused task: "); + mFocusedTask.dump(innerPrefix, writer); + } + + mLayoutAlgorithm.dump(innerPrefix, writer); + mStackScroller.dump(innerPrefix, writer); + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java index 583fb88e4069..19b3c943ae65 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java @@ -30,6 +30,8 @@ import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.recents.misc.Utilities; +import java.io.PrintWriter; + /* The scrolling logic for a TaskStackView */ public class TaskStackViewScroller { @@ -246,4 +248,10 @@ public class TaskStackViewScroller { mScroller.abortAnimation(); } } + + public void dump(String prefix, PrintWriter writer) { + writer.print(prefix); writer.print(TAG); + writer.print(" stackScroll:"); writer.print(mStackScrollP); + writer.println(); + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index ddd3ea163e57..d294c80bdf51 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -34,8 +34,6 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; * Controls the docked stack divider. */ public class Divider extends SystemUI { - private static final String TAG = "Divider"; - private int mDividerWindowWidth; private DividerWindowManager mWindowManager; private DividerView mView; private DockDividerVisibilityListener mDockDividerVisibilityListener; @@ -46,8 +44,6 @@ public class Divider extends SystemUI { @Override public void start() { mWindowManager = new DividerWindowManager(mContext); - mDividerWindowWidth = mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.docked_stack_divider_thickness); update(mContext.getResources().getConfiguration()); putComponent(Divider.class, this); mDockDividerVisibilityListener = new DockDividerVisibilityListener(); @@ -70,9 +66,11 @@ public class Divider extends SystemUI { mView = (DividerView) LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null); mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE); + final int size = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_divider_thickness); final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE; - final int width = landscape ? mDividerWindowWidth : MATCH_PARENT; - final int height = landscape ? MATCH_PARENT : mDividerWindowWidth; + final int width = landscape ? size : MATCH_PARENT; + final int height = landscape ? MATCH_PARENT : size; mWindowManager.add(mView, width, height); mView.setWindowManager(mWindowManager); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 8102fae28aaf..29b6908fb8c1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -91,6 +91,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.systemui.DejankUtils; import com.android.systemui.Interpolators; import com.android.systemui.R; @@ -100,6 +101,7 @@ import com.android.systemui.SystemUI; import com.android.systemui.assist.AssistManager; import com.android.systemui.recents.Recents; import com.android.systemui.statusbar.NotificationData.Entry; +import com.android.systemui.statusbar.NotificationGuts.OnGutsClosedListener; import com.android.systemui.statusbar.phone.NavigationBarView; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -114,12 +116,12 @@ import java.util.List; import java.util.Locale; import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH; -import static com.android.keyguard.KeyguardHostView.OnDismissAction; public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener, ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment, - ExpandableNotificationRow.OnExpandClickListener { + ExpandableNotificationRow.OnExpandClickListener, + OnGutsClosedListener { public static final String TAG = "StatusBar"; public static final boolean DEBUG = false; public static final boolean MULTIUSER_DEBUG = false; @@ -1010,6 +1012,7 @@ public abstract class BaseStatusBar extends SystemUI implements PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier()); row.setTag(sbn.getPackageName()); final NotificationGuts guts = row.getGuts(); + guts.setClosedListener(this); final String pkg = sbn.getPackageName(); String appname = pkg; Drawable pkgicon = null; @@ -1037,6 +1040,7 @@ public abstract class BaseStatusBar extends SystemUI implements settingsButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO); + guts.resetFalsingCheck(); startAppNotificationSettingsActivity(pkg, appUidF); } }); @@ -1047,24 +1051,43 @@ public abstract class BaseStatusBar extends SystemUI implements row.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - guts.saveImportance(sbn); - - int[] rowLocation = new int[2]; - int[] doneLocation = new int[2]; - row.getLocationOnScreen(rowLocation); - v.getLocationOnScreen(doneLocation); - - final int centerX = v.getWidth() / 2; - final int centerY = v.getHeight() / 2; - final int x = doneLocation[0] - rowLocation[0] + centerX; - final int y = doneLocation[1] - rowLocation[1] + centerY; - dismissPopups(x, y); + // If the user has security enabled, show challenge if the setting is changed. + if (guts.hasImportanceChanged() && isLockscreenPublicMode() && + (mState == StatusBarState.KEYGUARD + || mState == StatusBarState.SHADE_LOCKED)) { + OnDismissAction dismissAction = new OnDismissAction() { + @Override + public boolean onDismiss() { + saveImportanceCloseControls(sbn, row, guts, v); + return true; + } + }; + onLockedNotificationImportanceChange(dismissAction); + } else { + saveImportanceCloseControls(sbn, row, guts, v); + } } }); - guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey())); } + private void saveImportanceCloseControls(StatusBarNotification sbn, + ExpandableNotificationRow row, NotificationGuts guts, View done) { + guts.resetFalsingCheck(); + guts.saveImportance(sbn); + + int[] rowLocation = new int[2]; + int[] doneLocation = new int[2]; + row.getLocationOnScreen(rowLocation); + done.getLocationOnScreen(doneLocation); + + final int centerX = done.getWidth() / 2; + final int centerY = done.getHeight() / 2; + final int x = doneLocation[0] - rowLocation[0] + centerX; + final int y = doneLocation[1] - rowLocation[1] + centerY; + dismissPopups(x, y); + } + protected SwipeHelper.LongPressListener getNotificationLongClicker() { return new SwipeHelper.LongPressListener() { @Override @@ -1119,7 +1142,8 @@ public abstract class BaseStatusBar extends SystemUI implements } }); a.start(); - guts.setExposed(true); + guts.setExposed(true /* exposed */, + mState == StatusBarState.KEYGUARD /* needsFalsingProtection */); row.closeRemoteInput(); mStackScroller.onHeightChanged(null, true /* needsAnimation */); mNotificationGutsExposed = guts; @@ -1147,31 +1171,7 @@ public abstract class BaseStatusBar extends SystemUI implements public void dismissPopups(int x, int y, boolean resetGear, boolean animate) { if (mNotificationGutsExposed != null) { - final NotificationGuts v = mNotificationGutsExposed; - mNotificationGutsExposed = null; - - if (v.getWindowToken() == null) return; - if (x == -1 || y == -1) { - x = (v.getLeft() + v.getRight()) / 2; - y = (v.getTop() + v.getHeight() / 2); - } - final double horz = Math.max(v.getWidth() - x, x); - final double vert = Math.max(v.getHeight() - y, y); - final float r = (float) Math.hypot(horz, vert); - final Animator a = ViewAnimationUtils.createCircularReveal(v, - x, y, r, 0); - a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); - a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); - a.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - v.setVisibility(View.GONE); - } - }); - a.start(); - v.setExposed(false); - mStackScroller.onHeightChanged(null, true /* needsAnimation */); + mNotificationGutsExposed.closeControls(x, y, true /* notify */); } if (resetGear) { mStackScroller.resetExposedGearView(animate, true /* force */); @@ -1179,6 +1179,12 @@ public abstract class BaseStatusBar extends SystemUI implements } @Override + public void onGutsClosed(NotificationGuts guts) { + mStackScroller.onHeightChanged(null, true /* needsAnimation */); + mNotificationGutsExposed = null; + } + + @Override public void showRecentApps(boolean triggeredFromAltTab) { int msg = MSG_SHOW_RECENT_APPS; mHandler.removeMessages(msg); @@ -1450,6 +1456,8 @@ public abstract class BaseStatusBar extends SystemUI implements } } + protected void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {} + protected void onLockedRemoteInput(ExpandableNotificationRow row, View clickedView) {} @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java index 2b365dc743e9..977a77d59559 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java @@ -21,6 +21,9 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.hardware.input.InputManager; import android.os.Handler; import android.os.Looper; @@ -37,6 +40,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.KeyboardShortcutsReceiver; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -52,175 +56,191 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; /** * Contains functionality for handling keyboard shortcuts. */ -public class KeyboardShortcuts { +public final class KeyboardShortcuts { private static final String TAG = KeyboardShortcuts.class.getSimpleName(); - private static final SparseArray<String> SPECIAL_CHARACTER_NAMES = new SparseArray<>(); - private static final SparseArray<String> MODIFIER_NAMES = new SparseArray<>(); + private final SparseArray<String> mSpecialCharacterNames = new SparseArray<>(); + private final SparseArray<String> mModifierNames = new SparseArray<>(); + private final SparseArray<Drawable> mSpecialCharacterDrawables = new SparseArray<>(); + private final SparseArray<Drawable> mModifierDrawables = new SparseArray<>(); - private static void loadSpecialCharacterNames(Context context) { - SPECIAL_CHARACTER_NAMES.put( + private final Handler mHandler = new Handler(Looper.getMainLooper()); + private final Context mContext; + private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dismissKeyboardShortcutsDialog(); + } + }; + + private Dialog mKeyboardShortcutsDialog; + private KeyCharacterMap mKeyCharacterMap; + + public KeyboardShortcuts(Context context) { + this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light); + loadResources(context); + } + + private void loadResources(Context context) { + mSpecialCharacterNames.put( KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_BACK, context.getString(R.string.keyboard_key_back)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_DPAD_UP, context.getString(R.string.keyboard_key_dpad_up)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_DPAD_DOWN, context.getString(R.string.keyboard_key_dpad_down)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_DPAD_LEFT, context.getString(R.string.keyboard_key_dpad_left)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_DPAD_RIGHT, context.getString(R.string.keyboard_key_dpad_right)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_DPAD_CENTER, context.getString(R.string.keyboard_key_dpad_center)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_PERIOD, "."); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put(KeyEvent.KEYCODE_PERIOD, "."); + mSpecialCharacterNames.put( KeyEvent.KEYCODE_TAB, context.getString(R.string.keyboard_key_tab)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_SPACE, context.getString(R.string.keyboard_key_space)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_ENTER, context.getString(R.string.keyboard_key_enter)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_DEL, context.getString(R.string.keyboard_key_backspace)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, context.getString(R.string.keyboard_key_media_play_pause)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_MEDIA_STOP, context.getString(R.string.keyboard_key_media_stop)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_MEDIA_NEXT, context.getString(R.string.keyboard_key_media_next)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS, context.getString(R.string.keyboard_key_media_previous)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_REWIND, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_REWIND, context.getString(R.string.keyboard_key_media_rewind)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, context.getString(R.string.keyboard_key_media_fast_forward)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_PAGE_UP, context.getString(R.string.keyboard_key_page_up)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_PAGE_DOWN, context.getString(R.string.keyboard_key_page_down)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_A, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_A, context.getString(R.string.keyboard_key_button_template, "A")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_B, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_B, context.getString(R.string.keyboard_key_button_template, "B")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_C, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_C, context.getString(R.string.keyboard_key_button_template, "C")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_X, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_X, context.getString(R.string.keyboard_key_button_template, "X")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Y, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Y, context.getString(R.string.keyboard_key_button_template, "Y")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Z, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Z, context.getString(R.string.keyboard_key_button_template, "Z")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L1, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L1, context.getString(R.string.keyboard_key_button_template, "L1")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R1, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R1, context.getString(R.string.keyboard_key_button_template, "R1")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L2, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L2, context.getString(R.string.keyboard_key_button_template, "L2")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R2, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R2, context.getString(R.string.keyboard_key_button_template, "R2")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_START, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_START, context.getString(R.string.keyboard_key_button_template, "Start")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_SELECT, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_SELECT, context.getString(R.string.keyboard_key_button_template, "Select")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_MODE, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_MODE, context.getString(R.string.keyboard_key_button_template, "Mode")); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_FORWARD_DEL, context.getString(R.string.keyboard_key_forward_del)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ESCAPE, "Esc"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SYSRQ, "SysRq"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BREAK, "Break"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock"); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put(KeyEvent.KEYCODE_ESCAPE, "Esc"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_SYSRQ, "SysRq"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_BREAK, "Break"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock"); + mSpecialCharacterNames.put( KeyEvent.KEYCODE_MOVE_HOME, context.getString(R.string.keyboard_key_move_home)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_MOVE_END, context.getString(R.string.keyboard_key_move_end)); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put( KeyEvent.KEYCODE_INSERT, context.getString(R.string.keyboard_key_insert)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F1, "F1"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F2, "F2"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F3, "F3"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F4, "F4"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F5, "F5"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F6, "F6"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F7, "F7"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F8, "F8"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F9, "F9"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F10, "F10"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F11, "F11"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F12, "F12"); - SPECIAL_CHARACTER_NAMES.put( + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F1, "F1"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F2, "F2"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F3, "F3"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F4, "F4"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F5, "F5"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F6, "F6"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F7, "F7"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F8, "F8"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F9, "F9"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F10, "F10"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F11, "F11"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_F12, "F12"); + mSpecialCharacterNames.put( KeyEvent.KEYCODE_NUM_LOCK, context.getString(R.string.keyboard_key_num_lock)); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_0, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_0, context.getString(R.string.keyboard_key_numpad_template, "0")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_1, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_1, context.getString(R.string.keyboard_key_numpad_template, "1")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_2, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_2, context.getString(R.string.keyboard_key_numpad_template, "2")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_3, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_3, context.getString(R.string.keyboard_key_numpad_template, "3")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_4, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_4, context.getString(R.string.keyboard_key_numpad_template, "4")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_5, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_5, context.getString(R.string.keyboard_key_numpad_template, "5")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_6, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_6, context.getString(R.string.keyboard_key_numpad_template, "6")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_7, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_7, context.getString(R.string.keyboard_key_numpad_template, "7")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_8, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_8, context.getString(R.string.keyboard_key_numpad_template, "8")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_9, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_9, context.getString(R.string.keyboard_key_numpad_template, "9")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, context.getString(R.string.keyboard_key_numpad_template, "/")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, context.getString(R.string.keyboard_key_numpad_template, "*")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, context.getString(R.string.keyboard_key_numpad_template, "-")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ADD, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ADD, context.getString(R.string.keyboard_key_numpad_template, "+")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DOT, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DOT, context.getString(R.string.keyboard_key_numpad_template, ".")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_COMMA, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_COMMA, context.getString(R.string.keyboard_key_numpad_template, ",")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ENTER, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ENTER, context.getString(R.string.keyboard_key_numpad_template, context.getString(R.string.keyboard_key_enter))); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_EQUALS, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_EQUALS, context.getString(R.string.keyboard_key_numpad_template, "=")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN, context.getString(R.string.keyboard_key_numpad_template, "(")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN, + mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN, context.getString(R.string.keyboard_key_numpad_template, ")")); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_EISU, "英数"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MUHENKAN, "無変換"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_HENKAN, "変換"); - SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_EISU, "英数"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_MUHENKAN, "無変換"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_HENKAN, "変換"); + mSpecialCharacterNames.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな"); - MODIFIER_NAMES.put(KeyEvent.META_META_ON, "Meta"); - MODIFIER_NAMES.put(KeyEvent.META_CTRL_ON, "Ctrl"); - MODIFIER_NAMES.put(KeyEvent.META_ALT_ON, "Alt"); - MODIFIER_NAMES.put(KeyEvent.META_SHIFT_ON, "Shift"); - MODIFIER_NAMES.put(KeyEvent.META_SYM_ON, "Sym"); - MODIFIER_NAMES.put(KeyEvent.META_FUNCTION_ON, "Fn"); - } + mModifierNames.put(KeyEvent.META_META_ON, "Meta"); + mModifierNames.put(KeyEvent.META_CTRL_ON, "Ctrl"); + mModifierNames.put(KeyEvent.META_ALT_ON, "Alt"); + mModifierNames.put(KeyEvent.META_SHIFT_ON, "Shift"); + mModifierNames.put(KeyEvent.META_SYM_ON, "Sym"); + mModifierNames.put(KeyEvent.META_FUNCTION_ON, "Fn"); - private final Handler mHandler = new Handler(Looper.getMainLooper()); - private final Context mContext; - private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dismissKeyboardShortcutsDialog(); - } - }; - - private Dialog mKeyboardShortcutsDialog; - private KeyCharacterMap mKeyCharacterMap; + mSpecialCharacterDrawables.put( + KeyEvent.KEYCODE_DEL, context.getDrawable(R.drawable.ic_ksh_key_backspace)); + mSpecialCharacterDrawables.put( + KeyEvent.KEYCODE_ENTER, context.getDrawable(R.drawable.ic_ksh_key_enter)); + mSpecialCharacterDrawables.put( + KeyEvent.KEYCODE_DPAD_UP, context.getDrawable(R.drawable.ic_ksh_key_up)); + mSpecialCharacterDrawables.put( + KeyEvent.KEYCODE_DPAD_RIGHT, context.getDrawable(R.drawable.ic_ksh_key_right)); + mSpecialCharacterDrawables.put( + KeyEvent.KEYCODE_DPAD_DOWN, context.getDrawable(R.drawable.ic_ksh_key_down)); + mSpecialCharacterDrawables.put( + KeyEvent.KEYCODE_DPAD_LEFT, context.getDrawable(R.drawable.ic_ksh_key_left)); - public KeyboardShortcuts(Context context) { - this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light); - if (SPECIAL_CHARACTER_NAMES.size() == 0) { - loadSpecialCharacterNames(context); - } + mModifierDrawables.put( + KeyEvent.META_META_ON, context.getDrawable(R.drawable.ic_ksh_key_meta)); } public void toggleKeyboardShortcuts(int deviceId) { @@ -343,6 +363,8 @@ public class KeyboardShortcuts { List<KeyboardShortcutGroup> keyboardShortcutGroups) { LayoutInflater inflater = LayoutInflater.from(mContext); final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size(); + // Needed to be able to scale the image items to the same height as the text items. + final int shortcutTextItemHeight = getShortcutTextItemHeight(inflater); for (int i = 0; i < keyboardShortcutGroupsSize; i++) { KeyboardShortcutGroup group = keyboardShortcutGroups.get(i); TextView categoryTitle = (TextView) inflater.inflate( @@ -364,7 +386,7 @@ public class KeyboardShortcuts { Log.w(TAG, "Keyboard Shortcut contains key not on device, skipping."); continue; } - List<String> shortcutKeys = getHumanReadableShortcutKeys(info); + List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info); if (shortcutKeys == null) { // Ignore shortcuts we can't display keys for. Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping."); @@ -380,11 +402,26 @@ public class KeyboardShortcuts { .findViewById(R.id.keyboard_shortcuts_item_container); final int shortcutKeysSize = shortcutKeys.size(); for (int k = 0; k < shortcutKeysSize; k++) { - String shortcutKey = shortcutKeys.get(k); - TextView shortcutKeyView = (TextView) inflater.inflate( - R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false); - shortcutKeyView.setText(shortcutKey); - shortcutItemsContainer.addView(shortcutKeyView); + StringOrDrawable shortcutRepresentation = shortcutKeys.get(k); + if (shortcutRepresentation.drawable != null) { + ImageView shortcutKeyIconView = (ImageView) inflater.inflate( + R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer, + false); + Bitmap bitmap = Bitmap.createBitmap(shortcutTextItemHeight, + shortcutTextItemHeight, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(), + canvas.getHeight()); + shortcutRepresentation.drawable.draw(canvas); + shortcutKeyIconView.setImageBitmap(bitmap); + shortcutItemsContainer.addView(shortcutKeyIconView); + } else if (shortcutRepresentation.string != null) { + TextView shortcutKeyTextView = (TextView) inflater.inflate( + R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, + false); + shortcutKeyTextView.setText(shortcutRepresentation.string); + shortcutItemsContainer.addView(shortcutKeyTextView); + } } shortcutContainer.addView(shortcutView); } @@ -398,16 +435,29 @@ public class KeyboardShortcuts { } } - private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) { - List<String> shortcutKeys = getHumanReadableModifiers(info); + private int getShortcutTextItemHeight(LayoutInflater inflater) { + TextView shortcutKeyTextView = (TextView) inflater.inflate( + R.layout.keyboard_shortcuts_key_view, null, false); + shortcutKeyTextView.measure( + View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + return shortcutKeyTextView.getMeasuredHeight() + - shortcutKeyTextView.getPaddingTop() + - shortcutKeyTextView.getPaddingBottom(); + } + + private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) { + List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info); if (shortcutKeys == null) { return null; } - String displayLabelString; + String displayLabelString = null; + Drawable displayLabelDrawable = null; if (info.getBaseCharacter() > Character.MIN_VALUE) { displayLabelString = String.valueOf(info.getBaseCharacter()); - } else if (SPECIAL_CHARACTER_NAMES.get(info.getKeycode()) != null) { - displayLabelString = SPECIAL_CHARACTER_NAMES.get(info.getKeycode()); + } else if (mSpecialCharacterDrawables.get(info.getKeycode()) != null) { + displayLabelDrawable = mSpecialCharacterDrawables.get(info.getKeycode()); + } else if (mSpecialCharacterNames.get(info.getKeycode()) != null) { + displayLabelString = mSpecialCharacterNames.get(info.getKeycode()); } else { // Special case for shortcuts with no base key or keycode. if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) { @@ -422,20 +472,31 @@ public class KeyboardShortcuts { return null; } } - shortcutKeys.add(displayLabelString.toUpperCase()); + + if (displayLabelDrawable != null) { + shortcutKeys.add(new StringOrDrawable(displayLabelDrawable)); + } else if (displayLabelString != null) { + shortcutKeys.add(new StringOrDrawable(displayLabelString.toUpperCase())); + } return shortcutKeys; } - private List<String> getHumanReadableModifiers(KeyboardShortcutInfo info) { - final List<String> shortcutKeys = new ArrayList<>(); + private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) { + final List<StringOrDrawable> shortcutKeys = new ArrayList<>(); int modifiers = info.getModifiers(); if (modifiers == 0) { return shortcutKeys; } - for(int i = 0; i < MODIFIER_NAMES.size(); ++i) { - final int supportedModifier = MODIFIER_NAMES.keyAt(i); + for(int i = 0; i < mModifierNames.size(); ++i) { + final int supportedModifier = mModifierNames.keyAt(i); if ((modifiers & supportedModifier) != 0) { - shortcutKeys.add(MODIFIER_NAMES.get(supportedModifier).toUpperCase()); + if (mModifierDrawables.get(supportedModifier) != null) { + shortcutKeys.add(new StringOrDrawable( + mModifierDrawables.get(supportedModifier))); + } else { + shortcutKeys.add(new StringOrDrawable( + mModifierNames.get(supportedModifier).toUpperCase())); + } modifiers &= ~supportedModifier; } } @@ -445,4 +506,17 @@ public class KeyboardShortcuts { } return shortcutKeys; } + + private static final class StringOrDrawable { + public String string; + public Drawable drawable; + + public StringOrDrawable(String string) { + this.string = string; + } + + public StringOrDrawable(Drawable drawable) { + this.drawable = drawable; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java index 45a24a0b3822..3c464d5a1819 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java @@ -16,28 +16,35 @@ package com.android.systemui.statusbar; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.app.INotificationManager; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.util.AttributeSet; import android.view.View; +import android.view.ViewAnimationUtils; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RadioButton; +import android.widget.RadioGroup; import android.widget.SeekBar; import android.widget.TextView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.settingslib.Utils; +import com.android.systemui.Interpolators; import com.android.systemui.R; +import com.android.systemui.statusbar.stack.StackStateAnimator; import com.android.systemui.tuner.TunerService; /** @@ -46,6 +53,8 @@ import com.android.systemui.tuner.TunerService; public class NotificationGuts extends LinearLayout implements TunerService.Tunable { public static final String SHOW_SLIDER = "show_importance_slider"; + private static final long CLOSE_GUTS_DELAY = 8000; + private Drawable mBackground; private int mClipTopAmount; private int mActualHeight; @@ -59,10 +68,35 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab private RadioButton mSilent; private RadioButton mReset; + private Handler mHandler; + private Runnable mFalsingCheck; + private boolean mNeedsFalsingProtection; + private OnGutsClosedListener mListener; + + public interface OnGutsClosedListener { + public void onGutsClosed(NotificationGuts guts); + } + public NotificationGuts(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); TunerService.get(mContext).addTunable(this, SHOW_SLIDER); + mHandler = new Handler(); + mFalsingCheck = new Runnable() { + @Override + public void run() { + if (mNeedsFalsingProtection && mExposed) { + closeControls(-1 /* x */, -1 /* y */, true /* notify */); + } + } + }; + } + + public void resetFalsingCheck() { + mHandler.removeCallbacks(mFalsingCheck); + if (mNeedsFalsingProtection && mExposed) { + mHandler.postDelayed(mFalsingCheck, CLOSE_GUTS_DELAY); + } } @Override @@ -130,30 +164,23 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab importanceSlider.setVisibility(View.VISIBLE); importanceButtons.setVisibility(View.GONE); } else { - int userImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED; + mStartingImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED; try { - userImportance = + mStartingImportance = mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid()); } catch (RemoteException e) {} - bindToggles(importanceButtons, userImportance, systemApp); + bindToggles(importanceButtons, mStartingImportance, systemApp); importanceButtons.setVisibility(View.VISIBLE); importanceSlider.setVisibility(View.GONE); } } + public boolean hasImportanceChanged() { + return mStartingImportance != getSelectedImportance(); + } + void saveImportance(final StatusBarNotification sbn) { - int progress; - if (mSeekBar!= null && mSeekBar.isShown()) { - progress = mSeekBar.getProgress(); - } else { - if (mBlock.isChecked()) { - progress = NotificationListenerService.Ranking.IMPORTANCE_NONE; - } else if (mSilent.isChecked()) { - progress = NotificationListenerService.Ranking.IMPORTANCE_LOW; - } else { - progress = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED; - } - } + int progress = getSelectedImportance(); MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE, progress - mStartingImportance); try { @@ -163,8 +190,29 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab } } + private int getSelectedImportance() { + if (mSeekBar!= null && mSeekBar.isShown()) { + return mSeekBar.getProgress(); + } else { + if (mBlock.isChecked()) { + return NotificationListenerService.Ranking.IMPORTANCE_NONE; + } else if (mSilent.isChecked()) { + return NotificationListenerService.Ranking.IMPORTANCE_LOW; + } else { + return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED; + } + } + } + private void bindToggles(final View importanceButtons, final int importance, final boolean systemApp) { + ((RadioGroup) importanceButtons).setOnCheckedChangeListener( + new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + resetFalsingCheck(); + } + }); mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance); mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance); mReset = (RadioButton) importanceButtons.findViewById(R.id.reset_importance); @@ -198,6 +246,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + resetFalsingCheck(); if (progress < minProgress) { seekBar.setProgress(minProgress); progress = minProgress; @@ -210,7 +259,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab @Override public void onStartTrackingTouch(SeekBar seekBar) { - // no-op + resetFalsingCheck(); } @Override @@ -256,6 +305,38 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab mSeekBar.setProgress(mStartingImportance); } + public void closeControls(int x, int y, boolean notify) { + if (getWindowToken() == null) { + if (notify && mListener != null) { + mListener.onGutsClosed(this); + } + return; + } + if (x == -1 || y == -1) { + x = (getLeft() + getRight()) / 2; + y = (getTop() + getHeight() / 2); + } + final double horz = Math.max(getWidth() - x, x); + final double vert = Math.max(getHeight() - y, y); + final float r = (float) Math.hypot(horz, vert); + final Animator a = ViewAnimationUtils.createCircularReveal(this, + x, y, r, 0); + a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); + a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); + a.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + setVisibility(View.GONE); + } + }); + a.start(); + setExposed(false, mNeedsFalsingProtection); + if (notify && mListener != null) { + mListener.onGutsClosed(this); + } + } + public void setActualHeight(int actualHeight) { mActualHeight = actualHeight; invalidate(); @@ -277,8 +358,18 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab return false; } - public void setExposed(boolean exposed) { + public void setClosedListener(OnGutsClosedListener listener) { + mListener = listener; + } + + public void setExposed(boolean exposed, boolean needsFalsingProtection) { mExposed = exposed; + mNeedsFalsingProtection = needsFalsingProtection; + if (mExposed && mNeedsFalsingProtection) { + resetFalsingCheck(); + } else { + mHandler.removeCallbacks(mFalsingCheck); + } } public boolean areGutsExposed() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java index c70aad2d4198..06d79a7f9124 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java @@ -131,11 +131,8 @@ public class NotificationHeaderUtil { mComparators.add(HeaderProcessor.forTextView(mRow, com.android.internal.R.id.app_name_text)); mComparators.add(HeaderProcessor.forTextView(mRow, - com.android.internal.R.id.header_sub_text)); - mComparators.add(HeaderProcessor.forTextView(mRow, - com.android.internal.R.id.header_content_info)); - mDividers.add(com.android.internal.R.id.sub_text_divider); - mDividers.add(com.android.internal.R.id.content_info_divider); + com.android.internal.R.id.header_text)); + mDividers.add(com.android.internal.R.id.header_text_divider); mDividers.add(com.android.internal.R.id.time_divider); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 56a7dbed52cb..68593484a862 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -76,6 +76,8 @@ public class NavigationBarView extends LinearLayout { private Drawable mHomeDefaultIcon, mHomeCarModeIcon; private Drawable mRecentIcon; private Drawable mDockedIcon; + private Drawable mImeIcon; + private Drawable mMenuIcon; private NavigationBarGestureHelper mGestureHelper; private DeadZone mDeadZone; @@ -270,7 +272,8 @@ public class NavigationBarView extends LinearLayout { } private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) { - if (oldConfig.orientation != newConfig.orientation) { + if (oldConfig.orientation != newConfig.orientation + || oldConfig.densityDpi != newConfig.densityDpi) { mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked); } if (oldConfig.densityDpi != newConfig.densityDpi) { @@ -280,8 +283,10 @@ public class NavigationBarView extends LinearLayout { mBackAltLandIcon = mBackAltIcon; mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home); - mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent); + mMenuIcon = ctx.getDrawable(R.drawable.ic_sysbar_menu); + mImeIcon = ctx.getDrawable(R.drawable.ic_ime_switcher_default); + updateCarModeIcons(ctx); } } @@ -348,9 +353,11 @@ public class NavigationBarView extends LinearLayout { final boolean showImeButton = ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0); getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE); + getImeSwitchButton().setImageDrawable(mImeIcon); // Update menu button in case the IME state has changed. setMenuVisibility(mShowMenu, true); + getMenuButton().setImageDrawable(mMenuIcon); setDisabledFlags(mDisabledFlags, true); } @@ -595,14 +602,12 @@ public class NavigationBarView extends LinearLayout { super.onConfigurationChanged(newConfig); boolean uiCarModeChanged = updateCarMode(newConfig); updateTaskSwitchHelper(); - if (uiCarModeChanged) { - // uiMode changed either from carmode or to carmode. - // replace the nav bar button icons based on which mode - // we are switching to. - setNavigationIconHints(mNavigationIconHints, true); - } updateIcons(getContext(), mConfiguration, newConfig); updateRecentsIcon(); + if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi) { + // If car mode or density changes, we need to reset the icons. + setNavigationIconHints(mNavigationIconHints, true); + } mConfiguration.updateFrom(newConfig); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index fce893e0b5f6..bf58592c7ca9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -3303,10 +3303,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, protected void loadDimens() { final Resources res = mContext.getResources(); + int oldBarHeight = mNaturalBarHeight; mNaturalBarHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); - - mMaxAllowedKeyguardNotifications = res.getInteger(R.integer.keyguard_max_notification_count); + if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) { + mStatusBarWindowManager.setBarHeight(mNaturalBarHeight); + } + mMaxAllowedKeyguardNotifications = res.getInteger( + R.integer.keyguard_max_notification_count); if (DEBUG) Log.v(TAG, "updateResources"); } @@ -4193,6 +4197,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override + public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) { + mLeaveOpenOnKeyguardHide = true; + dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */); + } + + @Override protected void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) { mLeaveOpenOnKeyguardHide = true; showBouncer(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index b271380e496c..888e19c50f38 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -323,6 +323,11 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { apply(mCurrentState); } + public void setBarHeight(int barHeight) { + mBarHeight = barHeight; + apply(mCurrentState); + } + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("StatusBarWindowManager state:"); pw.println(mCurrentState); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index ab44b6a277ee..ea0bdf29c25c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -23,6 +23,7 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -52,6 +53,7 @@ import com.android.settingslib.RestrictedLockUtils; import com.android.systemui.BitmapHelper; import com.android.systemui.GuestResumeSessionReceiver; import com.android.systemui.R; +import com.android.systemui.SystemUISecondaryUserService; import com.android.systemui.qs.QSTile; import com.android.systemui.qs.tiles.UserDetailView; import com.android.systemui.statusbar.phone.ActivityStarter; @@ -101,6 +103,8 @@ public class UserSwitcherController { private boolean mSimpleUserSwitcher; private boolean mAddUsersWhenLocked; private boolean mPauseRefreshUsers; + private int mSecondaryUser = UserHandle.USER_NULL; + private Intent mSecondaryUserServiceIntent; private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2); public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor, @@ -121,6 +125,8 @@ public class UserSwitcherController { mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter, null /* permission */, null /* scheduler */); + mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class); + filter = new IntentFilter(); filter.addAction(ACTION_REMOVE_GUEST); filter.addAction(ACTION_LOGOUT_USER); @@ -477,6 +483,20 @@ public class UserSwitcherController { } notifyAdapters(); + // Disconnect from the old secondary user's service + if (mSecondaryUser != UserHandle.USER_NULL) { + context.stopServiceAsUser(mSecondaryUserServiceIntent, + UserHandle.of(mSecondaryUser)); + mSecondaryUser = UserHandle.USER_NULL; + } + // Connect to the new secondary user's service (purely to ensure that a persistent + // SystemUI application is created for that user) + if (userInfo != null && !userInfo.isPrimary()) { + context.startServiceAsUser(mSecondaryUserServiceIntent, + UserHandle.of(userInfo.id)); + mSecondaryUser = userInfo.id; + } + if (UserManager.isSplitSystemUser() && userInfo != null && !userInfo.isGuest() && userInfo.id != UserHandle.USER_SYSTEM) { showLogoutNotification(currentId); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java index 2f4e799fd69b..ee483e5a40e2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java @@ -640,7 +640,7 @@ public class NotificationChildrenContainer extends ViewGroup { firstChild = false; } ExpandableNotificationRow child = mChildren.get(i); - minExpandHeight += child.getMinHeight(); + minExpandHeight += child.getSingleLineView().getHeight(); visibleChildren++; } minExpandHeight += mCollapsedBottompadding; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 46a49ee29e28..fa37e2257a61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -918,7 +918,7 @@ public class NotificationStackScrollLayout extends ViewGroup int positionInLinearLayout = getPositionInLinearLayout(v); int targetScroll = positionInLinearLayout + expandableView.getActualHeight() + - mBottomInset - getHeight() + getTopPadding(); + getImeInset() - getHeight() + getTopPadding(); if (mOwnScrollY < targetScroll) { mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY); mDontReportNextOverScroll = true; @@ -928,8 +928,7 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { - mBottomInset = Math.max(0, insets.getSystemWindowInsetBottom() - - (getRootView().getHeight() - getHeight())); + mBottomInset = insets.getSystemWindowInsetBottom(); int range = getScrollRange(); if (mOwnScrollY > range) { @@ -987,7 +986,8 @@ public class NotificationStackScrollLayout extends ViewGroup } public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) { - mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration); + mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration, + true /* isDismissAll */); } public void snapViewIfNeeded(View child) { @@ -1498,23 +1498,17 @@ public class NotificationStackScrollLayout extends ViewGroup } private int getScrollRange() { - int scrollRange = 0; - ExpandableView firstChild = (ExpandableView) getFirstChildNotGone(); - if (firstChild != null) { - int contentHeight = getContentHeight(); - scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize - + mBottomStackSlowDownHeight); - if (scrollRange > 0) { - int firstChildMaxExpandHeight = getMaxExpandHeight(firstChild); - // We want to at least be able collapse the first item and not ending in a weird - // end state. - scrollRange = Math.max(scrollRange, firstChildMaxExpandHeight - - firstChild.getMinHeight()); - } - } - int imeOverlap = Math.max(0, - getContentHeight() - (getHeight() - mBottomInset)); - return scrollRange + imeOverlap; + int contentHeight = getContentHeight(); + int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize + + mBottomStackSlowDownHeight); + int imeInset = getImeInset(); + scrollRange += Math.min(imeInset, Math.max(0, + getContentHeight() - (getHeight() - imeInset))); + return scrollRange; + } + + private int getImeInset() { + return Math.max(0, mBottomInset - (getRootView().getHeight() - getHeight())); } /** @@ -3201,9 +3195,6 @@ public class NotificationStackScrollLayout extends ViewGroup disableClipOptimization(); } handleDismissAllClipping(); - if (mCurrIconRow != null && mCurrIconRow.isVisible()) { - mCurrIconRow.getNotificationParent().animateTranslateNotification(0 /* left target */); - } } private void handleDismissAllClipping() { @@ -3463,8 +3454,10 @@ public class NotificationStackScrollLayout extends ViewGroup } private class NotificationSwipeHelper extends SwipeHelper { - private static final long GEAR_SHOW_DELAY = 60; + private static final long SHOW_GEAR_DELAY = 60; + private static final long COVER_GEAR_DELAY = 4000; private CheckForDrag mCheckForDrag; + private Runnable mFalsingCheck; private Handler mHandler; private boolean mGearSnappedTo; private boolean mGearSnappedOnLeft; @@ -3472,6 +3465,12 @@ public class NotificationStackScrollLayout extends ViewGroup public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) { super(swipeDirection, callback, context); mHandler = new Handler(); + mFalsingCheck = new Runnable() { + @Override + public void run() { + resetExposedGearView(true /* animate */, true /* force */); + } + }; } @Override @@ -3486,6 +3485,7 @@ public class NotificationStackScrollLayout extends ViewGroup } mCheckForDrag = null; mCurrIconRow = null; + mHandler.removeCallbacks(mFalsingCheck); // Slide back any notifications that might be showing a gear resetExposedGearView(true /* animate */, false /* force */); @@ -3499,6 +3499,8 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public void onMoveUpdate(View view, float translation, float delta) { + mHandler.removeCallbacks(mFalsingCheck); + if (mCurrIconRow != null) { mCurrIconRow.setSnapping(false); // If we're moving, we're not snapping. @@ -3624,6 +3626,12 @@ public class NotificationStackScrollLayout extends ViewGroup setSnappedToGear(true); } onDragCancelled(animView); + + // If we're on the lockscreen we want to false this. + if (mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD) { + mHandler.removeCallbacks(mFalsingCheck); + mHandler.postDelayed(mFalsingCheck, COVER_GEAR_DELAY); + } super.snapChild(animView, target, velocity); } @@ -3646,10 +3654,7 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public Animator getViewTranslationAnimator(View v, float target, AnimatorUpdateListener listener) { - if (mDismissAllInProgress) { - // When dismissing all, we translate the entire view instead. - return super.getViewTranslationAnimator(v, target, listener); - } else if (v instanceof ExpandableNotificationRow) { + if (v instanceof ExpandableNotificationRow) { return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener); } else { return super.getViewTranslationAnimator(v, target, listener); @@ -3658,22 +3663,12 @@ public class NotificationStackScrollLayout extends ViewGroup @Override public void setTranslation(View v, float translate) { - if (mDismissAllInProgress) { - // When dismissing all, we translate the entire view instead. - super.setTranslation(v, translate); - } else { - ((ExpandableView) v).setTranslation(translate); - } + ((ExpandableView) v).setTranslation(translate); } @Override public float getTranslation(View v) { - if (mDismissAllInProgress) { - // When dismissing all, we translate the entire view instead. - return super.getTranslation(v); - } else { - return ((ExpandableView) v).getTranslation(); - } + return ((ExpandableView) v).getTranslation(); } public void closeControlsIfOutsideTouch(MotionEvent ev) { @@ -3740,7 +3735,7 @@ public class NotificationStackScrollLayout extends ViewGroup private void checkForDrag() { if (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag)) { mCheckForDrag = new CheckForDrag(); - mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY); + mHandler.postDelayed(mCheckForDrag, SHOW_GEAR_DELAY); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java index 6a8165942cc0..a30f50775f77 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java @@ -198,7 +198,7 @@ public class TileLifecycleManagerTests extends AndroidTestCase { } private void waitForCallback(String callback) { - for (int i = 0; i < 25; i++) { + for (int i = 0; i < 50; i++) { if (mCallbacks.contains(callback)) { mCallbacks.remove(callback); return; @@ -229,7 +229,7 @@ public class TileLifecycleManagerTests extends AndroidTestCase { } }); try { - lock.wait(5000); + lock.wait(10000); } catch (InterruptedException e) { } } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index e256ecd6b85e..27417332f7d1 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -2151,7 +2151,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { MagnificationController getMagnificationController() { synchronized (mLock) { if (mMagnificationController == null) { - mMagnificationController = new MagnificationController(mContext, this); + mMagnificationController = new MagnificationController(mContext, this, mLock); mMagnificationController.register(); mMagnificationController.setUserId(mCurrentUserId); } diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java index e15b785ba718..b2196bf946e2 100644 --- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java @@ -72,7 +72,7 @@ class MagnificationController { */ private static final float MIN_PERSISTED_SCALE = 2.0f; - private final Object mLock = new Object(); + private final Object mLock; /** * The current magnification spec. If an animation is running, this @@ -97,12 +97,13 @@ class MagnificationController { private int mUserId; - public MagnificationController(Context context, AccessibilityManagerService ams) { + public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) { mAms = ams; mContentResolver = context.getContentResolver(); mScreenStateObserver = new ScreenStateObserver(context, this); mWindowStateObserver = new WindowStateObserver(context, this); mSpecAnimationBridge = new SpecAnimationBridge(context); + mLock = lock; } /** diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java index a0b5c154c13f..e98b4aa6e267 100644 --- a/services/core/java/com/android/server/AnyMotionDetector.java +++ b/services/core/java/com/android/server/AnyMotionDetector.java @@ -108,63 +108,71 @@ public class AnyMotionDetector { public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm, DeviceIdleCallback callback, float thresholdAngle) { if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated."); - mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mWakeLock.setReferenceCounted(false); - mHandler = handler; - mSensorManager = sm; - mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - mMeasurementInProgress = false; - mState = STATE_INACTIVE; - mCallback = callback; - mThresholdAngle = thresholdAngle; - mRunningStats = new RunningSignalStats(); - mNumSufficientSamples = (int) Math.ceil( - ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS)); - if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples); + synchronized (mLock) { + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + mWakeLock.setReferenceCounted(false); + mHandler = handler; + mSensorManager = sm; + mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + mMeasurementInProgress = false; + mState = STATE_INACTIVE; + mCallback = callback; + mThresholdAngle = thresholdAngle; + mRunningStats = new RunningSignalStats(); + mNumSufficientSamples = (int) Math.ceil( + ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS)); + if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples); + } } /* * Acquire accel data until we determine AnyMotion status. */ public void checkForAnyMotion() { - if (DEBUG) Slog.d(TAG, "checkForAnyMotion(). mState = " + mState); + if (DEBUG) { + Slog.d(TAG, "checkForAnyMotion(). mState = " + mState); + } if (mState != STATE_ACTIVE) { - mState = STATE_ACTIVE; - if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE."); - mCurrentGravityVector = null; - mPreviousGravityVector = null; - startOrientationMeasurement(); + synchronized (mLock) { + mState = STATE_ACTIVE; + if (DEBUG) { + Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE."); + } + mCurrentGravityVector = null; + mPreviousGravityVector = null; + mWakeLock.acquire(); + startOrientationMeasurementLocked(); + } } } public void stop() { if (mState == STATE_ACTIVE) { - mState = STATE_INACTIVE; - if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE."); - if (mMeasurementInProgress) { - mMeasurementInProgress = false; - mSensorManager.unregisterListener(mListener); + synchronized (mLock) { + mState = STATE_INACTIVE; + if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE."); + if (mMeasurementInProgress) { + mMeasurementInProgress = false; + mSensorManager.unregisterListener(mListener); + } + mHandler.removeCallbacks(mMeasurementTimeout); + mHandler.removeCallbacks(mSensorRestart); + mCurrentGravityVector = null; + mPreviousGravityVector = null; + mWakeLock.release(); } - mHandler.removeCallbacks(mMeasurementTimeout); - mHandler.removeCallbacks(mSensorRestart); - mWakeLock.release(); - mCurrentGravityVector = null; - mPreviousGravityVector = null; } } - private void startOrientationMeasurement() { - if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" + + private void startOrientationMeasurementLocked() { + if (DEBUG) Slog.d(TAG, "startOrientationMeasurementLocked: mMeasurementInProgress=" + mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null)); - if (!mMeasurementInProgress && mAccelSensor != null) { if (mSensorManager.registerListener(mListener, mAccelSensor, SAMPLING_INTERVAL_MILLIS * 1000)) { - mWakeLock.acquire(); mMeasurementInProgress = true; mRunningStats.reset(); } - Message msg = Message.obtain(mHandler, mMeasurementTimeout); msg.setAsynchronous(true); mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS); @@ -178,7 +186,6 @@ public class AnyMotionDetector { if (mMeasurementInProgress) { mSensorManager.unregisterListener(mListener); mHandler.removeCallbacks(mMeasurementTimeout); - mWakeLock.release(); long detectionEndTime = SystemClock.elapsedRealtime(); mMeasurementInProgress = false; mPreviousGravityVector = mCurrentGravityVector; @@ -196,8 +203,10 @@ public class AnyMotionDetector { status = getStationaryStatus(); if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status); if (status != RESULT_UNKNOWN) { - if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " + - status); + mWakeLock.release(); + if (DEBUG) { + Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " + status); + } mState = STATE_INACTIVE; } else { /* @@ -275,7 +284,7 @@ public class AnyMotionDetector { @Override public void run() { synchronized (mLock) { - startOrientationMeasurement(); + startOrientationMeasurementLocked(); } } }; @@ -442,4 +451,4 @@ public class AnyMotionDetector { return msg; } } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 423f9456ee7f..ccb4647d8591 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -198,6 +198,7 @@ public class DeviceIdleController extends SystemService private long mNextIdleDelay; private long mNextLightIdleDelay; private long mNextLightAlarmTime; + private long mNextSensingTimeoutAlarmTime; private long mCurIdleBudget; private long mMaintenanceStartTime; @@ -339,6 +340,18 @@ public class DeviceIdleController extends SystemService } }; + private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener + = new AlarmManager.OnAlarmListener() { + @Override + public void onAlarm() { + if (mState == STATE_SENSING) { + synchronized (DeviceIdleController.this) { + becomeInactiveIfAppropriateLocked(); + } + } + } + }; + private final AlarmManager.OnAlarmListener mDeepAlarmListener = new AlarmManager.OnAlarmListener() { @Override @@ -924,6 +937,11 @@ public class DeviceIdleController extends SystemService @Override public void onAnyMotionResult(int result) { if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")"); + if (result != AnyMotionDetector.RESULT_UNKNOWN) { + synchronized (this) { + cancelSensingTimeoutAlarmLocked(); + } + } if (result == AnyMotionDetector.RESULT_MOVED) { if (DEBUG) Slog.d(TAG, "RESULT_MOVED received."); synchronized (this) { @@ -1746,6 +1764,7 @@ public class DeviceIdleController extends SystemService mNextIdleDelay = 0; mNextLightIdleDelay = 0; cancelAlarmLocked(); + cancelSensingTimeoutAlarmLocked(); cancelLocatingLocked(); stopMonitoringMotionLocked(); mAnyMotionDetector.stop(); @@ -1866,15 +1885,16 @@ public class DeviceIdleController extends SystemService mState = STATE_SENSING; if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING."); EventLogTags.writeDeviceIdle(mState, reason); - scheduleAlarmLocked(mConstants.SENSING_TIMEOUT, false); + scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT); cancelLocatingLocked(); - mAnyMotionDetector.checkForAnyMotion(); mNotMoving = false; mLocated = false; mLastGenericLocation = null; mLastGpsLocation = null; + mAnyMotionDetector.checkForAnyMotion(); break; case STATE_SENSING: + cancelSensingTimeoutAlarmLocked(); mState = STATE_LOCATING; if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING."); EventLogTags.writeDeviceIdle(mState, reason); @@ -2161,6 +2181,13 @@ public class DeviceIdleController extends SystemService } } + void cancelSensingTimeoutAlarmLocked() { + if (mNextSensingTimeoutAlarmTime != 0) { + mNextSensingTimeoutAlarmTime = 0; + mAlarmManager.cancel(mSensingTimeoutAlarmListener); + } + } + void scheduleAlarmLocked(long delay, boolean idleUntil) { if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")"); if (mMotionSensor == null) { @@ -2194,6 +2221,13 @@ public class DeviceIdleController extends SystemService mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler); } + void scheduleSensingTimeoutAlarmLocked(long delay) { + if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")"); + mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay; + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime, + "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler); + } + private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps, ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) { outAppIds.clear(); diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java index aa0a80508d0f..9ef02598c1d3 100644 --- a/services/core/java/com/android/server/DisplayThread.java +++ b/services/core/java/com/android/server/DisplayThread.java @@ -17,6 +17,7 @@ package com.android.server; import android.os.Handler; +import android.os.Trace; /** * Shared singleton foreground thread for the system. This is a thread for @@ -36,6 +37,7 @@ public final class DisplayThread extends ServiceThread { if (sInstance == null) { sInstance = new DisplayThread(); sInstance.start(); + sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER); sHandler = new Handler(sInstance.getLooper()); } } diff --git a/services/core/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java index 03765db35bae..5f85cbac21d5 100644 --- a/services/core/java/com/android/server/FgThread.java +++ b/services/core/java/com/android/server/FgThread.java @@ -17,6 +17,7 @@ package com.android.server; import android.os.Handler; +import android.os.Trace; /** * Shared singleton foreground thread for the system. This is a thread for regular @@ -38,6 +39,7 @@ public final class FgThread extends ServiceThread { if (sInstance == null) { sInstance = new FgThread(); sInstance.start(); + sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER); sHandler = new Handler(sInstance.getLooper()); } } diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index d6575e84352d..aa986489e1c2 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -34,6 +34,7 @@ import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; +import android.util.MutableBoolean; import android.util.Slog; import android.view.KeyEvent; @@ -251,7 +252,8 @@ public class GestureLauncherService extends SystemService { return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources); } - public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) { + public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, + MutableBoolean outLaunched) { boolean launched = false; boolean intercept = false; long doubleTapInterval; @@ -276,6 +278,7 @@ public class GestureLauncherService extends SystemService { } } MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval); + outLaunched.value = launched; return intercept && launched; } diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 811e34e00bd2..ac7872a94bf8 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -15,6 +15,8 @@ package com.android.server; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import com.android.internal.content.PackageMonitor; import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController; import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; @@ -37,6 +39,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -133,6 +136,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.lang.annotation.Retention; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; @@ -178,6 +182,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID; private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher"; + @Retention(SOURCE) + @IntDef({HardKeyboardBehavior.WIRELESS_AFFORDANCE, HardKeyboardBehavior.WIRED_AFFORDANCE}) + private @interface HardKeyboardBehavior { + int WIRELESS_AFFORDANCE = 0; + int WIRED_AFFORDANCE = 1; + } final Context mContext; final Resources mRes; @@ -462,6 +472,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor(); private final IPackageManager mIPackageManager; private final String mSlotIme; + @HardKeyboardBehavior + private final int mHardKeyboardBehavior; class SettingsObserver extends ContentObserver { int mUserId; @@ -854,6 +866,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mHasFeature = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); + mHardKeyboardBehavior = mContext.getResources().getInteger( + com.android.internal.R.integer.config_externalHardKeyboardBehavior); Bundle extras = new Bundle(); extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true); @@ -1712,11 +1726,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (isScreenLocked()) return false; if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false; if (mWindowManagerInternal.isHardKeyboardAvailable()) { - // When physical keyboard is attached, we show the ime switcher (or notification if - // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently - // exists in the IME switcher dialog. Might be OK to remove this condition once - // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live. - return true; + if (mHardKeyboardBehavior == HardKeyboardBehavior.WIRELESS_AFFORDANCE) { + // When physical keyboard is attached, we show the ime switcher (or notification if + // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently + // exists in the IME switcher dialog. Might be OK to remove this condition once + // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live. + return true; + } } else if ((visibility & InputMethodService.IME_VISIBLE) == 0) { return false; } diff --git a/services/core/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java index 0f29857db345..ad4c19485f26 100644 --- a/services/core/java/com/android/server/IoThread.java +++ b/services/core/java/com/android/server/IoThread.java @@ -17,6 +17,7 @@ package com.android.server; import android.os.Handler; +import android.os.Trace; /** * Shared singleton I/O thread for the system. This is a thread for non-background @@ -35,6 +36,7 @@ public final class IoThread extends ServiceThread { if (sInstance == null) { sInstance = new IoThread(); sInstance.start(); + sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER); sHandler = new Handler(sInstance.getLooper()); } } diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index ed16af51c7eb..ab0f55ebb965 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -254,7 +254,7 @@ public class LockSettingsService extends ILockSettings.Stub { com.android.internal.R.color.system_notification_accent_color)) .setContentTitle(title) .setContentText(message) - .setContentInfo(detail) + .setSubText(detail) .setVisibility(Notification.VISIBILITY_PUBLIC) .setContentIntent(intent) .build(); diff --git a/services/core/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java index 0beb77fb4b92..c06afc2505ee 100644 --- a/services/core/java/com/android/server/UiThread.java +++ b/services/core/java/com/android/server/UiThread.java @@ -17,6 +17,7 @@ package com.android.server; import android.os.Handler; +import android.os.Trace; /** * Shared singleton thread for showing UI. This is a foreground thread, and in @@ -35,6 +36,7 @@ public final class UiThread extends ServiceThread { if (sInstance == null) { sInstance = new UiThread(); sInstance.start(); + sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER); sHandler = new Handler(sInstance.getLooper()); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f6f32950fe37..158751630ee0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -13227,10 +13227,11 @@ public final class ActivityManagerService extends ActivityManagerNative // Merge several logcat streams, and take the last N lines InputStreamReader input = null; try { - java.lang.Process logcat = new ProcessBuilder("/system/bin/logcat", - "-v", "time", "-b", "events", "-b", "system", "-b", "main", - "-b", "crash", - "-t", String.valueOf(lines)).redirectErrorStream(true).start(); + java.lang.Process logcat = new ProcessBuilder( + "/system/bin/timeout", "-k", "15s", "10s", + "/system/bin/logcat", "-v", "time", "-b", "events", "-b", "system", + "-b", "main", "-b", "crash", "-t", String.valueOf(lines)) + .redirectErrorStream(true).start(); try { logcat.getOutputStream().close(); } catch (IOException e) {} try { logcat.getErrorStream().close(); } catch (IOException e) {} diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index f659bde8d6d4..7b2a37081103 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2043,8 +2043,10 @@ public final class ActivityStackSupervisor implements DisplayListener { resizeStackUncheckedLocked(stack, dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds); - if (stack.mFullscreen) { - // The dock stack went fullscreen which is kinda like dismissing it. + // TODO: Checking for isAttached might not be needed as if the user passes in null + // dockedBounds then they want the docked stack to be dismissed. + if (stack.mFullscreen || (dockedBounds == null && !stack.isAttached())) { + // The dock stack either was dismissed or went fullscreen, which is kinda the same. // In this case we make all other static stacks fullscreen and move all // docked stack tasks to the fullscreen stack. for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { @@ -2069,18 +2071,13 @@ public final class ActivityStackSupervisor implements DisplayListener { // static stacks need to be adjusted so they don't overlap with the docked stack. // We get the bounds to use from window manager which has been adjusted for any // screen controls and is also the same for all stacks. - if (dockedBounds != null) { - mWindowManager.getStackDockedModeBounds( - HOME_STACK_ID, tempRect, true /* ignoreVisibility */); - } + mWindowManager.getStackDockedModeBounds( + HOME_STACK_ID, tempRect, true /* ignoreVisibility */); for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) { - if (StackId.isResizeableByDockedStack(i)) { - ActivityStack otherStack = getStack(i); - if (otherStack != null) { - resizeStackLocked(i, dockedBounds != null ? tempRect : null, - tempOtherTaskBounds, tempOtherTaskInsetBounds, preserveWindows, - true /* allowResizeInDockedMode */); - } + if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) { + resizeStackLocked(i, tempRect, tempOtherTaskBounds, + tempOtherTaskInsetBounds, preserveWindows, + true /* allowResizeInDockedMode */); } } } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 6cd756186ab7..68bd2fd3ce3e 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -724,9 +724,7 @@ class AppErrors { final boolean crashSilenced = mAppsNotReportingCrashes != null && mAppsNotReportingCrashes.contains(proc.info.packageName); if (mService.canShowErrorDialogs() && !crashSilenced) { - Dialog d = new AppErrorDialog(mContext, mService, data); - d.show(); - proc.crashDialog = d; + proc.crashDialog = new AppErrorDialog(mContext, mService, data); } else { // The device is asleep, so just pretend that the user // saw a crash dialog and hit "force quit". @@ -735,6 +733,10 @@ class AppErrors { } } } + // If we've created a crash dialog, show it without the lock held + if(data.proc.crashDialog != null) { + data.proc.crashDialog.show(); + } } void stopReportingCrashesLocked(ProcessRecord proc) { @@ -924,6 +926,7 @@ class AppErrors { } void handleShowAnrUi(Message msg) { + Dialog d = null; synchronized (mService) { HashMap<String, Object> data = (HashMap<String, Object>) msg.obj; ProcessRecord proc = (ProcessRecord)data.get("app"); @@ -944,10 +947,9 @@ class AppErrors { null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */); if (mService.canShowErrorDialogs()) { - Dialog d = new AppNotRespondingDialog(mService, + d = new AppNotRespondingDialog(mService, mContext, proc, (ActivityRecord)data.get("activity"), msg.arg1 != 0); - d.show(); proc.anrDialog = d; } else { MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, @@ -956,6 +958,10 @@ class AppErrors { mService.killAppAtUsersRequest(proc, null); } } + // If we've created a crash dialog, show it without the lock held + if (d != null) { + d.show(); + } } /** diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index aef454ee6357..6e890d5d34d8 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -260,6 +260,9 @@ final class UserController { mUserManager.onBeforeUnlockUser(userId); progress.setProgress(20); + // Dispatch unlocked to system services + mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0)); + // Send PRE_BOOT broadcasts if fingerprint changed final UserInfo info = getUserInfo(userId); if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) { @@ -302,9 +305,6 @@ final class UserController { // Remember that we logged in mUserManager.onUserLoggedIn(userId); - // Dispatch unlocked to system services - mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0)); - // Dispatch unlocked to external apps final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED); unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 3b0b79a771ef..a111bf925181 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -264,7 +264,12 @@ public class Vpn { return true; } - // Check if the caller is authorized. + // Stop an existing always-on VPN from being dethroned by other apps. + if (getAlwaysOnPackage() != null) { + return false; + } + + // Check that the caller is authorized. enforceControlPermission(); prepareInternal(newPackage); diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index e9d962827632..6e7ea9925f91 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -73,7 +73,8 @@ import java.util.List; * {@hide} */ public final class ContentService extends IContentService.Stub { - private static final String TAG = "ContentService"; + static final String TAG = "ContentService"; + static final boolean DEBUG = false; public static class Lifecycle extends SystemService { private ContentService mContentService; @@ -339,12 +340,10 @@ public final class ContentService extends IContentService.Stub { */ @Override public void notifyChange(Uri uri, IContentObserver observer, - boolean observerWantsSelfNotifications, boolean syncToNetwork, + boolean observerWantsSelfNotifications, int flags, int userHandle) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle - + " from observer " + observer + ", syncToNetwork " + syncToNetwork); - } + if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle + + " from observer " + observer + ", flags " + Integer.toHexString(flags)); final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); @@ -373,16 +372,15 @@ public final class ContentService extends IContentService.Stub { ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); synchronized (mRootNode) { mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, - userHandle, calls); + flags, userHandle, calls); } final int numCalls = calls.size(); for (int i=0; i<numCalls; i++) { ObserverCall oc = calls.get(i); try { oc.mObserver.onChange(oc.mSelfChange, uri, userHandle); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); - } + if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at " + + uri); } catch (RemoteException ex) { synchronized (mRootNode) { Log.w(TAG, "Found dead observer, removing"); @@ -401,7 +399,7 @@ public final class ContentService extends IContentService.Stub { } } } - if (syncToNetwork) { + if ((flags&ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) { SyncManager syncManager = getSyncManager(); if (syncManager != null) { syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid, @@ -420,7 +418,8 @@ public final class ContentService extends IContentService.Stub { public void notifyChange(Uri uri, IContentObserver observer, boolean observerWantsSelfNotifications, boolean syncToNetwork) { - notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, + notifyChange(uri, observer, observerWantsSelfNotifications, + syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0, UserHandle.getCallingUserId()); } @@ -1064,14 +1063,14 @@ public final class ContentService extends IContentService.Stub { for (int i = 0; i < packageCache.size();) { final Pair<String, Uri> key = packageCache.keyAt(i); if (key.second != null && key.second.toString().startsWith(uri.toString())) { - Slog.d(TAG, "Invalidating cache for key " + key); + if (DEBUG) Slog.d(TAG, "Invalidating cache for key " + key); packageCache.removeAt(i); } else { i++; } } } else { - Slog.d(TAG, "Invalidating cache for package " + providerPackageName); + if (DEBUG) Slog.d(TAG, "Invalidating cache for package " + providerPackageName); packageCache.clear(); } } @@ -1310,8 +1309,8 @@ public final class ContentService extends IContentService.Stub { } private void collectMyObserversLocked(boolean leaf, IContentObserver observer, - boolean observerWantsSelfNotifications, int targetUserHandle, - ArrayList<ObserverCall> calls) { + boolean observerWantsSelfNotifications, int flags, + int targetUserHandle, ArrayList<ObserverCall> calls) { int N = mObservers.size(); IBinder observerBinder = observer == null ? null : observer.asBinder(); for (int i = 0; i < N; i++) { @@ -1329,9 +1328,29 @@ public final class ContentService extends IContentService.Stub { || entry.userHandle == UserHandle.USER_ALL || targetUserHandle == entry.userHandle) { // Make sure the observer is interested in the notification - if (leaf || (!leaf && entry.notifyForDescendants)) { - calls.add(new ObserverCall(this, entry.observer, selfChange)); + if (leaf) { + // If we are at the leaf: we always report, unless the sender has asked + // to skip observers that are notifying for descendants (since they will + // be sending another more specific URI for them). + if ((flags&ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS) != 0 + && entry.notifyForDescendants) { + if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer + + ": skip notify for descendants"); + continue; + } + } else { + // If we are not at the leaf: we report if the observer says it wants + // to be notified for all descendants. + if (!entry.notifyForDescendants) { + if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer + + ": not monitor descendants"); + continue; + } } + if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf + + " flags=" + Integer.toHexString(flags) + + " desc=" + entry.notifyForDescendants); + calls.add(new ObserverCall(this, entry.observer, selfChange)); } } } @@ -1340,19 +1359,22 @@ public final class ContentService extends IContentService.Stub { * targetUserHandle is either a hard user handle or is USER_ALL */ public void collectObserversLocked(Uri uri, int index, IContentObserver observer, - boolean observerWantsSelfNotifications, int targetUserHandle, - ArrayList<ObserverCall> calls) { + boolean observerWantsSelfNotifications, int flags, + int targetUserHandle, ArrayList<ObserverCall> calls) { String segment = null; int segmentCount = countUriSegments(uri); if (index >= segmentCount) { // This is the leaf node, notify all observers + if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName); collectMyObserversLocked(true, observer, observerWantsSelfNotifications, - targetUserHandle, calls); + flags, targetUserHandle, calls); } else if (index < segmentCount){ segment = getUriSegment(uri, index); + if (DEBUG) Slog.d(TAG, "Collecting non-leaf observers @ #" + index + " / " + + segment); // Notify any observers at this level who are interested in descendants collectMyObserversLocked(false, observer, observerWantsSelfNotifications, - targetUserHandle, calls); + flags, targetUserHandle, calls); } int N = mChildren.size(); @@ -1360,8 +1382,8 @@ public final class ContentService extends IContentService.Stub { ObserverNode node = mChildren.get(i); if (segment == null || node.mName.equals(segment)) { // We found the child, - node.collectObserversLocked(uri, index + 1, - observer, observerWantsSelfNotifications, targetUserHandle, calls); + node.collectObserversLocked(uri, index + 1, observer, + observerWantsSelfNotifications, flags, targetUserHandle, calls); if (segment != null) { break; } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index e5342ceec1dc..db41a54f1a0a 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -1402,12 +1402,24 @@ public class SyncManager { } } + private void restoreLostPeriodicSyncsIfNeeded(int userId) { + List<SyncOperation> periodicSyncs = new ArrayList<SyncOperation>(); + for (SyncOperation sync : getAllPendingSyncs()) { + if (sync.isPeriodic && sync.target.userId == userId) { + periodicSyncs.add(sync); + } + } + mSyncStorageEngine.restorePeriodicSyncsIfNeededForUser(userId, periodicSyncs); + } + private void onUserUnlocked(int userId) { // Make sure that accounts we're about to use are valid. AccountManagerService.getSingleton().validateAccounts(userId); mSyncAdapters.invalidateCache(userId); + restoreLostPeriodicSyncsIfNeeded(userId); + EndPoint target = new EndPoint(null, null, userId); updateRunningAccounts(target); @@ -2578,9 +2590,11 @@ public class SyncManager { } } + // Cancel all jobs from non-existent accounts. + AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts(); List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { - if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) { + if (!containsAccountAndUser(allAccounts, op.target.account, op.target.userId)) { getJobScheduler().cancel(op.jobId); } } diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index bc3fc6a47aef..fb23265c2189 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -826,6 +826,35 @@ public class SyncStorageEngine extends Handler { return true; } + /** + * STOPSHIP This is a temporary workaround and should be removed before shipping: b/28052438 + */ + void restorePeriodicSyncsIfNeededForUser(int userHandle, List<SyncOperation> periodicSyncs) { + if (mPeriodicSyncAddedListener == null) { + return; + } + synchronized (mAuthorities) { + for (int i = 0; i < mAuthorities.size(); i++) { + AuthorityInfo authority = mAuthorities.valueAt(i); + if (authority.target.userId == userHandle && authority.enabled) { + boolean periodicSyncAlreadyExists = false; + for (SyncOperation sync : periodicSyncs) { + if (authority.target.matchesSpec(sync.target)) { + periodicSyncAlreadyExists = true; + break; + } + } + // The periodic sync must have been lost due to previous bug. + if (!periodicSyncAlreadyExists) { + mPeriodicSyncAddedListener.onPeriodicSyncAdded(authority.target, + new Bundle(), DEFAULT_POLL_FREQUENCY_SECONDS, + calculateDefaultFlexTime(DEFAULT_POLL_FREQUENCY_SECONDS)); + } + } + } + } + } + public void setMasterSyncAutomatically(boolean flag, int userId) { synchronized (mAuthorities) { Boolean auto = mMasterSyncAutomatically.get(userId); diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 7b134cab2b95..7ba030f78b9b 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -107,6 +107,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private static final int FINGERPRINT_ACQUIRED_GOOD = 0; private final String mKeyguardPackage; private int mCurrentUserId = UserHandle.USER_CURRENT; + private int mUserIdForRemove = UserHandle.USER_NULL; Handler mHandler = new Handler() { @Override @@ -205,10 +206,12 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe protected void handleRemoved(long deviceId, int fingerId, int groupId) { final ClientMonitor client = mRemoveClient; if (fingerId != 0) { - removeTemplateForUser(mRemoveClient, fingerId); + removeTemplateForUser(mUserIdForRemove, fingerId); + } else { + mUserIdForRemove = UserHandle.USER_NULL; } if (client != null && client.sendRemoved(fingerId, groupId)) { - removeClient(mRemoveClient); + removeClient(client); } } @@ -325,8 +328,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe return false; } - private void removeTemplateForUser(ClientMonitor clientMonitor, int fingerId) { - mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, clientMonitor.userId); + private void removeTemplateForUser(int userId, int fingerId) { + mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, userId); } private void addTemplateForUser(ClientMonitor clientMonitor, int fingerId) { @@ -488,6 +491,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe stopPendingOperations(true); mRemoveClient = new ClientMonitor(token, receiver, userId, restricted, token.toString()); + mUserIdForRemove = mCurrentUserId; // The fingerprint template ids will be removed when we get confirmation from the HAL try { final int result = daemon.remove(fingerId, userId); diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index e73beaab6f0b..c7c765bb431e 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -200,6 +200,7 @@ public class InputManagerService extends IInputManager.Stub private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId, int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int policyFlags); + private static native void nativeToggleCapsLock(long ptr, int deviceId); private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles); private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen); private static native void nativeSetSystemUiVisibility(long ptr, int visibility); @@ -2279,5 +2280,10 @@ public class InputManagerService extends IInputManager.Stub mHandler.obtainMessage(MSG_INPUT_METHOD_SUBTYPE_CHANGED, userId, 0, someArgs) .sendToTarget(); } + + @Override + public void toggleCapsLock(int deviceId) { + nativeToggleCapsLock(mPtr, deviceId); + } } } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index fa8620f20a8f..b2350025152f 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -304,7 +304,7 @@ public final class JobSchedulerService extends com.android.server.SystemService toCancel = mJobs.getJobByUidAndJobId(uId, job.getId()); if (toCancel != null) { - cancelJobImpl(toCancel); + cancelJobImpl(toCancel, jobStatus); } startTrackingJob(jobStatus, toCancel); } @@ -331,7 +331,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } for (int i=0; i<jobsForUser.size(); i++) { JobStatus toRemove = jobsForUser.get(i); - cancelJobImpl(toRemove); + cancelJobImpl(toRemove, null); } } @@ -360,7 +360,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } catch (RemoteException e) { } } - cancelJobImpl(toRemove); + cancelJobImpl(toRemove, null); } } @@ -377,13 +377,13 @@ public final class JobSchedulerService extends com.android.server.SystemService toCancel = mJobs.getJobByUidAndJobId(uid, jobId); } if (toCancel != null) { - cancelJobImpl(toCancel); + cancelJobImpl(toCancel, null); } } - private void cancelJobImpl(JobStatus cancelled) { + private void cancelJobImpl(JobStatus cancelled, JobStatus incomingJob) { if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString()); - stopTrackingJob(cancelled, true /* writeBack */); + stopTrackingJob(cancelled, incomingJob, true /* writeBack */); synchronized (mLock) { // Remove from pending queue. mPendingJobs.remove(cancelled); @@ -549,7 +549,7 @@ public final class JobSchedulerService extends com.android.server.SystemService for (int i = 0; i < mControllers.size(); i++) { StateController controller = mControllers.get(i); if (update) { - controller.maybeStopTrackingJobLocked(jobStatus, true); + controller.maybeStopTrackingJobLocked(jobStatus, null, true); } controller.maybeStartTrackingJobLocked(jobStatus, lastJob); } @@ -561,14 +561,15 @@ public final class JobSchedulerService extends com.android.server.SystemService * Called when we want to remove a JobStatus object that we've finished executing. Returns the * object removed. */ - private boolean stopTrackingJob(JobStatus jobStatus, boolean writeBack) { + private boolean stopTrackingJob(JobStatus jobStatus, JobStatus incomingJob, + boolean writeBack) { synchronized (mLock) { // Remove from store as well as controllers. final boolean removed = mJobs.remove(jobStatus, writeBack); if (removed && mReadyToRock) { for (int i=0; i<mControllers.size(); i++) { StateController controller = mControllers.get(i); - controller.maybeStopTrackingJobLocked(jobStatus, false); + controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false); } } return removed; @@ -696,7 +697,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } // Do not write back immediately if this is a periodic job. The job may get lost if system // shuts down before it is added back. - if (!stopTrackingJob(jobStatus, !jobStatus.getJob().isPeriodic())) { + if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) { if (DEBUG) { Slog.d(TAG, "Could not find job to remove. Was job removed while executing?"); } @@ -780,7 +781,7 @@ public final class JobSchedulerService extends com.android.server.SystemService } break; case MSG_STOP_JOB: - cancelJobImpl((JobStatus)message.obj); + cancelJobImpl((JobStatus)message.obj, null); break; } maybeRunPendingJobsH(); diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java index 2114fc3b07c8..d8490d4de516 100644 --- a/services/core/java/com/android/server/job/controllers/AppIdleController.java +++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java @@ -77,7 +77,7 @@ public class AppIdleController extends StateController { } @Override - public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) { mTrackedTasks.remove(jobStatus); } diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java index ac9f42520195..077236443dea 100644 --- a/services/core/java/com/android/server/job/controllers/BatteryController.java +++ b/services/core/java/com/android/server/job/controllers/BatteryController.java @@ -87,7 +87,7 @@ public class BatteryController extends StateController { } @Override - public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) { if (taskStatus.hasChargingConstraint()) { mTrackedTasks.remove(taskStatus); } diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java index 6ef425a57877..5ad8189da054 100644 --- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java @@ -92,7 +92,7 @@ public class ConnectivityController extends StateController implements } @Override - public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) { if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) { mTrackedJobs.remove(jobStatus); } diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java index c5cf30f4739d..b2f1958bac83 100644 --- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java +++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java @@ -84,17 +84,8 @@ public class ContentObserverController extends StateController { boolean havePendingUris = false; // If there is a previous job associated with the new job, propagate over // any pending content URI trigger reports. - if (lastJob != null && lastJob.contentObserverJobInstance != null - && lastJob.contentObserverJobInstance - != taskStatus.contentObserverJobInstance - && lastJob.contentObserverJobInstance.mChangedAuthorities != null) { + if (taskStatus.contentObserverJobInstance.mChangedAuthorities != null) { havePendingUris = true; - taskStatus.contentObserverJobInstance.mChangedAuthorities - = lastJob.contentObserverJobInstance.mChangedAuthorities; - taskStatus.contentObserverJobInstance.mChangedUris - = lastJob.contentObserverJobInstance.mChangedUris; - lastJob.contentObserverJobInstance.mChangedAuthorities = null; - lastJob.contentObserverJobInstance.mChangedUris = null; } // If we have previously reported changed authorities/uris, then we failed // to complete the job with them so will re-record them to report again. @@ -138,15 +129,34 @@ public class ContentObserverController extends StateController { } @Override - public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, + boolean forUpdate) { if (taskStatus.hasContentTriggerConstraint()) { - if (!forUpdate) { - // We won't do this reset if being called for an update, because - // we know it will be immediately followed by maybeStartTrackingJobLocked... - // and we don't want to lose any content changes in-between. - if (taskStatus.contentObserverJobInstance != null) { - taskStatus.contentObserverJobInstance.detach(); - taskStatus.contentObserverJobInstance = null; + if (taskStatus.contentObserverJobInstance != null) { + if (incomingJob != null && taskStatus.contentObserverJobInstance != null + && taskStatus.contentObserverJobInstance.mChangedAuthorities != null) { + // We are stopping this job, but it is going to be replaced by this given + // incoming job. We want to propagate our state over to it, so we don't + // lose any content changes that had happend since the last one started. + // If there is a previous job associated with the new job, propagate over + // any pending content URI trigger reports. + if (incomingJob.contentObserverJobInstance == null) { + incomingJob.contentObserverJobInstance = new JobInstance(incomingJob); + } + incomingJob.contentObserverJobInstance.mChangedAuthorities + = taskStatus.contentObserverJobInstance.mChangedAuthorities; + incomingJob.contentObserverJobInstance.mChangedUris + = taskStatus.contentObserverJobInstance.mChangedUris; + taskStatus.contentObserverJobInstance.mChangedAuthorities = null; + taskStatus.contentObserverJobInstance.mChangedUris = null; + } else { + // We won't do this reset if being called for an update, because + // we know it will be immediately followed by maybeStartTrackingJobLocked... + // and we don't want to lose any content changes in-between. + if (taskStatus.contentObserverJobInstance != null) { + taskStatus.contentObserverJobInstance.detach(); + taskStatus.contentObserverJobInstance = null; + } } } mTrackedTasks.remove(taskStatus); diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java index d2ef6a2e5aa2..64887e8d394d 100644 --- a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java +++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java @@ -166,7 +166,7 @@ public class DeviceIdleJobsController extends StateController { } @Override - public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) { mTrackedTasks.remove(jobStatus); } diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java index d9eb45c6026d..50aa88257ace 100644 --- a/services/core/java/com/android/server/job/controllers/IdleController.java +++ b/services/core/java/com/android/server/job/controllers/IdleController.java @@ -75,7 +75,7 @@ public class IdleController extends StateController { } @Override - public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) { mTrackedTasks.remove(taskStatus); } diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java index ac7f4c3f4756..013903939f18 100644 --- a/services/core/java/com/android/server/job/controllers/StateController.java +++ b/services/core/java/com/android/server/job/controllers/StateController.java @@ -56,7 +56,8 @@ public abstract class StateController { /** * Remove task - this will happen if the task is cancelled, completed, etc. */ - public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate); + public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, + boolean forUpdate); /** * Called when a new job is being created to reschedule an old failed job. */ diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java index 35432495942d..ab6768e99878 100644 --- a/services/core/java/com/android/server/job/controllers/TimeController.java +++ b/services/core/java/com/android/server/job/controllers/TimeController.java @@ -74,7 +74,7 @@ public class TimeController extends StateController { @Override public void maybeStartTrackingJobLocked(JobStatus job, JobStatus lastJob) { if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) { - maybeStopTrackingJobLocked(job, false); + maybeStopTrackingJobLocked(job, null, false); boolean isInsert = false; ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size()); while (it.hasPrevious()) { @@ -101,7 +101,7 @@ public class TimeController extends StateController { * Really an == comparison should be enough, but why play with fate? We'll do <=. */ @Override - public void maybeStopTrackingJobLocked(JobStatus job, boolean forUpdate) { + public void maybeStopTrackingJobLocked(JobStatus job, JobStatus incomingJob, boolean forUpdate) { if (mTrackedJobs.remove(job)) { checkExpiredDelaysAndResetAlarm(); checkExpiredDeadlinesAndResetAlarm(); diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java index 257c7dadfc5d..5953ddecd222 100644 --- a/services/core/java/com/android/server/lights/LightsService.java +++ b/services/core/java/com/android/server/lights/LightsService.java @@ -18,12 +18,17 @@ package com.android.server.lights; import com.android.server.SystemService; import com.android.server.vr.VrManagerInternal; +import com.android.server.vr.VrManagerService; import com.android.server.vr.VrStateListener; import android.content.Context; import android.os.Handler; +import android.os.IBinder; import android.os.Message; +import android.os.RemoteException; import android.os.Trace; +import android.service.vr.IVrManager; +import android.service.vr.IVrStateCallbacks; import android.util.Slog; public class LightsService extends SystemService { @@ -164,13 +169,19 @@ public class LightsService extends SystemService { @Override public void onBootPhase(int phase) { if (phase == PHASE_SYSTEM_SERVICES_READY) { - getLocalService(VrManagerInternal.class).registerListener(mVrStateListener); + IVrManager vrManager = + (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE); + try { + vrManager.registerListener(mVrStateCallbacks); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to register VR mode state listener: " + e); + } } } - private final VrStateListener mVrStateListener = new VrStateListener() { + private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() { @Override - public void onVrStateChanged(boolean enabled) { + public void onVrStateChanged(boolean enabled) throws RemoteException { LightImpl l = mLights[LightsManager.LIGHT_ID_BACKLIGHT]; if (enabled) { if (DEBUG) Slog.v(TAG, "VR mode enabled, setting brightness to low persistence"); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 660f79080193..99c41eae22ae 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2897,9 +2897,10 @@ public class NotificationManagerService extends SystemService { } private void scheduleSendRankingUpdate() { - mHandler.removeMessages(MESSAGE_SEND_RANKING_UPDATE); - Message m = Message.obtain(mHandler, MESSAGE_SEND_RANKING_UPDATE); - mHandler.sendMessage(m); + if (!mHandler.hasMessages(MESSAGE_SEND_RANKING_UPDATE)) { + Message m = Message.obtain(mHandler, MESSAGE_SEND_RANKING_UPDATE); + mHandler.sendMessage(m); + } } private void handleSendRankingUpdate() { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 83ddf1c380fb..31eac1f3e0ec 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -110,6 +110,7 @@ import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.IDevicePolicyManager; import android.app.admin.SecurityLog; import android.app.backup.IBackupManager; +import android.app.usage.UsageStatsManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -7005,11 +7006,28 @@ public class PackageManagerService extends IPackageManager.Stub { pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this); } + UsageStatsManager usageMgr = + (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE); + int curr = 0; int total = pkgs.size(); for (PackageParser.Package pkg : pkgs) { curr++; + if (!PackageDexOptimizer.canOptimizePackage(pkg)) { + if (DEBUG_DEXOPT) { + Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName); + } + continue; + } + + if (!causeFirstBoot && usageMgr.isAppInactive(pkg.packageName)) { + if (DEBUG_DEXOPT) { + Log.i(TAG, "Skipping update of of idle app " + pkg.packageName); + } + continue; + } + if (DEBUG_DEXOPT) { Log.i(TAG, "Extracting app " + curr + " of " + total + ": " + pkg.packageName); } @@ -7023,16 +7041,11 @@ public class PackageManagerService extends IPackageManager.Stub { } } - if (PackageDexOptimizer.canOptimizePackage(pkg)) { - // If the cache was pruned, any compiled odex files will likely be out of date - // and would have to be patched (would be SELF_PATCHOAT, which is deprecated). - // Instead, force the extraction in this case. - performDexOpt(pkg.packageName, - null /* instructionSet */, - false /* checkProfiles */, - causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT, - false /* force */); - } + performDexOpt(pkg.packageName, + null /* instructionSet */, + false /* checkProfiles */, + causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT, + false /* force */); } } @@ -14260,14 +14273,11 @@ public class PackageManagerService extends IPackageManager.Stub { } } - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { PackageParser.collectCertificates(pkg, parseFlags); } catch (PackageParserException e) { res.setError("Failed collect during installPackageLI", e); return; - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } // Get rid of all references to package scan path via parser. @@ -17006,7 +17016,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); intent.addCategory(Intent.CATEGORY_SETUP_WIZARD); final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, - MATCH_SYSTEM_ONLY | MATCH_DISABLED_COMPONENTS, UserHandle.myUserId()); + MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE + | MATCH_DISABLED_COMPONENTS, + UserHandle.myUserId()); if (matches.size() == 1) { return matches.get(0).getComponentInfo().packageName; } else { diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index 4b355de62e87..364e9fa6719c 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -425,6 +425,18 @@ public class UserRestrictionsUtils { } } } + break; + case UserManager.DISALLOW_SAFE_BOOT: + // Unlike with the other restrictions, we want to propagate the new value to + // the system settings even if it is false. The other restrictions modify + // settings which could be manually changed by the user from the Settings app + // after the policies enforcing these restrictions have been revoked, so we + // leave re-setting of those settings to the user. + android.provider.Settings.Global.putInt( + context.getContentResolver(), + android.provider.Settings.Global.SAFE_BOOT_DISALLOWED, + newValue ? 1 : 0); + break; } } finally { Binder.restoreCallingIdentity(id); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 14d0457e41c1..fb56a0c7ee3e 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -69,6 +69,7 @@ import android.graphics.Rect; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; +import android.hardware.input.InputManagerInternal; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.AudioSystem; @@ -107,6 +108,7 @@ import android.telecom.TelecomManager; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; +import android.util.MutableBoolean; import android.util.Slog; import android.util.SparseArray; import android.util.LongSparseArray; @@ -304,6 +306,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManagerInternal mWindowManagerInternal; PowerManager mPowerManager; ActivityManagerInternal mActivityManagerInternal; + InputManagerInternal mInputManagerInternal; DreamManagerInternal mDreamManagerInternal; PowerManagerInternal mPowerManagerInternal; IStatusBarService mStatusBarService; @@ -396,6 +399,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { volatile boolean mBeganFromNonInteractive; volatile int mPowerKeyPressCounter; volatile boolean mEndCallKeyHandled; + volatile boolean mCameraGestureTriggeredDuringGoingToSleep; + volatile boolean mGoingToSleep; boolean mRecentsVisible; int mRecentAppsHeldModifiers; @@ -601,6 +606,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mConsumeSearchKeyUp; boolean mAssistKeyLongPressed; boolean mPendingMetaAction; + boolean mPendingCapsLockToggle; + int mMetaState; + int mInitialMetaState; boolean mForceShowSystemBars; // support for activating the lock screen while the screen is on @@ -685,6 +693,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { = new LogDecelerateInterpolator(100, 0); private boolean mForceWindowDrawsStatusBarBackground; + private final MutableBoolean mTmpBoolean = new MutableBoolean(false); private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_DISABLE_POINTER_LOCATION = 2; @@ -1032,7 +1041,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { GestureLauncherService.class); boolean gesturedServiceIntercepted = false; if (gestureService != null) { - gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive); + gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive, + mTmpBoolean); + if (mTmpBoolean.value && mGoingToSleep) { + mCameraGestureTriggeredDuringGoingToSleep = true; + } } // If the power key has still not yet been handled, then detect short @@ -1486,6 +1499,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManagerFuncs = windowManagerFuncs; mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); + mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); @@ -1817,41 +1831,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - mStatusBarHeight = - res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); - - // Height of the navigation bar when presented horizontally at bottom - mNavigationBarHeightForRotationDefault[mPortraitRotation] = - mNavigationBarHeightForRotationDefault[mUpsideDownRotation] = - res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height); - mNavigationBarHeightForRotationDefault[mLandscapeRotation] = - mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_height_landscape); - - // Width of the navigation bar when presented vertically along one side - mNavigationBarWidthForRotationDefault[mPortraitRotation] = - mNavigationBarWidthForRotationDefault[mUpsideDownRotation] = - mNavigationBarWidthForRotationDefault[mLandscapeRotation] = - mNavigationBarWidthForRotationDefault[mSeascapeRotation] = - res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); - - // Height of the navigation bar when presented horizontally at bottom - mNavigationBarHeightForRotationInCarMode[mPortraitRotation] = - mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] = - res.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_height_car_mode); - mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] = - mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode); - - // Width of the navigation bar when presented vertically along one side - mNavigationBarWidthForRotationInCarMode[mPortraitRotation] = - mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] = - mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] = - mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] = - res.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_width_car_mode); - // SystemUI (status bar) layout policy int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density; int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density; @@ -1860,6 +1839,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mNavigationBarCanMove = width != height && shortSizeDp < 600; mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar); + // Allow a system property to override this. Used by the emulator. // See also hasNavigationBar(). String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); @@ -2290,6 +2270,46 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + @Override + public void onConfigurationChanged() { + final Resources res = mContext.getResources(); + + mStatusBarHeight = + res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); + + // Height of the navigation bar when presented horizontally at bottom + mNavigationBarHeightForRotationDefault[mPortraitRotation] = + mNavigationBarHeightForRotationDefault[mUpsideDownRotation] = + res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height); + mNavigationBarHeightForRotationDefault[mLandscapeRotation] = + mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_height_landscape); + + // Width of the navigation bar when presented vertically along one side + mNavigationBarWidthForRotationDefault[mPortraitRotation] = + mNavigationBarWidthForRotationDefault[mUpsideDownRotation] = + mNavigationBarWidthForRotationDefault[mLandscapeRotation] = + mNavigationBarWidthForRotationDefault[mSeascapeRotation] = + res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); + + // Height of the navigation bar when presented horizontally at bottom + mNavigationBarHeightForRotationInCarMode[mPortraitRotation] = + mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] = + res.getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_height_car_mode); + mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] = + mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode); + + // Width of the navigation bar when presented vertically along one side + mNavigationBarWidthForRotationInCarMode[mPortraitRotation] = + mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] = + mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] = + mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] = + res.getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_width_car_mode); + } + /** {@inheritDoc} */ @Override public int windowTypeToLayerLw(int type) { @@ -2954,6 +2974,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { mPendingMetaAction = false; } + // Any key that is not Alt or Meta cancels Caps Lock combo tracking. + if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) { + mPendingCapsLockToggle = false; + } // First we always handle the home key here, so applications // can never break it, although if keyguard is on, we do let @@ -3202,6 +3226,38 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // Toggle Caps Lock on META-ALT. + boolean actionTriggered = false; + if (KeyEvent.isModifierKey(keyCode)) { + if (!mPendingCapsLockToggle) { + // Start tracking meta state for combo. + mInitialMetaState = mMetaState; + mPendingCapsLockToggle = true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; + int metaOnMask = mMetaState & KeyEvent.META_META_MASK; + + // Check for Caps Lock toggle + if ((metaOnMask != 0) && (altOnMask != 0)) { + // Check if nothing else is pressed + if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { + // Handle Caps Lock Toggle + mInputManagerInternal.toggleCapsLock(event.getDeviceId()); + actionTriggered = true; + } + } + + // Always stop tracking when key goes up. + mPendingCapsLockToggle = false; + } + } + // Store current meta state to be able to evaluate it later. + mMetaState = metaState; + + if (actionTriggered) { + return -1; + } + if (KeyEvent.isMetaKey(keyCode)) { if (down) { mPendingMetaAction = true; @@ -5948,6 +6004,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void startedGoingToSleep(int why) { if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); + mCameraGestureTriggeredDuringGoingToSleep = false; + mGoingToSleep = true; if (mKeyguardDelegate != null) { mKeyguardDelegate.onStartedGoingToSleep(why); } @@ -5960,6 +6018,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); + mGoingToSleep = false; + // We must get this work done here because the power manager will drop // the wake lock and let the system suspend once this function returns. synchronized (mLock) { @@ -5969,8 +6029,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateLockScreenTimeout(); } if (mKeyguardDelegate != null) { - mKeyguardDelegate.onFinishedGoingToSleep(why); + mKeyguardDelegate.onFinishedGoingToSleep(why, + mCameraGestureTriggeredDuringGoingToSleep); } + mCameraGestureTriggeredDuringGoingToSleep = false; } // Called on the PowerManager's Notifier thread. diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index 8d296d505c4c..52e588015177 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -294,9 +294,9 @@ public class KeyguardServiceDelegate { mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP; } - public void onFinishedGoingToSleep(int why) { + public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) { if (mKeyguardService != null) { - mKeyguardService.onFinishedGoingToSleep(why); + mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered); } mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP; } diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java index 429b18866a61..dacdec042a45 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java @@ -117,9 +117,9 @@ public class KeyguardServiceWrapper implements IKeyguardService { } @Override - public void onFinishedGoingToSleep(int reason) { + public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) { try { - mService.onFinishedGoingToSleep(reason); + mService.onFinishedGoingToSleep(reason, cameraGestureTriggered); } catch (RemoteException e) { Slog.w(TAG , "Remote Exception", e); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 757096016329..8cd536de9b54 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -53,6 +53,8 @@ import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.SettingNotFoundException; import android.service.dreams.DreamManagerInternal; +import android.service.vr.IVrManager; +import android.service.vr.IVrStateCallbacks; import android.util.EventLog; import android.util.Slog; import android.util.SparseIntArray; @@ -72,6 +74,7 @@ import com.android.server.am.BatteryStatsService; import com.android.server.lights.Light; import com.android.server.lights.LightsManager; import com.android.server.vr.VrManagerInternal; +import com.android.server.vr.VrManagerService; import com.android.server.vr.VrStateListener; import libcore.util.Objects; @@ -658,7 +661,13 @@ public final class PowerManagerService extends SystemService resolver.registerContentObserver(Settings.Secure.getUriFor( Secure.BRIGHTNESS_USE_TWILIGHT), false, mSettingsObserver, UserHandle.USER_ALL); - getLocalService(VrManagerInternal.class).registerListener(mVrStateListener); + IVrManager vrManager = + (IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE); + try { + vrManager.registerListener(mVrStateCallbacks); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to register VR mode state listener: " + e); + } // Go. readConfigurationLocked(); updateSettingsLocked(); @@ -3007,7 +3016,7 @@ public final class PowerManagerService extends SystemService } } - private final VrStateListener mVrStateListener = new VrStateListener() { + private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() { @Override public void onVrStateChanged(boolean enabled) { powerHintInternal(POWER_HINT_VR_MODE, enabled ? 1 : 0); diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java index 93bb9d795ddd..1bbb9f52c818 100644 --- a/services/core/java/com/android/server/vr/VrManagerInternal.java +++ b/services/core/java/com/android/server/vr/VrManagerInternal.java @@ -31,13 +31,6 @@ public abstract class VrManagerInternal { public static final int NO_ERROR = 0; /** - * Return current VR mode state. - * - * @return {@code true} if VR mode is enabled. - */ - public abstract boolean isInVrMode(); - - /** * Return {@code true} if the given package is the currently bound VrListenerService for the * given user. * @@ -59,22 +52,6 @@ public abstract class VrManagerInternal { public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName, int userId, @NonNull ComponentName calling); - /** - * Add a listener for VR mode state changes. - * <p> - * This listener will immediately be called with the current VR mode state. - * </p> - * @param listener the listener instance to add. - */ - public abstract void registerListener(@NonNull VrStateListener listener); - - /** - * Remove the listener from the current set of listeners. - * - * @param listener the listener to remove. - */ - public abstract void unregisterListener(@NonNull VrStateListener listener); - /** * Return NO_ERROR if the given package is installed on the device and enabled as a * VrListenerService for the given current user, or a negative error code indicating a failure. diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index c572e766f1ec..e6e5a2db0725 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -15,6 +15,7 @@ */ package com.android.server.vr; +import android.Manifest; import android.app.AppOpsManager; import android.app.NotificationManager; import android.annotation.NonNull; @@ -29,11 +30,15 @@ import android.os.Handler; import android.os.IBinder; import android.os.IInterface; import android.os.Looper; +import android.os.Message; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.vr.IVrListener; +import android.service.vr.IVrManager; +import android.service.vr.IVrStateCallbacks; import android.service.vr.VrListenerService; import android.util.ArraySet; import android.util.Slog; @@ -46,6 +51,7 @@ import com.android.server.utils.ManagedApplicationService; import com.android.server.utils.ManagedApplicationService.BinderChecker; import java.lang.StringBuilder; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.Objects; @@ -75,6 +81,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC public static final String TAG = "VrManagerService"; + public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager"; + private static native void initializeNative(); private static native void setVrModeNative(boolean enabled); @@ -84,7 +92,6 @@ public class VrManagerService extends SystemService implements EnabledComponentC // State protected by mLock private boolean mVrModeEnabled; - private final Set<VrStateListener> mListeners = new ArraySet<>(); private EnabledComponentsObserver mComponentObserver; private ManagedApplicationService mCurrentVrService; private Context mContext; @@ -92,10 +99,37 @@ public class VrManagerService extends SystemService implements EnabledComponentC private int mCurrentVrModeUser; private boolean mWasDefaultGranted; private boolean mGuard; + private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks = + new RemoteCallbackList<>(); private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>(); private String mPreviousNotificationPolicyAccessPackage; private String mPreviousManageOverlayPackage; + private static final int MSG_VR_STATE_CHANGE = 0; + + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch(msg.what) { + case MSG_VR_STATE_CHANGE : { + boolean state = (msg.arg1 == 1); + int i = mRemoteCallbacks.beginBroadcast(); + while (i > 0) { + i--; + try { + mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state); + } catch (RemoteException e) { + // Noop + } + } + mRemoteCallbacks.finishBroadcast(); + } break; + default : + throw new IllegalStateException("Unknown message type: " + msg.what); + } + } + }; + private static final BinderChecker sBinderChecker = new BinderChecker() { @Override public IInterface asInterface(IBinder binder) { @@ -125,34 +159,55 @@ public class VrManagerService extends SystemService implements EnabledComponentC } } - /** - * Implementation of VrManagerInternal. Callable only from system services. - */ - private final class LocalService extends VrManagerInternal { + private final IVrManager mVrManager = new IVrManager.Stub() { + @Override - public boolean isInVrMode() { - return VrManagerService.this.getVrMode(); + public void registerListener(IVrStateCallbacks cb) { + enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); + if (cb == null) { + throw new IllegalArgumentException("Callback binder object is null."); + } + + VrManagerService.this.addStateCallback(cb); } @Override - public void setVrMode(boolean enabled, ComponentName packageName, int userId, - ComponentName callingPackage) { - VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage); + public void unregisterListener(IVrStateCallbacks cb) { + enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); + if (cb == null) { + throw new IllegalArgumentException("Callback binder object is null."); + } + + VrManagerService.this.removeStateCallback(cb); } @Override - public boolean isCurrentVrListener(String packageName, int userId) { - return VrManagerService.this.isCurrentVrListener(packageName, userId); + public boolean getVrModeState() { + return VrManagerService.this.getVrMode(); + } + + }; + + private void enforceCallerPermission(String permission) { + if (mContext.checkCallingOrSelfPermission(permission) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Caller does not hold the permission " + permission); } + } + /** + * Implementation of VrManagerInternal. Callable only from system services. + */ + private final class LocalService extends VrManagerInternal { @Override - public void registerListener(VrStateListener listener) { - VrManagerService.this.addListener(listener); + public void setVrMode(boolean enabled, ComponentName packageName, int userId, + ComponentName callingPackage) { + VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage); } @Override - public void unregisterListener(VrStateListener listener) { - VrManagerService.this.removeListener(listener); + public boolean isCurrentVrListener(String packageName, int userId) { + return VrManagerService.this.isCurrentVrListener(packageName, userId); } @Override @@ -173,6 +228,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC } publishLocalService(VrManagerInternal.class, new LocalService()); + publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder()); } @Override @@ -551,9 +607,8 @@ public class VrManagerService extends SystemService implements EnabledComponentC * Note: Must be called while holding {@code mLock}. */ private void onVrModeChangedLocked() { - for (VrStateListener l : mListeners) { - l.onVrStateChanged(mVrModeEnabled); - } + mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE, + (mVrModeEnabled) ? 1 : 0, 0)); } /** @@ -577,9 +632,9 @@ public class VrManagerService extends SystemService implements EnabledComponentC } } - private boolean getVrMode() { + private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) { synchronized (mLock) { - return mVrModeEnabled; + return mComponentObserver.isValid(targetPackageName, userId); } } @@ -593,21 +648,21 @@ public class VrManagerService extends SystemService implements EnabledComponentC } } - private void addListener(VrStateListener listener) { - synchronized (mLock) { - mListeners.add(listener); - } + /* + * Implementation of IVrManager calls. + */ + + private void addStateCallback(IVrStateCallbacks cb) { + mRemoteCallbacks.register(cb); } - private void removeListener(VrStateListener listener) { - synchronized (mLock) { - mListeners.remove(listener); - } + private void removeStateCallback(IVrStateCallbacks cb) { + mRemoteCallbacks.unregister(cb); } - private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) { + private boolean getVrMode() { synchronized (mLock) { - return mComponentObserver.isValid(targetPackageName, userId); + return mVrModeEnabled; } } } diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java index 6052a6e037c7..9486cfdb87a0 100644 --- a/services/core/java/com/android/server/webkit/SystemImpl.java +++ b/services/core/java/com/android/server/webkit/SystemImpl.java @@ -110,9 +110,7 @@ public class SystemImpl implements SystemInterface { Log.e(TAG, "Found an element that is not a webview provider"); } } - } catch(XmlPullParserException e) { - throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); - } catch(IOException e) { + } catch (XmlPullParserException | IOException e) { throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e); } finally { if (parser != null) parser.close(); @@ -120,6 +118,11 @@ public class SystemImpl implements SystemInterface { return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]); } + public int getFactoryPackageVersion(String packageName) throws NameNotFoundException { + PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); + return pm.getPackageInfo(packageName, PackageManager.MATCH_FACTORY_ONLY).versionCode; + } + /** * Reads all signatures at the current depth (within the current provider) from the XML parser. */ @@ -181,15 +184,18 @@ public class SystemImpl implements SystemInterface { @Override public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) { - context.getPackageManager().deletePackage(packageName, - new IPackageDeleteObserver.Stub() { - public void packageDeleted(String packageName, int returnCode) { - // Ignore returnCode since the deletion could fail, e.g. we might be trying - // to delete a non-updated system-package (and we should still disable the - // package) - enablePackageForAllUsers(context, packageName, false); + enablePackageForAllUsers(context, packageName, false); + try { + PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); + if (pm.getApplicationInfo(packageName, 0).isUpdatedSystemApp()) { + pm.deletePackage(packageName, new IPackageDeleteObserver.Stub() { + public void packageDeleted(String packageName, int returnCode) { + enablePackageForAllUsers(context, packageName, false); + } + }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS); } - }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS); + } catch (NameNotFoundException e) { + } } @Override diff --git a/services/core/java/com/android/server/webkit/SystemInterface.java b/services/core/java/com/android/server/webkit/SystemInterface.java index b5eb0a711fa3..7bde37a5a4fd 100644 --- a/services/core/java/com/android/server/webkit/SystemInterface.java +++ b/services/core/java/com/android/server/webkit/SystemInterface.java @@ -32,6 +32,7 @@ import android.webkit.WebViewProviderInfo; public interface SystemInterface { public WebViewProviderInfo[] getWebViewPackages(); public int onWebViewProviderChanged(PackageInfo packageInfo); + public int getFactoryPackageVersion(String packageName) throws NameNotFoundException; public String getUserChosenWebViewProvider(Context context); public void updateUserSetting(Context context, String newProviderName); diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java index 4669676320d9..ebec44554210 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -50,26 +51,21 @@ import java.util.List; public class WebViewUpdateService extends SystemService { private static final String TAG = "WebViewUpdateService"; - private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000. - - // Keeps track of the number of running relro creations - private int mNumRelroCreationsStarted = 0; - private int mNumRelroCreationsFinished = 0; - // Implies that we need to rerun relro creation because we are using an out-of-date package - private boolean mWebViewPackageDirty = false; - private boolean mAnyWebViewInstalled = false; - - private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE; - - // The WebView package currently in use (or the one we are preparing). - private PackageInfo mCurrentWebViewPackage = null; private BroadcastReceiver mWebViewUpdatedReceiver; private SystemInterface mSystemInterface; + static final int PACKAGE_CHANGED = 0; + static final int PACKAGE_ADDED = 1; + static final int PACKAGE_ADDED_REPLACED = 2; + static final int PACKAGE_REMOVED = 3; + + private WebViewUpdater mWebViewUpdater; + public WebViewUpdateService(Context context) { super(context); mSystemInterface = new SystemImpl(); + mWebViewUpdater = new WebViewUpdater(getContext(), mSystemInterface); } @Override @@ -77,76 +73,34 @@ public class WebViewUpdateService extends SystemService { mWebViewUpdatedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - // When a package is replaced we will receive two intents, one representing - // the removal of the old package and one representing the addition of the - // new package. - // In the case where we receive an intent to remove the old version of the - // package that is being replaced we early-out here so that we don't run the - // update-logic twice. - if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED) - && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) { - return; - } - - // Ensure that we only heed PACKAGE_CHANGED intents if they change an entire - // package, not just a component - if (intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED)) { - if (!entirePackageChanged(intent)) { - return; - } - } - - if (intent.getAction().equals(Intent.ACTION_USER_ADDED)) { - int userId = - intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); - handleNewUser(userId); - return; - } - - updateFallbackState(context, intent); - - for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) { - String webviewPackage = "package:" + provider.packageName; - - if (webviewPackage.equals(intent.getDataString())) { - boolean updateWebView = false; - boolean removedOrChangedOldPackage = false; - String oldProviderName = null; - PackageInfo newPackage = null; - synchronized(WebViewUpdateService.this) { - try { - newPackage = findPreferredWebViewPackage(); - if (mCurrentWebViewPackage != null) - oldProviderName = mCurrentWebViewPackage.packageName; - // Only trigger update actions if the updated package is the one - // that will be used, or the one that was in use before the - // update, or if we haven't seen a valid WebView package before. - updateWebView = - provider.packageName.equals(newPackage.packageName) - || provider.packageName.equals(oldProviderName) - || mCurrentWebViewPackage == null; - // We removed the old package if we received an intent to remove - // or replace the old package. - removedOrChangedOldPackage = - provider.packageName.equals(oldProviderName); - if (updateWebView) { - onWebViewProviderChanged(newPackage); - } - } catch (WebViewFactory.MissingWebViewPackageException e) { - Slog.e(TAG, "Could not find valid WebView package to create " + - "relro with " + e); - } + switch (intent.getAction()) { + case Intent.ACTION_PACKAGE_REMOVED: + // When a package is replaced we will receive two intents, one + // representing the removal of the old package and one representing the + // addition of the new package. + // In the case where we receive an intent to remove the old version of + // the package that is being replaced we early-out here so that we don't + // run the update-logic twice. + if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return; + packageStateChanged(packageNameFromIntent(intent), PACKAGE_REMOVED); + break; + case Intent.ACTION_PACKAGE_CHANGED: + // Ensure that we only heed PACKAGE_CHANGED intents if they change an + // entire package, not just a component + if (entirePackageChanged(intent)) { + packageStateChanged(packageNameFromIntent(intent), PACKAGE_CHANGED); } - if(updateWebView && !removedOrChangedOldPackage - && oldProviderName != null) { - // If the provider change is the result of adding or replacing a - // package that was not the previous provider then we must kill - // packages dependent on the old package ourselves. The framework - // only kills dependents of packages that are being removed. - mSystemInterface.killPackageDependents(oldProviderName); - } - return; - } + break; + case Intent.ACTION_PACKAGE_ADDED: + packageStateChanged(packageNameFromIntent(intent), + (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING) + ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED)); + break; + case Intent.ACTION_USER_ADDED: + int userId = + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); + handleNewUser(userId); + break; } } }; @@ -168,12 +122,27 @@ public class WebViewUpdateService extends SystemService { publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/); } + private void packageStateChanged(String packageName, int changedState) { + updateFallbackState(packageName, changedState); + mWebViewUpdater.packageStateChanged(packageName, changedState); + } + + public void prepareWebViewInSystemServer() { + updateFallbackStateOnBoot(); + mWebViewUpdater.prepareWebViewInSystemServer(); + } + + private static String packageNameFromIntent(Intent intent) { + return intent.getDataString().substring("package:".length()); + } + private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) { for (WebViewProviderInfo provider : providers) { if (provider.availableByDefault && !provider.isFallback) { try { PackageInfo packageInfo = mSystemInterface.getPackageInfoForProvider(provider); - if (isEnabledPackage(packageInfo) && isValidProvider(provider, packageInfo)) { + if (isEnabledPackage(packageInfo) + && mWebViewUpdater.isValidProvider(provider, packageInfo)) { return true; } } catch (NameNotFoundException e) { @@ -198,33 +167,37 @@ public class WebViewUpdateService extends SystemService { !existsValidNonFallbackProvider(webviewProviders), userId); } + public void updateFallbackStateOnBoot() { + WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages(); + updateFallbackState(webviewProviders, true); + } + /** * Handle the enabled-state of our fallback package, i.e. if there exists some non-fallback * package that is valid (and available by default) then disable the fallback package, * otherwise, enable the fallback package. */ - void updateFallbackState(final Context context, final Intent intent) { + public void updateFallbackState(String changedPackage, int changedState) { if (!mSystemInterface.isFallbackLogicEnabled()) return; WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages(); - if (intent != null && (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED) - || intent.getAction().equals(Intent.ACTION_PACKAGE_CHANGED))) { - // A package was changed / updated / downgraded, early out if it is not one of the - // webview packages that are available by default. - String changedPackage = null; - for (WebViewProviderInfo provider : webviewProviders) { - String webviewPackage = "package:" + provider.packageName; - if (webviewPackage.equals(intent.getDataString())) { - if (provider.availableByDefault) { - changedPackage = provider.packageName; - } - break; + // A package was changed / updated / downgraded, early out if it is not one of the + // webview packages that are available by default. + boolean changedPackageAvailableByDefault = false; + for (WebViewProviderInfo provider : webviewProviders) { + if (provider.packageName.equals(changedPackage)) { + if (provider.availableByDefault) { + changedPackageAvailableByDefault = true; } + break; } - if (changedPackage == null) return; } + if (!changedPackageAvailableByDefault) return; + updateFallbackState(webviewProviders, false); + } + private void updateFallbackState(WebViewProviderInfo[] webviewProviders, boolean isBoot) { // If there exists a valid and enabled non-fallback package - disable the fallback // package, otherwise, enable it. WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders); @@ -233,28 +206,29 @@ public class WebViewUpdateService extends SystemService { boolean isFallbackEnabled = false; try { - isFallbackEnabled = - isEnabledPackage(mSystemInterface.getPackageInfoForProvider(fallbackProvider)); + isFallbackEnabled = isEnabledPackage( + mSystemInterface.getPackageInfoForProvider(fallbackProvider)); } catch (NameNotFoundException e) { } if (existsValidNonFallbackProvider // During an OTA the primary user's WebView state might differ from other users', so // ignore the state of that user during boot. - && (isFallbackEnabled || intent == null)) { - mSystemInterface.uninstallAndDisablePackageForAllUsers(context, + && (isFallbackEnabled || isBoot)) { + mSystemInterface.uninstallAndDisablePackageForAllUsers(getContext(), fallbackProvider.packageName); } else if (!existsValidNonFallbackProvider // During an OTA the primary user's WebView state might differ from other users', so // ignore the state of that user during boot. - && (!isFallbackEnabled || intent==null)) { + && (!isFallbackEnabled || isBoot)) { // Enable the fallback package for all users. - mSystemInterface.enablePackageForAllUsers(context, fallbackProvider.packageName, true); + mSystemInterface.enablePackageForAllUsers(getContext(), + fallbackProvider.packageName, true); } } /** - * Returns the only fallback provider, or null if there is none. + * Returns the only fallback provider in the set of given packages, or null if there is none. */ private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) { for (WebViewProviderInfo provider : webviewPackages) { @@ -275,180 +249,361 @@ public class WebViewUpdateService extends SystemService { } /** - * Perform any WebView loading preparations that must happen at boot from the system server, - * after the package manager has started or after an update to the webview is installed. - * This must be called in the system server. - * Currently, this means spawning the child processes which will create the relro files. + * Class that decides what WebView implementation to use and prepares that implementation for + * use. */ - public void prepareWebViewInSystemServer() { - updateFallbackState(getContext(), null); - try { - synchronized(this) { - mCurrentWebViewPackage = findPreferredWebViewPackage(); - onWebViewProviderChanged(mCurrentWebViewPackage); - } - } catch (Throwable t) { - // Log and discard errors at this stage as we must not crash the system server. - Slog.e(TAG, "error preparing webview provider from system server", t); + private static class WebViewUpdater { + private Context mContext; + private SystemInterface mSystemInterface; + private int mMinimumVersionCode = -1; + + public WebViewUpdater(Context context, SystemInterface systemInterface) { + mContext = context; + mSystemInterface = systemInterface; } - } + private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000. + + // Keeps track of the number of running relro creations + private int mNumRelroCreationsStarted = 0; + private int mNumRelroCreationsFinished = 0; + // Implies that we need to rerun relro creation because we are using an out-of-date package + private boolean mWebViewPackageDirty = false; + private boolean mAnyWebViewInstalled = false; + + private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE; + + // The WebView package currently in use (or the one we are preparing). + private PackageInfo mCurrentWebViewPackage = null; + + private Object mLock = new Object(); + + public void packageStateChanged(String packageName, int changedState) { + for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) { + String webviewPackage = provider.packageName; + + if (webviewPackage.equals(packageName)) { + boolean updateWebView = false; + boolean removedOrChangedOldPackage = false; + String oldProviderName = null; + PackageInfo newPackage = null; + synchronized(mLock) { + try { + newPackage = findPreferredWebViewPackage(); + if (mCurrentWebViewPackage != null) + oldProviderName = mCurrentWebViewPackage.packageName; + // Only trigger update actions if the updated package is the one + // that will be used, or the one that was in use before the + // update, or if we haven't seen a valid WebView package before. + updateWebView = + provider.packageName.equals(newPackage.packageName) + || provider.packageName.equals(oldProviderName) + || mCurrentWebViewPackage == null; + // We removed the old package if we received an intent to remove + // or replace the old package. + removedOrChangedOldPackage = + provider.packageName.equals(oldProviderName); + if (updateWebView) { + onWebViewProviderChanged(newPackage); + } + } catch (WebViewFactory.MissingWebViewPackageException e) { + Slog.e(TAG, "Could not find valid WebView package to create " + + "relro with " + e); + } + } + if(updateWebView && !removedOrChangedOldPackage + && oldProviderName != null) { + // If the provider change is the result of adding or replacing a + // package that was not the previous provider then we must kill + // packages dependent on the old package ourselves. The framework + // only kills dependents of packages that are being removed. + mSystemInterface.killPackageDependents(oldProviderName); + } + return; + } + } + } - /** - * Change WebView provider and provider setting and kill packages using the old provider. - * Return the new provider (in case we are in the middle of creating relro files this new - * provider will not be in use directly, but will when the relros are done). - */ - private String changeProviderAndSetting(String newProviderName) { - PackageInfo oldPackage = null; - PackageInfo newPackage = null; - synchronized(this) { - oldPackage = mCurrentWebViewPackage; - mSystemInterface.updateUserSetting(getContext(), newProviderName); - + public void prepareWebViewInSystemServer() { try { - newPackage = findPreferredWebViewPackage(); - if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) { - // If we don't perform the user change, revert the settings change. - mSystemInterface.updateUserSetting(getContext(), newPackage.packageName); - return newPackage.packageName; + synchronized(mLock) { + mCurrentWebViewPackage = findPreferredWebViewPackage(); + onWebViewProviderChanged(mCurrentWebViewPackage); } - } catch (WebViewFactory.MissingWebViewPackageException e) { - Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView package " - + e); - // If we don't perform the user change but don't have an installed WebView package, - // we will have changed the setting and it will be used when a package is available. - return newProviderName; + } catch (Throwable t) { + // Log and discard errors at this stage as we must not crash the system server. + Slog.e(TAG, "error preparing webview provider from system server", t); } - onWebViewProviderChanged(newPackage); } - // Kill apps using the old provider - if (oldPackage != null) { - mSystemInterface.killPackageDependents(oldPackage.packageName); + + /** + * Change WebView provider and provider setting and kill packages using the old provider. + * Return the new provider (in case we are in the middle of creating relro files this new + * provider will not be in use directly, but will when the relros are done). + */ + public String changeProviderAndSetting(String newProviderName) { + PackageInfo oldPackage = null; + PackageInfo newPackage = null; + synchronized(mLock) { + oldPackage = mCurrentWebViewPackage; + mSystemInterface.updateUserSetting(mContext, newProviderName); + + try { + newPackage = findPreferredWebViewPackage(); + if (oldPackage != null + && newPackage.packageName.equals(oldPackage.packageName)) { + // If we don't perform the user change, revert the settings change. + mSystemInterface.updateUserSetting(mContext, newPackage.packageName); + return newPackage.packageName; + } + } catch (WebViewFactory.MissingWebViewPackageException e) { + Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView " + + "package " + e); + // If we don't perform the user change but don't have an installed WebView + // package, we will have changed the setting and it will be used when a package + // is available. + return newProviderName; + } + onWebViewProviderChanged(newPackage); + } + // Kill apps using the old provider + if (oldPackage != null) { + mSystemInterface.killPackageDependents(oldPackage.packageName); + } + return newPackage.packageName; } - return newPackage.packageName; - } - /** - * This is called when we change WebView provider, either when the current provider is updated - * or a new provider is chosen / takes precedence. - */ - private void onWebViewProviderChanged(PackageInfo newPackage) { - synchronized(this) { - mAnyWebViewInstalled = true; - if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) { - mCurrentWebViewPackage = newPackage; - mSystemInterface.updateUserSetting(getContext(), newPackage.packageName); - - // The relro creations might 'finish' (not start at all) before - // WebViewFactory.onWebViewProviderChanged which means we might not know the number - // of started creations before they finish. - mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN; - mNumRelroCreationsFinished = 0; - mNumRelroCreationsStarted = mSystemInterface.onWebViewProviderChanged(newPackage); - // If the relro creations finish before we know the number of started creations we - // will have to do any cleanup/notifying here. - checkIfRelrosDoneLocked(); - } else { - mWebViewPackageDirty = true; + /** + * This is called when we change WebView provider, either when the current provider is + * updated or a new provider is chosen / takes precedence. + */ + private void onWebViewProviderChanged(PackageInfo newPackage) { + synchronized(mLock) { + mAnyWebViewInstalled = true; + if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) { + mCurrentWebViewPackage = newPackage; + mSystemInterface.updateUserSetting(mContext, newPackage.packageName); + + // The relro creations might 'finish' (not start at all) before + // WebViewFactory.onWebViewProviderChanged which means we might not know the + // number of started creations before they finish. + mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN; + mNumRelroCreationsFinished = 0; + mNumRelroCreationsStarted = + mSystemInterface.onWebViewProviderChanged(newPackage); + // If the relro creations finish before we know the number of started creations + // we will have to do any cleanup/notifying here. + checkIfRelrosDoneLocked(); + } else { + mWebViewPackageDirty = true; + } } } - } - private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() { - WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages(); - List<ProviderAndPackageInfo> providers = new ArrayList<>(); - for(int n = 0; n < allProviders.length; n++) { - try { - PackageInfo packageInfo = - mSystemInterface.getPackageInfoForProvider(allProviders[n]); - if (isValidProvider(allProviders[n], packageInfo)) { - providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo)); + private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() { + WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages(); + List<ProviderAndPackageInfo> providers = new ArrayList<>(); + for(int n = 0; n < allProviders.length; n++) { + try { + PackageInfo packageInfo = + mSystemInterface.getPackageInfoForProvider(allProviders[n]); + if (isValidProvider(allProviders[n], packageInfo)) { + providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo)); + } + } catch (NameNotFoundException e) { + // Don't add non-existent packages } - } catch (NameNotFoundException e) { - // Don't add non-existent packages } + return providers.toArray(new ProviderAndPackageInfo[providers.size()]); + } + + /** + * Fetch only the currently valid WebView packages. + **/ + public WebViewProviderInfo[] getValidWebViewPackages() { + ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos(); + WebViewProviderInfo[] providers = + new WebViewProviderInfo[providersAndPackageInfos.length]; + for(int n = 0; n < providersAndPackageInfos.length; n++) { + providers[n] = providersAndPackageInfos[n].provider; + } + return providers; } - return providers.toArray(new ProviderAndPackageInfo[providers.size()]); - } - /** - * Fetch only the currently valid WebView packages. - **/ - private WebViewProviderInfo[] getValidWebViewPackages() { - ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos(); - WebViewProviderInfo[] providers = new WebViewProviderInfo[providersAndPackageInfos.length]; - for(int n = 0; n < providersAndPackageInfos.length; n++) { - providers[n] = providersAndPackageInfos[n].provider; - } - return providers; - } - private class ProviderAndPackageInfo { - public final WebViewProviderInfo provider; - public final PackageInfo packageInfo; + private class ProviderAndPackageInfo { + public final WebViewProviderInfo provider; + public final PackageInfo packageInfo; - public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) { - this.provider = provider; - this.packageInfo = packageInfo; + public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) { + this.provider = provider; + this.packageInfo = packageInfo; + } } - } - /** - * Returns either the package info of the WebView provider determined in the following way: - * If the user has chosen a provider then use that if it is valid, - * otherwise use the first package in the webview priority list that is valid. - * - * @hide - */ - private PackageInfo findPreferredWebViewPackage() { - ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos(); + /** + * Returns either the package info of the WebView provider determined in the following way: + * If the user has chosen a provider then use that if it is valid, + * otherwise use the first package in the webview priority list that is valid. + * + */ + private PackageInfo findPreferredWebViewPackage() { + ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos(); - String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(getContext()); + String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext); - // If the user has chosen provider, use that - for (ProviderAndPackageInfo providerAndPackage : providers) { - if (providerAndPackage.provider.packageName.equals(userChosenProvider) - && isEnabledPackage(providerAndPackage.packageInfo)) { + // If the user has chosen provider, use that + for (ProviderAndPackageInfo providerAndPackage : providers) { + if (providerAndPackage.provider.packageName.equals(userChosenProvider) + && isEnabledPackage(providerAndPackage.packageInfo)) { + return providerAndPackage.packageInfo; + } + } + + // User did not choose, or the choice failed; use the most stable provider that is + // enabled and available by default (not through user choice). + for (ProviderAndPackageInfo providerAndPackage : providers) { + if (providerAndPackage.provider.availableByDefault + && isEnabledPackage(providerAndPackage.packageInfo)) { + return providerAndPackage.packageInfo; + } + } + + // Could not find any enabled package either, use the most stable provider. + for (ProviderAndPackageInfo providerAndPackage : providers) { return providerAndPackage.packageInfo; } + + mAnyWebViewInstalled = false; + throw new WebViewFactory.MissingWebViewPackageException( + "Could not find a loadable WebView package"); } - // User did not choose, or the choice failed; use the most stable provider that is - // enabled and available by default (not through user choice). - for (ProviderAndPackageInfo providerAndPackage : providers) { - if (providerAndPackage.provider.availableByDefault - && isEnabledPackage(providerAndPackage.packageInfo)) { - return providerAndPackage.packageInfo; + public void notifyRelroCreationCompleted() { + synchronized (mLock) { + mNumRelroCreationsFinished++; + checkIfRelrosDoneLocked(); + } + } + + public WebViewProviderResponse waitForAndGetProvider() { + PackageInfo webViewPackage = null; + final long NS_PER_MS = 1000000; + final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS; + boolean webViewReady = false; + int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS; + synchronized (mLock) { + webViewReady = webViewIsReadyLocked(); + while (!webViewReady) { + final long timeNowMs = System.nanoTime() / NS_PER_MS; + if (timeNowMs >= timeoutTimeMs) break; + try { + mLock.wait(timeoutTimeMs - timeNowMs); + } catch (InterruptedException e) {} + webViewReady = webViewIsReadyLocked(); + } + // Make sure we return the provider that was used to create the relro file + webViewPackage = mCurrentWebViewPackage; + if (webViewReady) { + } else if (!mAnyWebViewInstalled) { + webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES; + } else { + // Either the current relro creation isn't done yet, or the new relro creatioin + // hasn't kicked off yet (the last relro creation used an out-of-date WebView). + webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO; + } } + if (!webViewReady) Slog.w(TAG, "creating relro file timed out"); + return new WebViewProviderResponse(webViewPackage, webViewStatus); } - // Could not find any enabled package either, use the most stable provider. - for (ProviderAndPackageInfo providerAndPackage : providers) { - return providerAndPackage.packageInfo; + public String getCurrentWebViewPackageName() { + synchronized(mLock) { + if (mCurrentWebViewPackage == null) + return null; + return mCurrentWebViewPackage.packageName; + } } - mAnyWebViewInstalled = false; - throw new WebViewFactory.MissingWebViewPackageException( - "Could not find a loadable WebView package"); - } + /** + * Returns whether WebView is ready and is not going to go through its preparation phase + * again directly. + */ + private boolean webViewIsReadyLocked() { + return !mWebViewPackageDirty + && (mNumRelroCreationsStarted == mNumRelroCreationsFinished) + // The current package might be replaced though we haven't received an intent + // declaring this yet, the following flag makes anyone loading WebView to wait in + // this case. + && mAnyWebViewInstalled; + } + private void checkIfRelrosDoneLocked() { + if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) { + if (mWebViewPackageDirty) { + mWebViewPackageDirty = false; + // If we have changed provider since we started the relro creation we need to + // redo the whole process using the new package instead. + PackageInfo newPackage = findPreferredWebViewPackage(); + onWebViewProviderChanged(newPackage); + } else { + mLock.notifyAll(); + } + } + } - /** - * Returns whether this provider is valid for use as a WebView provider. - */ - public boolean isValidProvider(WebViewProviderInfo configInfo, - PackageInfo packageInfo) { - if (providerHasValidSignature(configInfo, packageInfo) && - WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) { - return true; + /** + * Returns whether this provider is valid for use as a WebView provider. + */ + public boolean isValidProvider(WebViewProviderInfo configInfo, + PackageInfo packageInfo) { + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 + && packageInfo.versionCode < getMinimumVersionCode() + && !mSystemInterface.systemIsDebuggable()) { + // Non-system package webview providers may be downgraded arbitrarily low, prevent + // that by enforcing minimum version code. This check is only enforced for user + // builds. + return false; + } + if (providerHasValidSignature(configInfo, packageInfo, mSystemInterface) && + WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) { + return true; + } + return false; + } + + /** + * Gets the minimum version code allowed for a valid provider. It is the minimum versionCode + * of all available-by-default and non-fallback WebView provider packages. If there is no + * such WebView provider package on the system, then return -1, which means all positive + * versionCode WebView packages are accepted. + */ + private int getMinimumVersionCode() { + if (mMinimumVersionCode > 0) { + return mMinimumVersionCode; + } + + for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) { + if (provider.availableByDefault && !provider.isFallback) { + try { + int versionCode = + mSystemInterface.getFactoryPackageVersion(provider.packageName); + if (mMinimumVersionCode < 0 || versionCode < mMinimumVersionCode) { + mMinimumVersionCode = versionCode; + } + } catch (PackageManager.NameNotFoundException e) { + // Safe to ignore. + } + } + } + + return mMinimumVersionCode; } - return false; } - private boolean providerHasValidSignature(WebViewProviderInfo provider, - PackageInfo packageInfo) { - if (mSystemInterface.systemIsDebuggable()) { + private static boolean providerHasValidSignature(WebViewProviderInfo provider, + PackageInfo packageInfo, SystemInterface systemInterface) { + if (systemInterface.systemIsDebuggable()) { return true; } Signature[] packageSignatures; @@ -475,7 +630,7 @@ public class WebViewUpdateService extends SystemService { * Returns whether the given package is enabled. * This state can be changed by the user from Settings->Apps */ - public boolean isEnabledPackage(PackageInfo packageInfo) { + private static boolean isEnabledPackage(PackageInfo packageInfo) { return packageInfo.applicationInfo.enabled; } @@ -491,32 +646,6 @@ public class WebViewUpdateService extends SystemService { intent.getDataString().substring("package:".length())); } - /** - * Returns whether WebView is ready and is not going to go through its preparation phase again - * directly. - */ - private boolean webViewIsReadyLocked() { - return !mWebViewPackageDirty - && (mNumRelroCreationsStarted == mNumRelroCreationsFinished) - // The current package might be replaced though we haven't received an intent declaring - // this yet, the following flag makes anyone loading WebView to wait in this case. - && mAnyWebViewInstalled; - } - - private void checkIfRelrosDoneLocked() { - if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) { - if (mWebViewPackageDirty) { - mWebViewPackageDirty = false; - // If we have changed provider since we started the relro creation we need to - // redo the whole process using the new package instead. - PackageInfo newPackage = findPreferredWebViewPackage(); - onWebViewProviderChanged(newPackage); - } else { - this.notifyAll(); - } - } - } - private class BinderService extends IWebViewUpdateService.Stub { @Override @@ -544,10 +673,7 @@ public class WebViewUpdateService extends SystemService { long callingId = Binder.clearCallingIdentity(); try { - synchronized (WebViewUpdateService.this) { - mNumRelroCreationsFinished++; - checkIfRelrosDoneLocked(); - } + WebViewUpdateService.this.mWebViewUpdater.notifyRelroCreationCompleted(); } finally { Binder.restoreCallingIdentity(callingId); } @@ -567,34 +693,7 @@ public class WebViewUpdateService extends SystemService { throw new IllegalStateException("Cannot create a WebView from the SystemServer"); } - PackageInfo webViewPackage = null; - final long NS_PER_MS = 1000000; - final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS; - boolean webViewReady = false; - int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS; - synchronized (WebViewUpdateService.this) { - webViewReady = WebViewUpdateService.this.webViewIsReadyLocked(); - while (!webViewReady) { - final long timeNowMs = System.nanoTime() / NS_PER_MS; - if (timeNowMs >= timeoutTimeMs) break; - try { - WebViewUpdateService.this.wait(timeoutTimeMs - timeNowMs); - } catch (InterruptedException e) {} - webViewReady = WebViewUpdateService.this.webViewIsReadyLocked(); - } - // Make sure we return the provider that was used to create the relro file - webViewPackage = WebViewUpdateService.this.mCurrentWebViewPackage; - if (webViewReady) { - } else if (!mAnyWebViewInstalled) { - webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES; - } else { - // Either the current relro creation isn't done yet, or the new relro creatioin - // hasn't kicked off yet (the last relro creation used an out-of-date WebView). - webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO; - } - } - if (!webViewReady) Slog.w(TAG, "creating relro file timed out"); - return new WebViewProviderResponse(webViewPackage, webViewStatus); + return WebViewUpdateService.this.mWebViewUpdater.waitForAndGetProvider(); } /** @@ -615,7 +714,8 @@ public class WebViewUpdateService extends SystemService { long callingId = Binder.clearCallingIdentity(); try { - return WebViewUpdateService.this.changeProviderAndSetting(newProvider); + return WebViewUpdateService.this.mWebViewUpdater.changeProviderAndSetting( + newProvider); } finally { Binder.restoreCallingIdentity(callingId); } @@ -623,7 +723,7 @@ public class WebViewUpdateService extends SystemService { @Override // Binder call public WebViewProviderInfo[] getValidWebViewPackages() { - return WebViewUpdateService.this.getValidWebViewPackages(); + return WebViewUpdateService.this.mWebViewUpdater.getValidWebViewPackages(); } @Override // Binder call @@ -633,11 +733,7 @@ public class WebViewUpdateService extends SystemService { @Override // Binder call public String getCurrentWebViewPackageName() { - synchronized(WebViewUpdateService.this) { - if (WebViewUpdateService.this.mCurrentWebViewPackage == null) - return null; - return WebViewUpdateService.this.mCurrentWebViewPackage.packageName; - } + return WebViewUpdateService.this.mWebViewUpdater.getCurrentWebViewPackageName(); } @Override // Binder call diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index d6842787eef5..11b01ccb9c68 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -881,7 +881,7 @@ public class AppTransition implements Dump { * when a thumbnail is specified with the pending animation override. */ Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets, - Bitmap thumbnailHeader, final int taskId, int orientation) { + Bitmap thumbnailHeader, final int taskId, int uiMode, int orientation) { Animation a; final int thumbWidthI = thumbnailHeader.getWidth(); final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1; @@ -896,7 +896,7 @@ public class AppTransition implements Dump { final float toY; final float pivotX; final float pivotY; - if (orientation == Configuration.ORIENTATION_PORTRAIT) { + if (isTvUiMode(uiMode) || orientation == Configuration.ORIENTATION_PORTRAIT) { fromX = mTmpRect.left; fromY = mTmpRect.top; @@ -1028,7 +1028,7 @@ public class AppTransition implements Dump { * activity that is leaving, and the activity that is entering. */ Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState, - int orientation, int transit, Rect containingFrame, Rect contentInsets, + int uiMode, int orientation, int transit, Rect containingFrame, Rect contentInsets, @Nullable Rect surfaceInsets, boolean freeform, int taskId) { Animation a; final int appWidth = containingFrame.width(); @@ -1067,8 +1067,7 @@ public class AppTransition implements Dump { mTmpFromClipRect.inset(contentInsets); mNextAppTransitionInsets.set(contentInsets); - if (orientation == Configuration.ORIENTATION_PORTRAIT) { - // We scale the width and clip to the top/left square + if (isTvUiMode(uiMode) || orientation == Configuration.ORIENTATION_PORTRAIT) { // We scale the width and clip to the top/left square float scale = thumbWidth / (appWidth - contentInsets.left - contentInsets.right); @@ -1401,7 +1400,7 @@ public class AppTransition implements Dump { * to the recents thumbnail and hence need to account for the surface being * bigger. */ - Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, + Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, int uiMode, int orientation, Rect frame, Rect displayFrame, Rect insets, @Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform, int taskId) { @@ -1481,7 +1480,7 @@ public class AppTransition implements Dump { mNextAppTransitionScaleUp = (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP); a = createAspectScaledThumbnailEnterExitAnimationLocked( - getThumbnailTransitionState(enter), orientation, transit, frame, + getThumbnailTransitionState(enter), uiMode, orientation, transit, frame, insets, surfaceInsets, freeform, taskId); if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) { String animName = mNextAppTransitionScaleUp ? @@ -1922,4 +1921,11 @@ public class AppTransition implements Dump { } return prepared; } + + /** + * @return whether the specified {@param uiMode} is the TV mode. + */ + private boolean isTvUiMode(int uiMode) { + return (uiMode & Configuration.UI_MODE_TYPE_TELEVISION) > 0; + } } diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 6f7e64f28e74..6ac71c795ca7 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -76,8 +76,8 @@ public class DockedStackDividerController implements DimLayerUser { private final WindowManagerService mService; private final DisplayContent mDisplayContent; - private final int mDividerWindowWidth; - private final int mDividerInsets; + private int mDividerWindowWidth; + private int mDividerInsets; private boolean mResizing; private WindowState mWindow; private final Rect mTmpRect = new Rect(); @@ -105,14 +105,23 @@ public class DockedStackDividerController implements DimLayerUser { mService = service; mDisplayContent = displayContent; final Context context = service.mContext; - mDividerWindowWidth = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.docked_stack_divider_thickness); - mDividerInsets = context.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.docked_stack_divider_insets); mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId(), "DockedStackDim"); mMinimizedDockInterpolator = AnimationUtils.loadInterpolator( context, android.R.interpolator.fast_out_slow_in); + loadDimens(); + } + + private void loadDimens() { + final Context context = mService.mContext; + mDividerWindowWidth = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_divider_thickness); + mDividerInsets = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.docked_stack_divider_insets); + } + + void onConfigurationChanged() { + loadDimens(); } boolean isResizing() { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index eea0ca0666f7..8a9ace780ad5 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -595,6 +595,12 @@ class Task implements DimLayer.DimLayerUser { if (win.mHasSurface && !resizingWindows.contains(win)) { if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win); resizingWindows.add(win); + + // If we are not drag resizing, force recreating of a new surface so updating + // the content and positioning that surface will be in sync. + if (!win.computeDragResizing()) { + win.mResizedWhileNotDragResizing = true; + } } if (win.isGoneForLayoutLw()) { win.mResizedWhileGone = true; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 0225c9b4105f..3430ac9289a5 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -37,8 +37,8 @@ import java.util.ArrayList; import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; -import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.WindowManager.DOCKED_BOTTOM; import static android.view.WindowManager.DOCKED_INVALID; @@ -89,6 +89,9 @@ public class TaskStack implements DimLayer.DimLayerUser, // Device rotation as of the last time {@link #mBounds} was set. int mRotation; + /** Density as of last time {@link #mBounds} was set. */ + int mDensity; + /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */ DimLayer mAnimationBackgroundSurface; @@ -250,9 +253,11 @@ public class TaskStack implements DimLayer.DimLayerUser, private boolean setBounds(Rect bounds) { boolean oldFullscreen = mFullscreen; int rotation = Surface.ROTATION_0; + int density = DENSITY_DPI_UNDEFINED; if (mDisplayContent != null) { mDisplayContent.getLogicalDisplayRect(mTmpRect); rotation = mDisplayContent.getDisplayInfo().rotation; + density = mDisplayContent.getDisplayInfo().logicalDensityDpi; mFullscreen = bounds == null; if (mFullscreen) { bounds = mTmpRect; @@ -274,6 +279,7 @@ public class TaskStack implements DimLayer.DimLayerUser, mBounds.set(bounds); mRotation = rotation; + mDensity = density; updateAdjustedBounds(); @@ -343,20 +349,21 @@ public class TaskStack implements DimLayer.DimLayerUser, mTmpRect2.set(mBounds); final int newRotation = mDisplayContent.getDisplayInfo().rotation; - if (mRotation == newRotation) { + final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi; + if (mRotation == newRotation && mDensity == newDensity) { setBounds(mTmpRect2); } else { mLastUpdateDisplayInfoRotation = newRotation; - updateBoundsAfterRotation(true); + updateBoundsAfterConfigChange(true); } } boolean onConfigurationChanged() { mLastConfigChangedRotation = getDisplayInfo().rotation; - return updateBoundsAfterRotation(false); + return updateBoundsAfterConfigChange(false); } - boolean updateBoundsAfterRotation(boolean scheduleResize) { + boolean updateBoundsAfterConfigChange(boolean scheduleResize) { if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) { // We wait for the rotation values after configuration change and display info. update // to be equal before updating the bounds due to rotation change otherwise things might @@ -365,8 +372,9 @@ public class TaskStack implements DimLayer.DimLayerUser, } final int newRotation = getDisplayInfo().rotation; + final int newDensity = getDisplayInfo().logicalDensityDpi; - if (mRotation == newRotation) { + if (mRotation == newRotation && mDensity == newDensity) { // Nothing to do here if the rotation didn't change return false; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 08d9ddf559c8..2af324d19710 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2017,7 +2017,13 @@ public class WindowManagerService extends IWindowManager.Stub final WindowStateAnimator winAnimator = win.mWinAnimator; winAnimator.mEnterAnimationPending = true; winAnimator.mEnteringAnimation = true; - prepareWindowReplacementTransition(atoken); + // Check if we need to prepare a transition for replacing window first. + if (atoken != null && !prepareWindowReplacementTransition(atoken)) { + // If not, check if need to set up a dummy transition during display freeze + // so that the unfreeze wait for the apps to draw. This might be needed if + // the app is relaunching. + prepareNoneTransitionForRelaunching(atoken); + } if (displayContent.isDefaultDisplay) { if (mPolicy.getInsetHintLw(win.mAttrs, mRotation, outContentInsets, outStableInsets, @@ -2077,10 +2083,10 @@ public class WindowManagerService extends IWindowManager.Stub return res; } - private void prepareWindowReplacementTransition(AppWindowToken atoken) { - if (atoken == null) { - return; - } + /** + * Returns true if we're done setting up any transitions. + */ + private boolean prepareWindowReplacementTransition(AppWindowToken atoken) { atoken.allDrawn = false; WindowState replacedWindow = null; for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) { @@ -2093,7 +2099,7 @@ public class WindowManagerService extends IWindowManager.Stub if (replacedWindow == null) { // We expect to already receive a request to remove the old window. If it did not // happen, let's just simply add a window. - return; + return false; } // We use the visible frame, because we want the animation to morph the window from what // was visible to the user to the final destination of the new window. @@ -2105,6 +2111,19 @@ public class WindowManagerService extends IWindowManager.Stub mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top, frame.width(), frame.height()); executeAppTransition(); + return true; + } + + private void prepareNoneTransitionForRelaunching(AppWindowToken atoken) { + // Set up a none-transition and add the app to opening apps, so that the display + // unfreeze wait for the apps to be drawn. + // Note that if the display unfroze already because app unfreeze timed out, + // we don't set up the transition anymore and just let it go. + if (mDisplayFrozen && !mOpeningApps.contains(atoken) && atoken.isRelaunching()) { + mOpeningApps.add(atoken); + prepareAppTransition(AppTransition.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT); + executeAppTransition(); + } } /** @@ -2567,7 +2586,7 @@ public class WindowManagerService extends IWindowManager.Stub try { - win.applyGravityAndUpdateFrame(); + win.applyGravityAndUpdateFrame(win.mContainingFrame, win.mDisplayFrame); win.mWinAnimator.computeShownFrameLocked(); win.mWinAnimator.setSurfaceBoundariesLocked(false); @@ -2916,8 +2935,9 @@ public class WindowManagerService extends IWindowManager.Stub // If we're starting a drag-resize, we'll be changing the surface size as well as // notifying the client to render to with an offset from the surface's top-left. - if (win.isDragResizeChanged()) { + if (win.isDragResizeChanged() || win.mResizedWhileNotDragResizing) { win.setDragResizing(); + win.mResizedWhileNotDragResizing = false; // We can only change top level windows to the full-screen surface when // resizing (as we only have one full-screen surface). So there is no need // to preserve and destroy windows which are attached to another, they @@ -3039,7 +3059,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition." + " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter + " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets); - Animation a = mAppTransition.loadAnimation(lp, transit, enter, + Animation a = mAppTransition.loadAnimation(lp, transit, enter, mCurConfiguration.uiMode, mCurConfiguration.orientation, frame, displayFrame, insets, surfaceInsets, isVoiceInteraction, freeform, atoken.mTask.mTaskId); if (a != null) { @@ -3608,6 +3628,8 @@ public class WindowManagerService extends IWindowManager.Stub } private int[] onConfigurationChanged() { + mPolicy.onConfigurationChanged(); + getDefaultDisplayContentLocked().getDockedDividerController().onConfigurationChanged(); mChangedStackList.clear(); for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) { final TaskStack stack = mStackIdToStack.valueAt(stackNdx); @@ -7596,6 +7618,11 @@ public class WindowManagerService extends IWindowManager.Stub + " milliseconds before attempting to detect safe mode."); } + if (Settings.Global.getInt( + mContext.getContentResolver(), Settings.Global.SAFE_BOOT_DISALLOWED, 0) != 0) { + return false; + } + int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_MENU); int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); @@ -8997,7 +9024,8 @@ public class WindowManagerService extends IWindowManager.Stub || winAnimator.mSurfaceResized || w.mOutsetsChanged || configChanged - || dragResizingChanged) { + || dragResizingChanged + || w.mResizedWhileNotDragResizing) { if (DEBUG_RESIZE || DEBUG_ORIENTATION) { Slog.v(TAG_WM, "Resize reasons for w=" + w + ": " + " contentInsetsChanged=" + w.mContentInsetsChanged @@ -9031,7 +9059,8 @@ public class WindowManagerService extends IWindowManager.Stub // the display until this window has been redrawn; to do that, // we need to go through the process of getting informed by the // application when it has finished drawing. - if (w.mOrientationChanging || dragResizingChanged) { + if (w.mOrientationChanging || dragResizingChanged + || w.mResizedWhileNotDragResizing) { if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) { Slog.v(TAG_WM, "Orientation or resize start waiting for draw" + ", mDrawState=DRAW_PENDING in " + w @@ -9391,6 +9420,10 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (DEBUG_ORIENTATION) Slog.d(TAG_WM, + "startFreezingDisplayLocked: inTransaction=" + inTransaction + + " exitAnim=" + exitAnim + " enterAnim=" + enterAnim + + " called by " + Debug.getCallers(8)); mScreenFrozenLock.acquire(); mDisplayFrozen = true; @@ -9461,6 +9494,9 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (DEBUG_ORIENTATION) Slog.d(TAG_WM, + "stopFreezingDisplayLocked: Unfreezing now"); + mDisplayFrozen = false; mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); StringBuilder sb = new StringBuilder(128); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c62292dfeb86..ddfc022aeb3f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -328,6 +328,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { */ final Rect mInsetFrame = new Rect(); + private static final Rect sTmpRect = new Rect(); + boolean mContentChanged; // If a window showing a wallpaper: the requested offset for the @@ -466,6 +468,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { */ boolean mResizedWhileGone = false; + /** + * Indicates whether we got resized but drag resizing flag was false. In this case, we also + * need to recreate the surface and defer surface bound updates in order to make sure the + * buffer contents and the positioning/size stay in sync. + */ + boolean mResizedWhileNotDragResizing; + WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token, WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a, int viewVisibility, final DisplayContent displayContent) { @@ -629,6 +638,20 @@ final class WindowState implements WindowManagerPolicy.WindowState { return mAttrs.packageName; } + /** + * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame} + * from {@param frame}. In other words, it applies the insets that would result if + * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from + * {@param insetFrame}. + */ + private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame) { + final int left = Math.max(0, insetFrame.left - layoutFrame.left); + final int top = Math.max(0, insetFrame.top - layoutFrame.top); + final int right = Math.max(0, layoutFrame.right - insetFrame.right); + final int bottom = Math.max(0, layoutFrame.bottom - insetFrame.bottom); + frame.inset(left, top, right, bottom); + } + @Override public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf, Rect osf) { @@ -654,11 +677,25 @@ final class WindowState implements WindowManagerPolicy.WindowState { task.getTempInsetBounds(mInsetFrame); } + // Denotes the actual frame used to calculate the insets and to perform the layout. When + // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the + // insets temporarily. By the notion of a task having a different layout frame, we can + // achieve that while still moving the task around. + final Rect layoutContainingFrame; + final Rect layoutDisplayFrame; + + // The offset from the layout containing frame to the actual containing frame. + final int layoutXDiff; + final int layoutYDiff; if (mInsetFrame.isEmpty() && (fullscreenTask || layoutInParentFrame())) { // We use the parent frame as the containing frame for fullscreen and child windows mContainingFrame.set(pf); mDisplayFrame.set(df); + layoutDisplayFrame = df; + layoutContainingFrame = pf; + layoutXDiff = 0; + layoutYDiff = 0; } else { task.getBounds(mContainingFrame); if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) { @@ -693,6 +730,14 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } mDisplayFrame.set(mContainingFrame); + layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0; + layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0; + layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame; + subtractInsets(mDisplayFrame, layoutContainingFrame, df); + subtractInsets(mContainingFrame, layoutContainingFrame, pf); + subtractInsets(mInsetFrame, layoutContainingFrame, pf); + layoutDisplayFrame = df; + layoutDisplayFrame.intersect(layoutContainingFrame); } final int pw = mContainingFrame.width(); @@ -723,7 +768,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { final int fw = mFrame.width(); final int fh = mFrame.height(); - applyGravityAndUpdateFrame(); + applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame); + + // Offset the actual frame by the amount layout frame is off. + mFrame.offset(-layoutXDiff, -layoutYDiff); + mCompatFrame.offset(-layoutXDiff, -layoutYDiff); // Calculate the outsets before the content frame gets shrinked to the window frame. if (hasOutsets) { @@ -735,12 +784,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { mOutsets.set(0, 0, 0, 0); } - // Denotes the actual frame used to calculate the insets. When resizing in docked mode, - // we'd like to freeze the layout, so we also need to freeze the insets temporarily. By the - // notion of a task having a different inset frame, we can achieve that while still moving - // the task around. - final Rect frame = !mInsetFrame.isEmpty() ? mInsetFrame : mFrame; - // Make sure the content and visible frames are inside of the // final window frame. if (windowsAreFloating && !mFrame.isEmpty()) { @@ -769,29 +812,29 @@ final class WindowState implements WindowManagerPolicy.WindowState { mMovedByResize = true; } } else { - mContentFrame.set(Math.max(mContentFrame.left, frame.left), - Math.max(mContentFrame.top, frame.top), - Math.min(mContentFrame.right, frame.right), - Math.min(mContentFrame.bottom, frame.bottom)); + mContentFrame.set(Math.max(mContentFrame.left, layoutContainingFrame.left), + Math.max(mContentFrame.top, layoutContainingFrame.top), + Math.min(mContentFrame.right, layoutContainingFrame.right), + Math.min(mContentFrame.bottom, layoutContainingFrame.bottom)); - mVisibleFrame.set(Math.max(mVisibleFrame.left, frame.left), - Math.max(mVisibleFrame.top, frame.top), - Math.min(mVisibleFrame.right, frame.right), - Math.min(mVisibleFrame.bottom, frame.bottom)); + mVisibleFrame.set(Math.max(mVisibleFrame.left, layoutContainingFrame.left), + Math.max(mVisibleFrame.top, layoutContainingFrame.top), + Math.min(mVisibleFrame.right, layoutContainingFrame.right), + Math.min(mVisibleFrame.bottom, layoutContainingFrame.bottom)); - mStableFrame.set(Math.max(mStableFrame.left, frame.left), - Math.max(mStableFrame.top, frame.top), - Math.min(mStableFrame.right, frame.right), - Math.min(mStableFrame.bottom, frame.bottom)); + mStableFrame.set(Math.max(mStableFrame.left, layoutContainingFrame.left), + Math.max(mStableFrame.top, layoutContainingFrame.top), + Math.min(mStableFrame.right, layoutContainingFrame.right), + Math.min(mStableFrame.bottom, layoutContainingFrame.bottom)); } if (fullscreenTask && !windowsAreFloating) { // Windows that are not fullscreen can be positioned outside of the display frame, // but that is not a reason to provide them with overscan insets. - mOverscanInsets.set(Math.max(mOverscanFrame.left - frame.left, 0), - Math.max(mOverscanFrame.top - frame.top, 0), - Math.max(frame.right - mOverscanFrame.right, 0), - Math.max(frame.bottom - mOverscanFrame.bottom, 0)); + mOverscanInsets.set(Math.max(mOverscanFrame.left - layoutContainingFrame.left, 0), + Math.max(mOverscanFrame.top - layoutContainingFrame.top, 0), + Math.max(layoutContainingFrame.right - mOverscanFrame.right, 0), + Math.max(layoutContainingFrame.bottom - mOverscanFrame.bottom, 0)); } if (mAttrs.type == TYPE_DOCK_DIVIDER) { @@ -812,45 +855,32 @@ final class WindowState implements WindowManagerPolicy.WindowState { // non-fullscreen mode. boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right; boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom; - mContentInsets.set(mContentFrame.left - frame.left, - mContentFrame.top - frame.top, + mContentInsets.set(mContentFrame.left - layoutContainingFrame.left, + mContentFrame.top - layoutContainingFrame.top, overrideRightInset ? mTmpRect.right - mContentFrame.right - : frame.right - mContentFrame.right, + : layoutContainingFrame.right - mContentFrame.right, overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom - : frame.bottom - mContentFrame.bottom); + : layoutContainingFrame.bottom - mContentFrame.bottom); - mVisibleInsets.set(mVisibleFrame.left - frame.left, - mVisibleFrame.top - frame.top, + mVisibleInsets.set(mVisibleFrame.left - layoutContainingFrame.left, + mVisibleFrame.top - layoutContainingFrame.top, overrideRightInset ? mTmpRect.right - mVisibleFrame.right - : frame.right - mVisibleFrame.right, + : layoutContainingFrame.right - mVisibleFrame.right, overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom - : frame.bottom - mVisibleFrame.bottom); + : layoutContainingFrame.bottom - mVisibleFrame.bottom); - mStableInsets.set(Math.max(mStableFrame.left - frame.left, 0), - Math.max(mStableFrame.top - frame.top, 0), + mStableInsets.set(Math.max(mStableFrame.left - layoutContainingFrame.left, 0), + Math.max(mStableFrame.top - layoutContainingFrame.top, 0), overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0) - : Math.max(frame.right - mStableFrame.right, 0), + : Math.max(layoutContainingFrame.right - mStableFrame.right, 0), overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0) - : Math.max(frame.bottom - mStableFrame.bottom, 0)); + : Math.max(layoutContainingFrame.bottom - mStableFrame.bottom, 0)); } - if (!mInsetFrame.isEmpty()) { - mContentFrame.set(mFrame); - mContentFrame.top += mContentInsets.top; - mContentFrame.bottom -= mContentInsets.bottom; - mContentFrame.left += mContentInsets.left; - mContentFrame.right -= mContentInsets.right; - mVisibleFrame.set(mFrame); - mVisibleFrame.top += mVisibleInsets.top; - mVisibleFrame.bottom -= mVisibleInsets.bottom; - mVisibleFrame.left += mVisibleInsets.left; - mVisibleFrame.right -= mVisibleInsets.right; - mStableFrame.set(mFrame); - mStableFrame.top += mStableInsets.top; - mStableFrame.bottom -= mStableInsets.bottom; - mStableFrame.left += mStableInsets.left; - mStableFrame.right -= mStableInsets.right; - } + mContentFrame.offset(-layoutXDiff, -layoutYDiff); + mVisibleFrame.offset(-layoutXDiff, -layoutYDiff); + mStableFrame.offset(-layoutXDiff, -layoutYDiff); + mCompatFrame.set(mFrame); if (mEnforceSizeCompat) { // If there is a size compatibility scale being applied to the @@ -2549,9 +2579,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } - void applyGravityAndUpdateFrame() { - final int pw = mContainingFrame.width(); - final int ph = mContainingFrame.height(); + void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) { + final int pw = containingFrame.width(); + final int ph = containingFrame.height(); final Task task = getTask(); final boolean nonFullscreenTask = isInMultiWindowMode(); final boolean fitToDisplay = task != null && !task.isFloating() && !layoutInParentFrame(); @@ -2606,13 +2636,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { } // Set mFrame - Gravity.apply(mAttrs.gravity, w, h, mContainingFrame, + Gravity.apply(mAttrs.gravity, w, h, containingFrame, (int) (x + mAttrs.horizontalMargin * pw), (int) (y + mAttrs.verticalMargin * ph), mFrame); // Now make sure the window fits in the overall display frame. if (fitToDisplay) { - Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame); + Gravity.applyDisplay(mAttrs.gravity, displayFrame, mFrame); } // We need to make sure we update the CompatFrame as it is used for diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 8fd8bc06a90a..34452ee1eefa 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1318,6 +1318,11 @@ class WindowStateAnimator { final WindowState w = mWin; final Task task = w.getTask(); + // We got resized, so block all updates until we got the new surface. + if (w.mResizedWhileNotDragResizing) { + return; + } + mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0); calculateSurfaceBounds(w, w.getAttrs()); diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index eda2f39480a8..04aa735bc99d 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -1582,7 +1582,8 @@ class WindowSurfacePlacer { // synchronize its thumbnail surface with the surface for the // open/close animation (only on the way down) anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect, - insets, thumbnailHeader, taskId, mService.mCurConfiguration.orientation); + insets, thumbnailHeader, taskId, mService.mCurConfiguration.uiMode, + mService.mCurConfiguration.orientation); openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer); openingAppAnimator.deferThumbnailDestruction = !mService.mAppTransition.isNextThumbnailTransitionScaleUp(); diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index a5237ca89520..cd485c55c816 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -1312,6 +1312,12 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */, } } +static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */, + jlong ptr, jint deviceId) { + NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); + im->getInputManager()->getReader()->toggleCapsLockState(deviceId); +} + static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */, jlong ptr, jobjectArray windowHandleObjArray) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); @@ -1508,6 +1514,8 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*) nativeSetInputFilterEnabled }, { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I", (void*) nativeInjectInputEvent }, + { "nativeToggleCapsLock", "(JI)V", + (void*) nativeToggleCapsLock }, { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V", (void*) nativeSetInputWindows }, { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V", diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 0d4887d65cfe..42b57054a4ba 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1131,9 +1131,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } String tagDAM = parser.getName(); if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) { - PersistableBundle bundle = new PersistableBundle(); - bundle.restoreFromXml(parser); - result.options = bundle; + result.options = PersistableBundle.restoreFromXml(parser); } else { Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM); } @@ -4357,6 +4355,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + /** + * @return {@code true} if the package is installed and set as always-on, {@code false} if it is + * not installed and therefore not available. + * + * @throws SecurityException if the caller is not a profile or device owner. + * @throws UnsupportedException if the package does not support being set as always-on. + */ @Override public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage) throws SecurityException { @@ -4366,13 +4371,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int userId = mInjector.userHandleGetCallingUserId(); final long token = mInjector.binderClearCallingIdentity(); - try{ + try { + if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) { + return false; + } ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - return connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage); + if (!connectivityManager.setAlwaysOnVpnPackageForUser(userId, vpnPackage)) { + throw new UnsupportedOperationException(); + } } finally { mInjector.binderRestoreCallingIdentity(token); } + return true; } @Override @@ -6395,17 +6406,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent, - PersistableBundle args) { + PersistableBundle args, boolean parent) { if (!mHasFeature) { return; } Preconditions.checkNotNull(admin, "admin is null"); Preconditions.checkNotNull(agent, "agent is null"); final int userHandle = UserHandle.getCallingUserId(); - enforceNotManagedProfile(userHandle, "set trust agent configuration"); synchronized (this) { ActiveAdmin ap = getActiveAdminForCallerLocked(admin, - DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES); + DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES, parent); ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args)); saveSettingsLocked(userHandle); } @@ -6413,7 +6423,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin, - ComponentName agent, int userHandle) { + ComponentName agent, int userHandle, boolean parent) { if (!mHasFeature) { return null; } @@ -6423,46 +6433,44 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { final String componentName = agent.flattenToString(); if (admin != null) { - final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle); + final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle, parent); if (ap == null) return null; TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName); if (trustAgentInfo == null || trustAgentInfo.options == null) return null; - List<PersistableBundle> result = new ArrayList<PersistableBundle>(); + List<PersistableBundle> result = new ArrayList<>(); result.add(trustAgentInfo.options); return result; } // Return strictest policy for this user and profiles that are visible from this user. - final List<UserInfo> profiles = mUserManager.getProfiles(userHandle); List<PersistableBundle> result = null; - // Search through all admins that use KEYGUARD_DISABLE_TRUST_AGENTS and keep track // of the options. If any admin doesn't have options, discard options for the rest // and return null. + List<ActiveAdmin> admins = + getActiveAdminsForLockscreenPoliciesLocked(userHandle, parent); boolean allAdminsHaveOptions = true; - for (UserInfo userInfo : profiles) { - DevicePolicyData policy = getUserDataUnchecked(userInfo.id); - final int N = policy.mAdminList.size(); - for (int i=0; i < N; i++) { - final ActiveAdmin active = policy.mAdminList.get(i); - final boolean disablesTrust = (active.disabledKeyguardFeatures - & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; - final TrustAgentInfo info = active.trustAgentInfos.get(componentName); - if (info != null && info.options != null && !info.options.isEmpty()) { - if (disablesTrust) { - if (result == null) { - result = new ArrayList<PersistableBundle>(); - } - result.add(info.options); - } else { - Log.w(LOG_TAG, "Ignoring admin " + active.info - + " because it has trust options but doesn't declare " - + "KEYGUARD_DISABLE_TRUST_AGENTS"); + final int N = admins.size(); + for (int i = 0; i < N; i++) { + final ActiveAdmin active = admins.get(i); + + final boolean disablesTrust = (active.disabledKeyguardFeatures + & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0; + final TrustAgentInfo info = active.trustAgentInfos.get(componentName); + if (info != null && info.options != null && !info.options.isEmpty()) { + if (disablesTrust) { + if (result == null) { + result = new ArrayList<>(); } - } else if (disablesTrust) { - allAdminsHaveOptions = false; - break; + result.add(info.options); + } else { + Log.w(LOG_TAG, "Ignoring admin " + active.info + + " because it has trust options but doesn't declare " + + "KEYGUARD_DISABLE_TRUST_AGENTS"); } + } else if (disablesTrust) { + allAdminsHaveOptions = false; + break; } } return allAdminsHaveOptions ? result : null; diff --git a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java index 5b70c17ae28d..07280bc881d8 100644 --- a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java +++ b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java @@ -62,7 +62,7 @@ public class ObserverNodeTest extends AndroidTestCase { ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); for (int i = nums.length - 1; i >=0; --i) { - root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls); + root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls); assertEquals(nums[i], calls.size()); calls.clear(); } @@ -92,7 +92,7 @@ public class ObserverNodeTest extends AndroidTestCase { ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); for (int i = uris.length - 1; i >=0; --i) { - root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls); + root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls); assertEquals(nums[i], calls.size()); calls.clear(); } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index beec40f8b0fa..0aeb96f52181 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -144,6 +144,7 @@ public class UsageStatsService extends SystemService implements private long mLastAppIdleParoledTime; private volatile boolean mPendingOneTimeCheckIdleStates; + private boolean mSystemServicesReady = false; @GuardedBy("mLock") private AppIdleHistory mAppIdleHistory; @@ -232,6 +233,8 @@ public class UsageStatsService extends SystemService implements if (mPendingOneTimeCheckIdleStates) { postOneTimeCheckIdleStates(); } + + mSystemServicesReady = true; } else if (phase == PHASE_BOOT_COMPLETED) { setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging()); } @@ -810,28 +813,30 @@ public class UsageStatsService extends SystemService implements // retain this for safety). return false; } - try { - // We allow all whitelisted apps, including those that don't want to be whitelisted - // for idle mode, because app idle (aka app standby) is really not as big an issue - // for controlling who participates vs. doze mode. - if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) { - return false; + if (mSystemServicesReady) { + try { + // We allow all whitelisted apps, including those that don't want to be whitelisted + // for idle mode, because app idle (aka app standby) is really not as big an issue + // for controlling who participates vs. doze mode. + if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) { + return false; + } + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); } - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - if (isActiveDeviceAdmin(packageName, userId)) { - return false; - } + if (isActiveDeviceAdmin(packageName, userId)) { + return false; + } - if (isActiveNetworkScorer(packageName)) { - return false; - } + if (isActiveNetworkScorer(packageName)) { + return false; + } - if (mAppWidgetManager != null - && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) { - return false; + if (mAppWidgetManager != null + && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) { + return false; + } } if (!isAppIdleUnfiltered(packageName, userId, elapsedRealtime)) { diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk index 876a422a2678..ef11d662b2ce 100644 --- a/tools/aapt2/Android.mk +++ b/tools/aapt2/Android.mk @@ -66,6 +66,7 @@ sources := \ ResourceValues.cpp \ SdkConstants.cpp \ StringPool.cpp \ + xml/XmlActionExecutor.cpp \ xml/XmlDom.cpp \ xml/XmlPullParser.cpp \ xml/XmlUtil.cpp @@ -107,6 +108,7 @@ testSources := \ SdkConstants_test.cpp \ StringPool_test.cpp \ ValueVisitor_test.cpp \ + xml/XmlActionExecutor_test.cpp \ xml/XmlDom_test.cpp \ xml/XmlPullParser_test.cpp \ xml/XmlUtil_test.cpp @@ -140,7 +142,7 @@ else endif cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG -cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions -fno-rtti +cppFlags := -std=c++14 -Wno-missing-field-initializers -fno-exceptions -fno-rtti protoIncludes := $(call generated-sources-dir-for,STATIC_LIBRARIES,libaapt2,HOST) # ========================================================== diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h index ab4d284516e1..e86f2a8830e8 100644 --- a/tools/aapt2/Diagnostics.h +++ b/tools/aapt2/Diagnostics.h @@ -21,6 +21,7 @@ #include "util/StringPiece.h" #include "util/Util.h" +#include <android-base/macros.h> #include <iostream> #include <sstream> #include <string> @@ -46,7 +47,11 @@ public: DiagMessage(const Source& src) : mSource(src) { } - template <typename T> DiagMessage& operator<<(const T& value) { + DiagMessage(size_t line) : mSource(Source().withLine(line)) { + } + + template <typename T> + DiagMessage& operator<<(const T& value) { mMessage << value; return *this; } @@ -59,36 +64,82 @@ public: struct IDiagnostics { virtual ~IDiagnostics() = default; - virtual void error(const DiagMessage& message) = 0; - virtual void warn(const DiagMessage& message) = 0; - virtual void note(const DiagMessage& message) = 0; -}; + enum class Level { + Note, + Warn, + Error + }; -struct StdErrDiagnostics : public IDiagnostics { - size_t mNumErrors = 0; + virtual void log(Level level, DiagMessageActual& actualMsg) = 0; - void emit(const DiagMessage& msg, const char* tag) { - DiagMessageActual actual = msg.build(); - if (!actual.source.path.empty()) { - std::cerr << actual.source << ": "; - } - std::cerr << tag << actual.message << "." << std::endl; + virtual void error(const DiagMessage& message) { + DiagMessageActual actual = message.build(); + log(Level::Error, actual); + } + + virtual void warn(const DiagMessage& message) { + DiagMessageActual actual = message.build(); + log(Level::Warn, actual); + } + + virtual void note(const DiagMessage& message) { + DiagMessageActual actual = message.build(); + log(Level::Note, actual); } +}; - void error(const DiagMessage& msg) override { - if (mNumErrors < 20) { - emit(msg, "error: "); +class StdErrDiagnostics : public IDiagnostics { +public: + StdErrDiagnostics() = default; + + void log(Level level, DiagMessageActual& actualMsg) override { + const char* tag; + + switch (level) { + case Level::Error: + mNumErrors++; + if (mNumErrors > 20) { + return; + } + tag = "error"; + break; + + case Level::Warn: + tag = "warn"; + break; + + case Level::Note: + tag = "note"; + break; } - mNumErrors++; + + if (!actualMsg.source.path.empty()) { + std::cerr << actualMsg.source << ": "; + } + std::cerr << tag << ": " << actualMsg.message << "." << std::endl; } - void warn(const DiagMessage& msg) override { - emit(msg, "warn: "); +private: + size_t mNumErrors = 0; + + DISALLOW_COPY_AND_ASSIGN(StdErrDiagnostics); +}; + +class SourcePathDiagnostics : public IDiagnostics { +public: + SourcePathDiagnostics(const Source& src, IDiagnostics* diag) : mSource(src), mDiag(diag) { } - void note(const DiagMessage& msg) override { - emit(msg, "note: "); + void log(Level level, DiagMessageActual& actualMsg) override { + actualMsg.source.path = mSource.path; + mDiag->log(level, actualMsg); } + +private: + Source mSource; + IDiagnostics* mDiag; + + DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics); }; } // namespace aapt diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp index 180bd11275df..d6c52ab83d93 100644 --- a/tools/aapt2/ResourceTable_test.cpp +++ b/tools/aapt2/ResourceTable_test.cpp @@ -28,33 +28,23 @@ namespace aapt { -struct ResourceTableTest : public ::testing::Test { - struct EmptyDiagnostics : public IDiagnostics { - void error(const DiagMessage& msg) override {} - void warn(const DiagMessage& msg) override {} - void note(const DiagMessage& msg) override {} - }; - - EmptyDiagnostics mDiagnostics; -}; - -TEST_F(ResourceTableTest, FailToAddResourceWithBadName) { +TEST(ResourceTableTest, FailToAddResourceWithBadName) { ResourceTable table; EXPECT_FALSE(table.addResource( ResourceNameRef(u"android", ResourceType::kId, u"hey,there"), ConfigDescription{}, "", test::ValueBuilder<Id>().setSource("test.xml", 21u).build(), - &mDiagnostics)); + test::getDiagnostics())); EXPECT_FALSE(table.addResource( ResourceNameRef(u"android", ResourceType::kId, u"hey:there"), ConfigDescription{}, "", test::ValueBuilder<Id>().setSource("test.xml", 21u).build(), - &mDiagnostics)); + test::getDiagnostics())); } -TEST_F(ResourceTableTest, AddOneResource) { +TEST(ResourceTableTest, AddOneResource) { ResourceTable table; EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/id"), @@ -62,12 +52,12 @@ TEST_F(ResourceTableTest, AddOneResource) { "", test::ValueBuilder<Id>() .setSource("test/path/file.xml", 23u).build(), - &mDiagnostics)); + test::getDiagnostics())); ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id")); } -TEST_F(ResourceTableTest, AddMultipleResources) { +TEST(ResourceTableTest, AddMultipleResources) { ResourceTable table; ConfigDescription config; @@ -79,21 +69,21 @@ TEST_F(ResourceTableTest, AddMultipleResources) { config, "", test::ValueBuilder<Id>().setSource("test/path/file.xml", 10u).build(), - &mDiagnostics)); + test::getDiagnostics())); EXPECT_TRUE(table.addResource( test::parseNameOrDie(u"@android:attr/id"), config, "", test::ValueBuilder<Id>().setSource("test/path/file.xml", 12u).build(), - &mDiagnostics)); + test::getDiagnostics())); EXPECT_TRUE(table.addResource( test::parseNameOrDie(u"@android:string/ok"), config, "", test::ValueBuilder<Id>().setSource("test/path/file.xml", 14u).build(), - &mDiagnostics)); + test::getDiagnostics())); EXPECT_TRUE(table.addResource( test::parseNameOrDie(u"@android:string/ok"), @@ -102,7 +92,7 @@ TEST_F(ResourceTableTest, AddMultipleResources) { test::ValueBuilder<BinaryPrimitive>(android::Res_value{}) .setSource("test/path/file.xml", 20u) .build(), - &mDiagnostics)); + test::getDiagnostics())); ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/layout_width")); ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id")); @@ -111,37 +101,37 @@ TEST_F(ResourceTableTest, AddMultipleResources) { languageConfig)); } -TEST_F(ResourceTableTest, OverrideWeakResourceValue) { +TEST(ResourceTableTest, OverrideWeakResourceValue) { ResourceTable table; ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{}, - "", util::make_unique<Attribute>(true), &mDiagnostics)); + "", util::make_unique<Attribute>(true), test::getDiagnostics())); Attribute* attr = test::getValue<Attribute>(&table, u"@android:attr/foo"); ASSERT_NE(nullptr, attr); EXPECT_TRUE(attr->isWeak()); ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{}, - "", util::make_unique<Attribute>(false), &mDiagnostics)); + "", util::make_unique<Attribute>(false), test::getDiagnostics())); attr = test::getValue<Attribute>(&table, u"@android:attr/foo"); ASSERT_NE(nullptr, attr); EXPECT_FALSE(attr->isWeak()); } -TEST_F(ResourceTableTest, ProductVaryingValues) { +TEST(ResourceTableTest, ProductVaryingValues) { ResourceTable table; EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"), test::parseConfigOrDie("land"), "tablet", util::make_unique<Id>(), - &mDiagnostics)); + test::getDiagnostics())); EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"), test::parseConfigOrDie("land"), "phone", util::make_unique<Id>(), - &mDiagnostics)); + test::getDiagnostics())); EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/foo", test::parseConfigOrDie("land"), diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 9baf1d86795c..3779638590be 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -17,66 +17,199 @@ #include "ResourceUtils.h" #include "link/ManifestFixer.h" #include "util/Util.h" +#include "xml/XmlActionExecutor.h" #include "xml/XmlDom.h" namespace aapt { -static bool verifyManifest(IAaptContext* context, const Source& source, xml::Element* manifestEl) { - xml::Attribute* attr = manifestEl->findAttribute({}, u"package"); - if (!attr) { - context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber)) - << "missing 'package' attribute"); - } else if (ResourceUtils::isReference(attr->value)) { - context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber)) - << "value for attribute 'package' must not be a " - "reference"); - } else if (!util::isJavaPackageName(attr->value)) { - context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber)) - << "invalid package name '" << attr->value << "'"); - } else { - return true; +/** + * This is how PackageManager builds class names from AndroidManifest.xml entries. + */ +static bool nameIsJavaClassName(xml::Element* el, xml::Attribute* attr, + SourcePathDiagnostics* diag) { + std::u16string className = attr->value; + if (className.find(u'.') == std::u16string::npos) { + // There is no '.', so add one to the beginning. + className = u"."; + className += attr->value; } - return false; -} -static bool includeVersionName(IAaptContext* context, const Source& source, - const StringPiece16& versionName, xml::Element* manifestEl) { - if (manifestEl->findAttribute(xml::kSchemaAndroid, u"versionName")) { - return true; + // We allow unqualified class names (ie: .HelloActivity) + // Since we don't know the package name, we can just make a fake one here and + // the test will be identical as long as the real package name is valid too. + Maybe<std::u16string> fullyQualifiedClassName = + util::getFullyQualifiedClassName(u"a", className); + + StringPiece16 qualifiedClassName = fullyQualifiedClassName + ? fullyQualifiedClassName.value() : className; + if (!util::isJavaClassName(qualifiedClassName)) { + diag->error(DiagMessage(el->lineNumber) + << "attribute 'android:name' in <" + << el->name << "> tag must be a valid Java class name"); + return false; } + return true; +} - manifestEl->attributes.push_back(xml::Attribute{ - xml::kSchemaAndroid, u"versionName", versionName.toString() }); +static bool optionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) { + if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) { + return nameIsJavaClassName(el, attr, diag); + } return true; } -static bool includeVersionCode(IAaptContext* context, const Source& source, - const StringPiece16& versionCode, xml::Element* manifestEl) { - if (manifestEl->findAttribute(xml::kSchemaAndroid, u"versionCode")) { - return true; +static bool requiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) { + if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) { + return nameIsJavaClassName(el, attr, diag); } + diag->error(DiagMessage(el->lineNumber) + << "<" << el->name << "> is missing attribute 'android:name'"); + return false; +} - manifestEl->attributes.push_back(xml::Attribute{ - xml::kSchemaAndroid, u"versionCode", versionCode.toString() }); +static bool verifyManifest(xml::Element* el, SourcePathDiagnostics* diag) { + xml::Attribute* attr = el->findAttribute({}, u"package"); + if (!attr) { + diag->error(DiagMessage(el->lineNumber) << "<manifest> tag is missing 'package' attribute"); + return false; + } else if (ResourceUtils::isReference(attr->value)) { + diag->error(DiagMessage(el->lineNumber) + << "attribute 'package' in <manifest> tag must not be a reference"); + return false; + } else if (!util::isJavaPackageName(attr->value)) { + diag->error(DiagMessage(el->lineNumber) + << "attribute 'package' in <manifest> tag is not a valid Java package name: '" + << attr->value << "'"); + return false; + } return true; } -static bool fixUsesSdk(IAaptContext* context, const Source& source, xml::Element* el, - const ManifestFixerOptions& options) { - if (options.minSdkVersionDefault && - el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) { - // There was no minSdkVersion defined and we have a default to assign. - el->attributes.push_back(xml::Attribute{ - xml::kSchemaAndroid, u"minSdkVersion", options.minSdkVersionDefault.value() }); +bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag) { + // First verify some options. + if (mOptions.renameManifestPackage) { + if (!util::isJavaPackageName(mOptions.renameManifestPackage.value())) { + diag->error(DiagMessage() << "invalid manifest package override '" + << mOptions.renameManifestPackage.value() << "'"); + return false; + } } - if (options.targetSdkVersionDefault && - el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) { - // There was no targetSdkVersion defined and we have a default to assign. - el->attributes.push_back(xml::Attribute{ - xml::kSchemaAndroid, u"targetSdkVersion", - options.targetSdkVersionDefault.value() }); + if (mOptions.renameInstrumentationTargetPackage) { + if (!util::isJavaPackageName(mOptions.renameInstrumentationTargetPackage.value())) { + diag->error(DiagMessage() << "invalid instrumentation target package override '" + << mOptions.renameInstrumentationTargetPackage.value() << "'"); + return false; + } } + + // Common intent-filter actions. + xml::XmlNodeAction intentFilterAction; + intentFilterAction[u"action"]; + intentFilterAction[u"category"]; + intentFilterAction[u"data"]; + + // Common meta-data actions. + xml::XmlNodeAction metaDataAction; + + // Manifest actions. + xml::XmlNodeAction& manifestAction = (*executor)[u"manifest"]; + manifestAction.action(verifyManifest); + manifestAction.action([&](xml::Element* el) -> bool { + if (mOptions.versionNameDefault) { + if (el->findAttribute(xml::kSchemaAndroid, u"versionName") == nullptr) { + el->attributes.push_back(xml::Attribute{ + xml::kSchemaAndroid, + u"versionName", + mOptions.versionNameDefault.value() }); + } + } + + if (mOptions.versionCodeDefault) { + if (el->findAttribute(xml::kSchemaAndroid, u"versionCode") == nullptr) { + el->attributes.push_back(xml::Attribute{ + xml::kSchemaAndroid, + u"versionCode", + mOptions.versionCodeDefault.value() }); + } + } + return true; + }); + + // Uses-sdk actions. + manifestAction[u"uses-sdk"].action([&](xml::Element* el) -> bool { + if (mOptions.minSdkVersionDefault && + el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) { + // There was no minSdkVersion defined and we have a default to assign. + el->attributes.push_back(xml::Attribute{ + xml::kSchemaAndroid, u"minSdkVersion", + mOptions.minSdkVersionDefault.value() }); + } + + if (mOptions.targetSdkVersionDefault && + el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) { + // There was no targetSdkVersion defined and we have a default to assign. + el->attributes.push_back(xml::Attribute{ + xml::kSchemaAndroid, u"targetSdkVersion", + mOptions.targetSdkVersionDefault.value() }); + } + return true; + }); + + // Instrumentation actions. + manifestAction[u"instrumentation"].action([&](xml::Element* el) -> bool { + if (!mOptions.renameInstrumentationTargetPackage) { + return true; + } + + if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"targetPackage")) { + attr->value = mOptions.renameInstrumentationTargetPackage.value(); + } + return true; + }); + + manifestAction[u"eat-comment"]; + manifestAction[u"protected-broadcast"]; + manifestAction[u"uses-permission"]; + manifestAction[u"permission"]; + manifestAction[u"permission-tree"]; + manifestAction[u"permission-group"]; + + manifestAction[u"uses-configuration"]; + manifestAction[u"uses-feature"]; + manifestAction[u"uses-library"]; + manifestAction[u"supports-screens"]; + manifestAction[u"compatible-screens"]; + manifestAction[u"supports-gl-texture"]; + + // Application actions. + xml::XmlNodeAction& applicationAction = (*executor)[u"manifest"][u"application"]; + applicationAction.action(optionalNameIsJavaClassName); + + // Activity actions. + applicationAction[u"activity"].action(requiredNameIsJavaClassName); + applicationAction[u"activity"][u"intent-filter"] = intentFilterAction; + applicationAction[u"activity"][u"meta-data"] = metaDataAction; + + // Activity alias actions. + applicationAction[u"activity-alias"][u"intent-filter"] = intentFilterAction; + applicationAction[u"activity-alias"][u"meta-data"] = metaDataAction; + + // Service actions. + applicationAction[u"service"].action(requiredNameIsJavaClassName); + applicationAction[u"service"][u"intent-filter"] = intentFilterAction; + applicationAction[u"service"][u"meta-data"] = metaDataAction; + + // Receiver actions. + applicationAction[u"receiver"].action(requiredNameIsJavaClassName); + applicationAction[u"receiver"][u"intent-filter"] = intentFilterAction; + applicationAction[u"receiver"][u"meta-data"] = metaDataAction; + + // Provider actions. + applicationAction[u"provider"].action(requiredNameIsJavaClassName); + applicationAction[u"provider"][u"grant-uri-permissions"]; + applicationAction[u"provider"][u"meta-data"] = metaDataAction; + applicationAction[u"provider"][u"path-permissions"]; return true; } @@ -103,14 +236,7 @@ private: StringPiece16 mPackage; }; -static bool renameManifestPackage(IAaptContext* context, const Source& source, - const StringPiece16& packageOverride, xml::Element* manifestEl) { - if (!util::isJavaPackageName(packageOverride)) { - context->getDiagnostics()->error(DiagMessage() << "invalid manifest package override '" - << packageOverride << "'"); - return false; - } - +static bool renameManifestPackage(const StringPiece16& packageOverride, xml::Element* manifestEl) { xml::Attribute* attr = manifestEl->findAttribute({}, u"package"); // We've already verified that the manifest element is present, with a package name specified. @@ -124,32 +250,6 @@ static bool renameManifestPackage(IAaptContext* context, const Source& source, return true; } -static bool renameInstrumentationTargetPackage(IAaptContext* context, const Source& source, - const StringPiece16& packageOverride, - xml::Element* manifestEl) { - if (!util::isJavaPackageName(packageOverride)) { - context->getDiagnostics()->error(DiagMessage() - << "invalid instrumentation target package override '" - << packageOverride << "'"); - return false; - } - - xml::Element* instrumentationEl = manifestEl->findChild({}, u"instrumentation"); - if (!instrumentationEl) { - // No error if there is no work to be done. - return true; - } - - xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, u"targetPackage"); - if (!attr) { - // No error if there is no work to be done. - return true; - } - - attr->value = packageOverride.toString(); - return true; -} - bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) { xml::Element* root = xml::findRootElement(doc->root.get()); if (!root || !root->namespaceUri.empty() || root->name != u"manifest") { @@ -158,59 +258,31 @@ bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) { return false; } - if (!verifyManifest(context, doc->file.source, root)) { - return false; + if ((mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault) + && root->findChild({}, u"uses-sdk") == nullptr) { + // Auto insert a <uses-sdk> element. + std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>(); + usesSdk->name = u"uses-sdk"; + root->addChild(std::move(usesSdk)); } - if (mOptions.versionCodeDefault) { - if (!includeVersionCode(context, doc->file.source, mOptions.versionCodeDefault.value(), - root)) { - return false; - } + xml::XmlActionExecutor executor; + if (!buildRules(&executor, context->getDiagnostics())) { + return false; } - if (mOptions.versionNameDefault) { - if (!includeVersionName(context, doc->file.source, mOptions.versionNameDefault.value(), - root)) { - return false; - } + if (!executor.execute(xml::XmlActionExecutorPolicy::Whitelist, context->getDiagnostics(), + doc)) { + return false; } if (mOptions.renameManifestPackage) { - // Rename manifest package. - if (!renameManifestPackage(context, doc->file.source, - mOptions.renameManifestPackage.value(), root)) { - return false; - } - } - - if (mOptions.renameInstrumentationTargetPackage) { - if (!renameInstrumentationTargetPackage(context, doc->file.source, - mOptions.renameInstrumentationTargetPackage.value(), - root)) { + // Rename manifest package outside of the XmlActionExecutor. + // We need to extract the old package name and FullyQualify all class names. + if (!renameManifestPackage(mOptions.renameManifestPackage.value(), root)) { return false; } } - - bool foundUsesSdk = false; - for (xml::Element* el : root->getChildElements()) { - if (!el->namespaceUri.empty()) { - continue; - } - - if (el->name == u"uses-sdk") { - foundUsesSdk = true; - fixUsesSdk(context, doc->file.source, el, mOptions); - } - } - - if (!foundUsesSdk && (mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault)) { - std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>(); - usesSdk->name = u"uses-sdk"; - fixUsesSdk(context, doc->file.source, usesSdk.get(), mOptions); - root->addChild(std::move(usesSdk)); - } - return true; } diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h index b8d9c833ff05..4d9356a933c2 100644 --- a/tools/aapt2/link/ManifestFixer.h +++ b/tools/aapt2/link/ManifestFixer.h @@ -19,6 +19,7 @@ #include "process/IResourceTableConsumer.h" #include "util/Maybe.h" +#include "xml/XmlActionExecutor.h" #include "xml/XmlDom.h" #include <string> @@ -38,13 +39,17 @@ struct ManifestFixerOptions { * Verifies that the manifest is correctly formed and inserts defaults * where specified with ManifestFixerOptions. */ -struct ManifestFixer : public IXmlResourceConsumer { - ManifestFixerOptions mOptions; - +class ManifestFixer : public IXmlResourceConsumer { +public: ManifestFixer(const ManifestFixerOptions& options) : mOptions(options) { } bool consume(IAaptContext* context, xml::XmlResource* doc) override; + +private: + bool buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag); + + ManifestFixerOptions mOptions; }; } // namespace aapt diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 18c47dff33ec..f993720b9566 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -166,9 +166,9 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) { std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF( <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"> - <application name=".MainApplication" text="hello"> - <activity name=".activity.Start" /> - <receiver name="com.google.android.Receiver" /> + <application android:name=".MainApplication" text="hello"> + <activity android:name=".activity.Start" /> + <receiver android:name="com.google.android.Receiver" /> </application> </manifest>)EOF", options); ASSERT_NE(nullptr, doc); @@ -185,7 +185,7 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) { xml::Element* applicationEl = manifestEl->findChild({}, u"application"); ASSERT_NE(nullptr, applicationEl); - attr = applicationEl->findAttribute({}, u"name"); + attr = applicationEl->findAttribute(xml::kSchemaAndroid, u"name"); ASSERT_NE(nullptr, attr); EXPECT_EQ(std::u16string(u"android.MainApplication"), attr->value); @@ -197,14 +197,14 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) { el = applicationEl->findChild({}, u"activity"); ASSERT_NE(nullptr, el); - attr = el->findAttribute({}, u"name"); + attr = el->findAttribute(xml::kSchemaAndroid, u"name"); ASSERT_NE(nullptr, el); EXPECT_EQ(std::u16string(u"android.activity.Start"), attr->value); el = applicationEl->findChild({}, u"receiver"); ASSERT_NE(nullptr, el); - attr = el->findAttribute({}, u"name"); + attr = el->findAttribute(xml::kSchemaAndroid, u"name"); ASSERT_NE(nullptr, el); EXPECT_EQ(std::u16string(u"com.google.android.Receiver"), attr->value); } diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index 8c56ebc67b32..8eb4bc88168d 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -238,7 +238,7 @@ inline std::unique_ptr<xml::XmlResource> buildXmlDom(const StringPiece& str) { std::stringstream in; in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str; StdErrDiagnostics diag; - std::unique_ptr<xml::XmlResource> doc = xml::inflate(&in, &diag, {}); + std::unique_ptr<xml::XmlResource> doc = xml::inflate(&in, &diag, Source("test.xml")); assert(doc); return doc; } diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index 348c32a04e88..faccd47783ff 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -41,15 +41,20 @@ namespace aapt { namespace test { struct DummyDiagnosticsImpl : public IDiagnostics { - void error(const DiagMessage& message) override { - DiagMessageActual actual = message.build(); - std::cerr << actual.source << ": error: " << actual.message << "." << std::endl; - } - void warn(const DiagMessage& message) override { - DiagMessageActual actual = message.build(); - std::cerr << actual.source << ": warn: " << actual.message << "." << std::endl; + void log(Level level, DiagMessageActual& actualMsg) override { + switch (level) { + case Level::Note: + return; + + case Level::Warn: + std::cerr << actualMsg.source << ": warn: " << actualMsg.message << "." << std::endl; + break; + + case Level::Error: + std::cerr << actualMsg.source << ": error: " << actualMsg.message << "." << std::endl; + break; + } } - void note(const DiagMessage& message) override {} }; inline IDiagnostics* getDiagnostics() { diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp new file mode 100644 index 000000000000..0ef67eaf3dc5 --- /dev/null +++ b/tools/aapt2/xml/XmlActionExecutor.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "xml/XmlActionExecutor.h" + +namespace aapt { +namespace xml { + +static bool wrapperOne(XmlNodeAction::ActionFunc& f, Element* el, SourcePathDiagnostics*) { + return f(el); +} + +static bool wrapperTwo(XmlNodeAction::ActionFuncWithDiag& f, Element* el, + SourcePathDiagnostics* diag) { + return f(el, diag); +} + +void XmlNodeAction::action(XmlNodeAction::ActionFunc f) { + mActions.emplace_back(std::bind(wrapperOne, std::move(f), + std::placeholders::_1, + std::placeholders::_2)); +} + +void XmlNodeAction::action(XmlNodeAction::ActionFuncWithDiag f) { + mActions.emplace_back(std::bind(wrapperTwo, std::move(f), + std::placeholders::_1, + std::placeholders::_2)); +} + +static void printElementToDiagMessage(const Element* el, DiagMessage* msg) { + *msg << "<"; + if (!el->namespaceUri.empty()) { + *msg << el->namespaceUri << ":"; + } + *msg << el->name << ">"; +} + +bool XmlNodeAction::execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag, + Element* el) const { + bool error = false; + for (const ActionFuncWithDiag& action : mActions) { + error |= !action(el, diag); + } + + for (Element* childEl : el->getChildElements()) { + if (childEl->namespaceUri.empty()) { + std::map<std::u16string, XmlNodeAction>::const_iterator iter = + mMap.find(childEl->name); + if (iter != mMap.end()) { + error |= !iter->second.execute(policy, diag, childEl); + continue; + } + } + + if (policy == XmlActionExecutorPolicy::Whitelist) { + DiagMessage errorMsg(childEl->lineNumber); + errorMsg << "unknown element "; + printElementToDiagMessage(childEl, &errorMsg); + errorMsg << " found"; + diag->error(errorMsg); + error = true; + } + } + return !error; +} + +bool XmlActionExecutor::execute(XmlActionExecutorPolicy policy, IDiagnostics* diag, + XmlResource* doc) const { + SourcePathDiagnostics sourceDiag(doc->file.source, diag); + + Element* el = findRootElement(doc); + if (!el) { + if (policy == XmlActionExecutorPolicy::Whitelist) { + sourceDiag.error(DiagMessage() << "no root XML tag found"); + return false; + } + return true; + } + + if (el->namespaceUri.empty()) { + std::map<std::u16string, XmlNodeAction>::const_iterator iter = mMap.find(el->name); + if (iter != mMap.end()) { + return iter->second.execute(policy, &sourceDiag, el); + } + } + + if (policy == XmlActionExecutorPolicy::Whitelist) { + DiagMessage errorMsg(el->lineNumber); + errorMsg << "unknown element "; + printElementToDiagMessage(el, &errorMsg); + errorMsg << " found"; + sourceDiag.error(errorMsg); + return false; + } + return true; +} + +} // namespace xml +} // namespace aapt diff --git a/tools/aapt2/xml/XmlActionExecutor.h b/tools/aapt2/xml/XmlActionExecutor.h new file mode 100644 index 000000000000..36b94dbfde05 --- /dev/null +++ b/tools/aapt2/xml/XmlActionExecutor.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AAPT_XML_XMLPATTERN_H +#define AAPT_XML_XMLPATTERN_H + +#include "Diagnostics.h" +#include "xml/XmlDom.h" + +#include <android-base/macros.h> +#include <functional> +#include <map> +#include <string> +#include <vector> + +namespace aapt { +namespace xml { + +enum class XmlActionExecutorPolicy { + /** + * Actions on run if elements are matched, errors occur only when actions return false. + */ + None, + + /** + * The actions defined must match and run. If an element is found that does not match + * an action, an error occurs. + */ + Whitelist, +}; + +/** + * Contains the actions to perform at this XML node. This is a recursive data structure that + * holds XmlNodeActions for child XML nodes. + */ +class XmlNodeAction { +public: + using ActionFuncWithDiag = std::function<bool(Element*, SourcePathDiagnostics*)>; + using ActionFunc = std::function<bool(Element*)>; + + /** + * Find or create a child XmlNodeAction that will be performed for the child element + * with the name `name`. + */ + XmlNodeAction& operator[](const std::u16string& name) { + return mMap[name]; + } + + /** + * Add an action to be performed at this XmlNodeAction. + */ + void action(ActionFunc f); + void action(ActionFuncWithDiag); + +private: + friend class XmlActionExecutor; + + bool execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag, Element* el) const; + + std::map<std::u16string, XmlNodeAction> mMap; + std::vector<ActionFuncWithDiag> mActions; +}; + +/** + * Allows the definition of actions to execute at specific XML elements defined by their + * hierarchy. + */ +class XmlActionExecutor { +public: + XmlActionExecutor() = default; + + /** + * Find or create a root XmlNodeAction that will be performed for the root XML element + * with the name `name`. + */ + XmlNodeAction& operator[](const std::u16string& name) { + return mMap[name]; + } + + /** + * Execute the defined actions for this XmlResource. + * Returns true if all actions return true, otherwise returns false. + */ + bool execute(XmlActionExecutorPolicy policy, IDiagnostics* diag, XmlResource* doc) const; + +private: + std::map<std::u16string, XmlNodeAction> mMap; + + DISALLOW_COPY_AND_ASSIGN(XmlActionExecutor); +}; + +} // namespace xml +} // namespace aapt + +#endif /* AAPT_XML_XMLPATTERN_H */ diff --git a/tools/aapt2/xml/XmlActionExecutor_test.cpp b/tools/aapt2/xml/XmlActionExecutor_test.cpp new file mode 100644 index 000000000000..ebf287a251f2 --- /dev/null +++ b/tools/aapt2/xml/XmlActionExecutor_test.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test/Test.h" +#include "xml/XmlActionExecutor.h" + +namespace aapt { +namespace xml { + +TEST(XmlActionExecutorTest, BuildsAccessibleNestedPattern) { + XmlActionExecutor executor; + XmlNodeAction& manifestAction = executor[u"manifest"]; + XmlNodeAction& applicationAction = manifestAction[u"application"]; + + Element* manifestEl = nullptr; + manifestAction.action([&](Element* manifest) -> bool { + manifestEl = manifest; + return true; + }); + + Element* applicationEl = nullptr; + applicationAction.action([&](Element* application) -> bool { + applicationEl = application; + return true; + }); + + std::unique_ptr<XmlResource> doc = test::buildXmlDom("<manifest><application /></manifest>"); + + StdErrDiagnostics diag; + ASSERT_TRUE(executor.execute(XmlActionExecutorPolicy::None, &diag, doc.get())); + ASSERT_NE(nullptr, manifestEl); + EXPECT_EQ(std::u16string(u"manifest"), manifestEl->name); + + ASSERT_NE(nullptr, applicationEl); + EXPECT_EQ(std::u16string(u"application"), applicationEl->name); +} + +TEST(XmlActionExecutorTest, FailsWhenUndefinedHierarchyExists) { + XmlActionExecutor executor; + executor[u"manifest"][u"application"]; + + std::unique_ptr<XmlResource> doc = test::buildXmlDom( + "<manifest><application /><activity /></manifest>"); + StdErrDiagnostics diag; + ASSERT_FALSE(executor.execute(XmlActionExecutorPolicy::Whitelist, &diag, doc.get())); +} + +} // namespace xml +} // namespace aapt diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java index 01af669e39d3..381eb1f50973 100644 --- a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java @@ -15,8 +15,11 @@ */ package android.view; +import com.android.ide.common.rendering.api.LayoutLog; +import com.android.layoutlib.bridge.Bridge; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; +import java.lang.reflect.Field; import java.util.concurrent.atomic.AtomicReference; /** @@ -64,4 +67,18 @@ public class Choreographer_Delegate { thisChoreographer.doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); } + + public static void dispose() { + try { + Field threadInstanceField = Choreographer.class.getDeclaredField("sThreadInstance"); + threadInstanceField.setAccessible(true); + @SuppressWarnings("unchecked") ThreadLocal<Choreographer> threadInstance = + (ThreadLocal<Choreographer>) threadInstanceField.get(null); + threadInstance.remove(); + } catch (ReflectiveOperationException e) { + assert false; + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Unable to clear Choreographer memory.", e, null); + } + } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index ce7104ee6f9b..866b2480b828 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -1453,6 +1453,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> { if (createdLooper) { Bridge.cleanupThread(); + Choreographer_Delegate.dispose(); } } } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 1c7a308746b0..6ca4393a232a 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -149,9 +149,6 @@ interface IWifiManager void setAllowScansWithTraffic(int enabled); int getAllowScansWithTraffic(); - void setHalBasedAutojoinOffload(int enabled); - int getHalBasedAutojoinOffload(); - boolean enableAutoJoinWhenAssociated(boolean enabled); boolean getEnableAutoJoinWhenAssociated(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 8c1fbc3a6def..6653a8dd6e07 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -28,7 +28,6 @@ import android.net.NetworkRequest; import android.os.Binder; import android.os.Build; import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -43,7 +42,6 @@ import com.android.internal.util.Protocol; import com.android.server.net.NetworkPinner; import java.net.InetAddress; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -2721,27 +2719,4 @@ public class WifiManager { throw e.rethrowFromSystemServer(); } } - /** - * Set setting for enabling autojoin Offload thru Wifi HAL layer - * @hide - */ - public void setHalBasedAutojoinOffload(int enabled) { - try { - mService.setHalBasedAutojoinOffload(enabled); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Get setting for enabling autojoin Offload thru Wifi HAL layer - * @hide - */ - public int getHalBasedAutojoinOffload() { - try { - return mService.getHalBasedAutojoinOffload(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } } |