Merge "AccountManager: make account session APIs SystemApi."
diff --git a/Android.mk b/Android.mk
index c1c74ea..c5917df 100644
--- a/Android.mk
+++ b/Android.mk
@@ -341,10 +341,12 @@
media/java/android/media/IAudioRoutesObserver.aidl \
media/java/android/media/IMediaHTTPConnection.aidl \
media/java/android/media/IMediaHTTPService.aidl \
+ media/java/android/media/IMediaResourceMonitor.aidl \
media/java/android/media/IMediaRouterClient.aidl \
media/java/android/media/IMediaRouterService.aidl \
media/java/android/media/IMediaScannerListener.aidl \
media/java/android/media/IMediaScannerService.aidl \
+ media/java/android/media/IRecordingConfigDispatcher.aidl \
media/java/android/media/IRemoteDisplayCallback.aidl \
media/java/android/media/IRemoteDisplayProvider.aidl \
media/java/android/media/IRemoteVolumeController.aidl \
diff --git a/api/current.txt b/api/current.txt
index ce4cd6c3..1d251ec 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -334,6 +334,7 @@
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844040; // 0x1010508
+ field public static final int canPerformGestures = 16844046; // 0x101050e
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -2610,6 +2611,7 @@
public abstract class AccessibilityService extends android.app.Service {
ctor public AccessibilityService();
+ method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2649,6 +2651,12 @@
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
}
+ public static abstract class AccessibilityService.GestureResultCallback {
+ ctor public AccessibilityService.GestureResultCallback();
+ method public void onCancelled(android.accessibilityservice.GestureDescription);
+ method public void onCompleted(android.accessibilityservice.GestureDescription);
+ }
+
public static final class AccessibilityService.MagnificationController {
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener);
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener, android.os.Handler);
@@ -2681,6 +2689,7 @@
method public java.lang.String loadDescription(android.content.pm.PackageManager);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
+ field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
field public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 8; // 0x8
field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
@@ -2707,6 +2716,30 @@
field public java.lang.String[] packageNames;
}
+ public final class GestureDescription {
+ method public static android.accessibilityservice.GestureDescription createClick(int, int);
+ method public static android.accessibilityservice.GestureDescription createLongClick(int, int);
+ method public static android.accessibilityservice.GestureDescription createPinch(int, int, int, int, float, long);
+ method public static android.accessibilityservice.GestureDescription createSwipe(int, int, int, int, long);
+ method public android.accessibilityservice.GestureDescription.StrokeDescription getStroke(int);
+ method public int getStrokeCount();
+ field public static final long MAX_GESTURE_DURATION_MS = 60000L; // 0xea60L
+ field public static final int MAX_STROKE_COUNT = 10; // 0xa
+ }
+
+ public static class GestureDescription.Builder {
+ ctor public GestureDescription.Builder();
+ method public android.accessibilityservice.GestureDescription.Builder addStroke(android.accessibilityservice.GestureDescription.StrokeDescription);
+ method public android.accessibilityservice.GestureDescription build();
+ }
+
+ public static class GestureDescription.StrokeDescription {
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ method public long getDuration();
+ method public android.graphics.Path getPath();
+ method public long getStartTime();
+ }
+
}
package android.accounts {
@@ -3464,6 +3497,7 @@
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public void onProvideAssistContent(android.app.assist.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public android.net.Uri onProvideReferrer();
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method protected void onRestart();
@@ -4148,6 +4182,7 @@
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public void onRestoreInstanceState(android.os.Bundle);
method public android.os.Bundle onSaveInstanceState();
method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5752,6 +5787,7 @@
method public boolean getCameraDisabled(android.content.ComponentName);
method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
+ method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
method public int getCurrentFailedPasswordAttempts();
method public java.lang.String getDeviceOwnerLockScreenInfo();
@@ -5816,6 +5852,7 @@
method public void setCameraDisabled(android.content.ComponentName, boolean);
method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
+ method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -6125,6 +6162,7 @@
method public int describeContents();
method public int getBackoffPolicy();
method public android.os.PersistableBundle getExtras();
+ method public long getFlexMillis();
method public int getId();
method public long getInitialBackoffMillis();
method public long getIntervalMillis();
@@ -6142,6 +6180,8 @@
field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
+ field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
+ field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6155,6 +6195,7 @@
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
method public android.app.job.JobInfo.Builder setPeriodic(long);
+ method public android.app.job.JobInfo.Builder setPeriodic(long, long);
method public android.app.job.JobInfo.Builder setPersisted(boolean);
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
@@ -6215,6 +6256,8 @@
public static class NetworkStats.Bucket {
ctor public NetworkStats.Bucket();
method public long getEndTimeStamp();
+ method public int getMetering();
+ method public int getRoaming();
method public long getRxBytes();
method public long getRxPackets();
method public long getStartTimeStamp();
@@ -6222,6 +6265,12 @@
method public long getTxBytes();
method public long getTxPackets();
method public int getUid();
+ field public static final int METERING_ALL = -1; // 0xffffffff
+ field public static final int METERING_DEFAULT = 1; // 0x1
+ field public static final int METERING_METERED = 2; // 0x2
+ field public static final int ROAMING_ALL = -1; // 0xffffffff
+ field public static final int ROAMING_DEFAULT = 1; // 0x1
+ field public static final int ROAMING_ROAMING = 2; // 0x2
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
@@ -9435,8 +9484,6 @@
method public abstract int getComponentEnabledSetting(android.content.ComponentName);
method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
- method public abstract byte[] getEphemeralCookie();
- method public abstract int getEphemeralCookieMaxSizeBytes();
method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public abstract java.lang.String getInstallerPackageName(java.lang.String);
@@ -9470,7 +9517,6 @@
method public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract boolean hasSystemFeature(java.lang.String);
- method public abstract boolean isEphemeralApplication();
method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public abstract boolean isSafeMode();
method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -9488,7 +9534,6 @@
method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
method public abstract void setApplicationEnabledSetting(java.lang.String, int, int);
method public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int);
- method public abstract boolean setEphemeralCookie(byte[]);
method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
method public abstract void verifyPendingInstall(int, int);
field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
@@ -12735,6 +12780,7 @@
method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
field public static final int PADDING_MODE_NEST = 0; // 0x0
field public static final int PADDING_MODE_STACK = 1; // 0x1
+ field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
}
public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -20319,8 +20365,6 @@
field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
- field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
- field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc";
field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
@@ -22530,7 +22574,16 @@
public class MtpEvent {
ctor public MtpEvent();
+ method public int getDevicePropCode();
method public int getEventCode();
+ method public int getObjectFormatCode();
+ method public int getObjectHandle();
+ method public int getObjectPropCode();
+ method public int getParameter1();
+ method public int getParameter2();
+ method public int getParameter3();
+ method public int getStorageId();
+ method public int getTransactionId();
}
public final class MtpObjectInfo {
@@ -27181,7 +27234,7 @@
ctor public GLException(int, java.lang.String);
}
- public class GLSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback {
+ public class GLSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback2 {
ctor public GLSurfaceView(android.content.Context);
ctor public GLSurfaceView(android.content.Context, android.util.AttributeSet);
method public int getDebugFlags();
@@ -27205,6 +27258,7 @@
method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
method public void surfaceCreated(android.view.SurfaceHolder);
method public void surfaceDestroyed(android.view.SurfaceHolder);
+ method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
@@ -31319,6 +31373,7 @@
field public static final java.lang.String AUTO_TIME = "auto_time";
field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+ field public static final java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_ROAMING = "data_roaming";
field public static final java.lang.String DEBUG_APP = "debug_app";
@@ -33441,6 +33496,7 @@
method public boolean onMenuOpened(int, android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public boolean onSearchRequested(android.view.SearchEvent);
method public boolean onSearchRequested();
method public void onWakeUp();
@@ -33561,6 +33617,7 @@
field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_TOPIC_BANNED = 14; // 0xe
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -33661,17 +33718,24 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getLabel();
+ method public int getState();
method public void setContentDescription(java.lang.CharSequence);
method public void setIcon(android.graphics.drawable.Icon);
method public void setLabel(java.lang.CharSequence);
+ method public void setState(int);
method public void updateTile();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.quicksettings.Tile> CREATOR;
+ field public static final int STATE_ACTIVE = 2; // 0x2
+ field public static final int STATE_INACTIVE = 1; // 0x1
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
public class TileService extends android.app.Service {
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
+ method public final boolean isLocked();
+ method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
method public void onStartListening();
@@ -33680,6 +33744,8 @@
method public void onTileRemoved();
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void showDialog(android.app.Dialog);
+ method public final void startActivityAndCollapse(android.content.Intent);
+ method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
@@ -36785,8 +36851,6 @@
method public int getComponentEnabledSetting(android.content.ComponentName);
method public android.graphics.drawable.Drawable getDefaultActivityIcon();
method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
- method public byte[] getEphemeralCookie();
- method public int getEphemeralCookieMaxSizeBytes();
method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public java.lang.String getInstallerPackageName(java.lang.String);
@@ -36819,7 +36883,6 @@
method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public boolean hasSystemFeature(java.lang.String);
- method public boolean isEphemeralApplication();
method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public boolean isSafeMode();
method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -36837,7 +36900,6 @@
method public android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
method public void setApplicationEnabledSetting(java.lang.String, int, int);
method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
- method public boolean setEphemeralCookie(byte[]);
method public void setInstallerPackageName(java.lang.String, java.lang.String);
method public void verifyPendingInstall(int, int);
}
@@ -39068,7 +39130,9 @@
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
method public java.util.Locale getPrimary();
+ method public int indexOf(java.util.Locale);
method public boolean isEmpty();
+ method public static void setDefault(android.util.LocaleList);
method public int size();
method public java.lang.String toLanguageTags();
method public void writeToParcel(android.os.Parcel, int);
@@ -40330,6 +40394,27 @@
method public void startTracking(android.view.KeyEvent, java.lang.Object);
}
+ public final class KeyboardShortcutGroup implements android.os.Parcelable {
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence, java.util.List<android.view.KeyboardShortcutInfo>);
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence);
+ method public void addItem(android.view.KeyboardShortcutInfo);
+ method public int describeContents();
+ method public java.util.List<android.view.KeyboardShortcutInfo> getItems();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutGroup> CREATOR;
+ }
+
+ public final class KeyboardShortcutInfo implements android.os.Parcelable {
+ ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int);
+ method public int describeContents();
+ method public char getBaseCharacter();
+ method public java.lang.CharSequence getLabel();
+ method public int getModifiers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutInfo> CREATOR;
+ }
+
public abstract class LayoutInflater {
ctor protected LayoutInflater(android.content.Context);
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
@@ -42331,6 +42416,7 @@
method public abstract boolean onMenuOpened(int, android.view.Menu);
method public abstract void onPanelClosed(int, android.view.Menu);
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract boolean onSearchRequested(android.view.SearchEvent);
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -49492,6 +49578,8 @@
public class InternalError extends java.lang.VirtualMachineError {
ctor public InternalError();
ctor public InternalError(java.lang.String);
+ ctor public InternalError(java.lang.String, java.lang.Throwable);
+ ctor public InternalError(java.lang.Throwable);
}
public class InterruptedException extends java.lang.Exception {
@@ -50264,6 +50352,8 @@
public abstract class VirtualMachineError extends java.lang.Error {
ctor public VirtualMachineError();
ctor public VirtualMachineError(java.lang.String);
+ ctor public VirtualMachineError(java.lang.String, java.lang.Throwable);
+ ctor public VirtualMachineError(java.lang.Throwable);
}
public final class Void {
@@ -54006,6 +54096,7 @@
method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
method public final java.security.Provider getProvider();
+ method public final java.security.cert.CertPathChecker getRevocationChecker();
}
public class CertPathBuilderException extends java.security.GeneralSecurityException {
@@ -54023,6 +54114,13 @@
public abstract class CertPathBuilderSpi {
ctor public CertPathBuilderSpi();
method public abstract java.security.cert.CertPathBuilderResult engineBuild(java.security.cert.CertPathParameters) throws java.security.cert.CertPathBuilderException, java.security.InvalidAlgorithmParameterException;
+ method public java.security.cert.CertPathChecker engineGetRevocationChecker();
+ }
+
+ public abstract interface CertPathChecker {
+ method public abstract void check(java.security.cert.Certificate) throws java.security.cert.CertPathValidatorException;
+ method public abstract void init(boolean) throws java.security.cert.CertPathValidatorException;
+ method public abstract boolean isForwardCheckingSupported();
}
public abstract interface CertPathParameters implements java.lang.Cloneable {
@@ -54037,6 +54135,7 @@
method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
method public final java.security.Provider getProvider();
+ method public final java.security.cert.CertPathChecker getRevocationChecker();
method public final java.security.cert.CertPathValidatorResult validate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
}
@@ -54073,6 +54172,7 @@
public abstract class CertPathValidatorSpi {
ctor public CertPathValidatorSpi();
+ method public java.security.cert.CertPathChecker engineGetRevocationChecker();
method public abstract java.security.cert.CertPathValidatorResult engineValidate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
}
@@ -54231,9 +54331,10 @@
method public java.security.cert.CertPath getCertPath();
}
- public abstract class PKIXCertPathChecker implements java.lang.Cloneable {
+ public abstract class PKIXCertPathChecker implements java.security.cert.CertPathChecker java.lang.Cloneable {
ctor protected PKIXCertPathChecker();
method public abstract void check(java.security.cert.Certificate, java.util.Collection<java.lang.String>) throws java.security.cert.CertPathValidatorException;
+ method public void check(java.security.cert.Certificate) throws java.security.cert.CertPathValidatorException;
method public java.lang.Object clone();
method public abstract java.util.Set<java.lang.String> getSupportedExtensions();
method public abstract void init(boolean) throws java.security.cert.CertPathValidatorException;
@@ -54293,6 +54394,30 @@
enum_constant public static final java.security.cert.PKIXReason UNRECOGNIZED_CRIT_EXT;
}
+ public abstract class PKIXRevocationChecker extends java.security.cert.PKIXCertPathChecker {
+ ctor protected PKIXRevocationChecker();
+ method public java.util.List<java.security.cert.Extension> getOcspExtensions();
+ method public java.net.URI getOcspResponder();
+ method public java.security.cert.X509Certificate getOcspResponderCert();
+ method public java.util.Map<java.security.cert.X509Certificate, byte[]> getOcspResponses();
+ method public java.util.Set<java.security.cert.PKIXRevocationChecker.Option> getOptions();
+ method public abstract java.util.List<java.security.cert.CertPathValidatorException> getSoftFailExceptions();
+ method public void setOcspExtensions(java.util.List<java.security.cert.Extension>);
+ method public void setOcspResponder(java.net.URI);
+ method public void setOcspResponderCert(java.security.cert.X509Certificate);
+ method public void setOcspResponses(java.util.Map<java.security.cert.X509Certificate, byte[]>);
+ method public void setOptions(java.util.Set<java.security.cert.PKIXRevocationChecker.Option>);
+ }
+
+ public static final class PKIXRevocationChecker.Option extends java.lang.Enum {
+ method public static java.security.cert.PKIXRevocationChecker.Option valueOf(java.lang.String);
+ method public static final java.security.cert.PKIXRevocationChecker.Option[] values();
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option NO_FALLBACK;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option ONLY_END_ENTITY;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option PREFER_CRLS;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option SOFT_FAIL;
+ }
+
public abstract interface PolicyNode {
method public abstract java.util.Iterator<? extends java.security.cert.PolicyNode> getChildren();
method public abstract int getDepth();
@@ -54452,6 +54577,7 @@
method public javax.security.auth.x500.X500Principal getSubjectX500Principal();
method public abstract byte[] getTBSCertificate() throws java.security.cert.CertificateEncodingException;
method public abstract int getVersion();
+ method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
}
public abstract interface X509Extension {
diff --git a/api/system-current.txt b/api/system-current.txt
index 3ede80a..d1421e5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -214,6 +214,7 @@
field public static final java.lang.String STATUS_BAR = "android.permission.STATUS_BAR";
field public static final java.lang.String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final java.lang.String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
+ field public static final java.lang.String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
field public static final java.lang.String TV_INPUT_HARDWARE = "android.permission.TV_INPUT_HARDWARE";
field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
@@ -428,6 +429,7 @@
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844040; // 0x1010508
+ field public static final int canPerformGestures = 16844046; // 0x101050e
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -2711,6 +2713,7 @@
public abstract class AccessibilityService extends android.app.Service {
ctor public AccessibilityService();
+ method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2750,6 +2753,12 @@
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
}
+ public static abstract class AccessibilityService.GestureResultCallback {
+ ctor public AccessibilityService.GestureResultCallback();
+ method public void onCancelled(android.accessibilityservice.GestureDescription);
+ method public void onCompleted(android.accessibilityservice.GestureDescription);
+ }
+
public static final class AccessibilityService.MagnificationController {
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener);
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener, android.os.Handler);
@@ -2782,6 +2791,7 @@
method public java.lang.String loadDescription(android.content.pm.PackageManager);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
+ field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
field public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 8; // 0x8
field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
@@ -2808,6 +2818,30 @@
field public java.lang.String[] packageNames;
}
+ public final class GestureDescription {
+ method public static android.accessibilityservice.GestureDescription createClick(int, int);
+ method public static android.accessibilityservice.GestureDescription createLongClick(int, int);
+ method public static android.accessibilityservice.GestureDescription createPinch(int, int, int, int, float, long);
+ method public static android.accessibilityservice.GestureDescription createSwipe(int, int, int, int, long);
+ method public android.accessibilityservice.GestureDescription.StrokeDescription getStroke(int);
+ method public int getStrokeCount();
+ field public static final long MAX_GESTURE_DURATION_MS = 60000L; // 0xea60L
+ field public static final int MAX_STROKE_COUNT = 10; // 0xa
+ }
+
+ public static class GestureDescription.Builder {
+ ctor public GestureDescription.Builder();
+ method public android.accessibilityservice.GestureDescription.Builder addStroke(android.accessibilityservice.GestureDescription.StrokeDescription);
+ method public android.accessibilityservice.GestureDescription build();
+ }
+
+ public static class GestureDescription.StrokeDescription {
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ method public long getDuration();
+ method public android.graphics.Path getPath();
+ method public long getStartTime();
+ }
+
}
package android.accounts {
@@ -3577,6 +3611,7 @@
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public void onProvideAssistContent(android.app.assist.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public android.net.Uri onProvideReferrer();
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method protected void onRestart();
@@ -4276,6 +4311,7 @@
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public void onRestoreInstanceState(android.os.Bundle);
method public android.os.Bundle onSaveInstanceState();
method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5885,6 +5921,7 @@
method public boolean getCameraDisabled(android.content.ComponentName);
method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
+ method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
method public int getCurrentFailedPasswordAttempts();
method public deprecated java.lang.String getDeviceInitializerApp();
@@ -5958,6 +5995,7 @@
method public void setCameraDisabled(android.content.ComponentName, boolean);
method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
+ method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -6347,6 +6385,7 @@
method public int describeContents();
method public int getBackoffPolicy();
method public android.os.PersistableBundle getExtras();
+ method public long getFlexMillis();
method public int getId();
method public long getInitialBackoffMillis();
method public long getIntervalMillis();
@@ -6364,6 +6403,8 @@
field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
+ field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
+ field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6377,6 +6418,7 @@
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
method public android.app.job.JobInfo.Builder setPeriodic(long);
+ method public android.app.job.JobInfo.Builder setPeriodic(long, long);
method public android.app.job.JobInfo.Builder setPersisted(boolean);
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
@@ -6437,6 +6479,8 @@
public static class NetworkStats.Bucket {
ctor public NetworkStats.Bucket();
method public long getEndTimeStamp();
+ method public int getMetering();
+ method public int getRoaming();
method public long getRxBytes();
method public long getRxPackets();
method public long getStartTimeStamp();
@@ -6444,6 +6488,12 @@
method public long getTxBytes();
method public long getTxPackets();
method public int getUid();
+ field public static final int METERING_ALL = -1; // 0xffffffff
+ field public static final int METERING_DEFAULT = 1; // 0x1
+ field public static final int METERING_METERED = 2; // 0x2
+ field public static final int ROAMING_ALL = -1; // 0xffffffff
+ field public static final int ROAMING_DEFAULT = 1; // 0x1
+ field public static final int ROAMING_ROAMING = 2; // 0x2
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
@@ -9744,8 +9794,6 @@
method public abstract int getComponentEnabledSetting(android.content.ComponentName);
method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
- method public abstract byte[] getEphemeralCookie();
- method public abstract int getEphemeralCookieMaxSizeBytes();
method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public abstract java.lang.String getInstallerPackageName(java.lang.String);
@@ -9781,7 +9829,6 @@
method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
method public abstract boolean hasSystemFeature(java.lang.String);
- method public abstract boolean isEphemeralApplication();
method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public abstract boolean isSafeMode();
method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -9801,7 +9848,6 @@
method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
method public abstract void setApplicationEnabledSetting(java.lang.String, int, int);
method public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int);
- method public abstract boolean setEphemeralCookie(byte[]);
method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
method public abstract void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle);
method public abstract void verifyIntentFilter(int, int, java.util.List<java.lang.String>);
@@ -13097,6 +13143,7 @@
method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
field public static final int PADDING_MODE_NEST = 0; // 0x0
field public static final int PADDING_MODE_STACK = 1; // 0x1
+ field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
}
public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -21625,8 +21672,6 @@
field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
- field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
- field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc";
field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
@@ -24084,7 +24129,16 @@
public class MtpEvent {
ctor public MtpEvent();
+ method public int getDevicePropCode();
method public int getEventCode();
+ method public int getObjectFormatCode();
+ method public int getObjectHandle();
+ method public int getObjectPropCode();
+ method public int getParameter1();
+ method public int getParameter2();
+ method public int getParameter3();
+ method public int getStorageId();
+ method public int getTransactionId();
}
public final class MtpObjectInfo {
@@ -24165,6 +24219,7 @@
method public android.net.Network[] getAllNetworks();
method public deprecated boolean getBackgroundDataSetting();
method public android.net.Network getBoundNetworkForProcess();
+ method public java.lang.String getCaptivePortalServerUrl();
method public android.net.ProxyInfo getDefaultProxy();
method public android.net.LinkProperties getLinkProperties(android.net.Network);
method public android.net.NetworkCapabilities getNetworkCapabilities(android.net.Network);
@@ -29179,7 +29234,7 @@
ctor public GLException(int, java.lang.String);
}
- public class GLSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback {
+ public class GLSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback2 {
ctor public GLSurfaceView(android.content.Context);
ctor public GLSurfaceView(android.content.Context, android.util.AttributeSet);
method public int getDebugFlags();
@@ -29203,6 +29258,7 @@
method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
method public void surfaceCreated(android.view.SurfaceHolder);
method public void surfaceDestroyed(android.view.SurfaceHolder);
+ method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
@@ -33462,6 +33518,7 @@
field public static final java.lang.String AUTO_TIME = "auto_time";
field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+ field public static final java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_ROAMING = "data_roaming";
field public static final java.lang.String DEBUG_APP = "debug_app";
@@ -35585,6 +35642,7 @@
method public boolean onMenuOpened(int, android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public boolean onSearchRequested(android.view.SearchEvent);
method public boolean onSearchRequested();
method public void onWakeUp();
@@ -35705,6 +35763,7 @@
field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_TOPIC_BANNED = 14; // 0xe
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -35837,17 +35896,24 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getLabel();
+ method public int getState();
method public void setContentDescription(java.lang.CharSequence);
method public void setIcon(android.graphics.drawable.Icon);
method public void setLabel(java.lang.CharSequence);
+ method public void setState(int);
method public void updateTile();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.quicksettings.Tile> CREATOR;
+ field public static final int STATE_ACTIVE = 2; // 0x2
+ field public static final int STATE_INACTIVE = 1; // 0x1
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
public class TileService extends android.app.Service {
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
+ method public final boolean isLocked();
+ method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
method public void onStartListening();
@@ -35857,6 +35923,8 @@
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void setStatusIcon(android.graphics.drawable.Icon, java.lang.String);
method public final void showDialog(android.app.Dialog);
+ method public final void startActivityAndCollapse(android.content.Intent);
+ method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
@@ -37868,6 +37936,7 @@
field public static final java.lang.String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
+ field public static final java.lang.String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
@@ -39135,8 +39204,6 @@
method public int getComponentEnabledSetting(android.content.ComponentName);
method public android.graphics.drawable.Drawable getDefaultActivityIcon();
method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
- method public byte[] getEphemeralCookie();
- method public int getEphemeralCookieMaxSizeBytes();
method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public java.lang.String getInstallerPackageName(java.lang.String);
@@ -39171,7 +39238,6 @@
method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
method public boolean hasSystemFeature(java.lang.String);
- method public boolean isEphemeralApplication();
method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public boolean isSafeMode();
method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -39191,7 +39257,6 @@
method public void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
method public void setApplicationEnabledSetting(java.lang.String, int, int);
method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
- method public boolean setEphemeralCookie(byte[]);
method public void setInstallerPackageName(java.lang.String, java.lang.String);
method public void updatePermissionFlags(java.lang.String, java.lang.String, int, int, android.os.UserHandle);
method public void verifyIntentFilter(int, int, java.util.List<java.lang.String>);
@@ -41424,7 +41489,9 @@
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
method public java.util.Locale getPrimary();
+ method public int indexOf(java.util.Locale);
method public boolean isEmpty();
+ method public static void setDefault(android.util.LocaleList);
method public int size();
method public java.lang.String toLanguageTags();
method public void writeToParcel(android.os.Parcel, int);
@@ -42686,6 +42753,27 @@
method public void startTracking(android.view.KeyEvent, java.lang.Object);
}
+ public final class KeyboardShortcutGroup implements android.os.Parcelable {
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence, java.util.List<android.view.KeyboardShortcutInfo>);
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence);
+ method public void addItem(android.view.KeyboardShortcutInfo);
+ method public int describeContents();
+ method public java.util.List<android.view.KeyboardShortcutInfo> getItems();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutGroup> CREATOR;
+ }
+
+ public final class KeyboardShortcutInfo implements android.os.Parcelable {
+ ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int);
+ method public int describeContents();
+ method public char getBaseCharacter();
+ method public java.lang.CharSequence getLabel();
+ method public int getModifiers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutInfo> CREATOR;
+ }
+
public abstract class LayoutInflater {
ctor protected LayoutInflater(android.content.Context);
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
@@ -44688,6 +44776,7 @@
method public abstract boolean onMenuOpened(int, android.view.Menu);
method public abstract void onPanelClosed(int, android.view.Menu);
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract boolean onSearchRequested(android.view.SearchEvent);
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -52164,6 +52253,8 @@
public class InternalError extends java.lang.VirtualMachineError {
ctor public InternalError();
ctor public InternalError(java.lang.String);
+ ctor public InternalError(java.lang.String, java.lang.Throwable);
+ ctor public InternalError(java.lang.Throwable);
}
public class InterruptedException extends java.lang.Exception {
@@ -52936,6 +53027,8 @@
public abstract class VirtualMachineError extends java.lang.Error {
ctor public VirtualMachineError();
ctor public VirtualMachineError(java.lang.String);
+ ctor public VirtualMachineError(java.lang.String, java.lang.Throwable);
+ ctor public VirtualMachineError(java.lang.Throwable);
}
public final class Void {
@@ -56678,6 +56771,7 @@
method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
method public final java.security.Provider getProvider();
+ method public final java.security.cert.CertPathChecker getRevocationChecker();
}
public class CertPathBuilderException extends java.security.GeneralSecurityException {
@@ -56695,6 +56789,13 @@
public abstract class CertPathBuilderSpi {
ctor public CertPathBuilderSpi();
method public abstract java.security.cert.CertPathBuilderResult engineBuild(java.security.cert.CertPathParameters) throws java.security.cert.CertPathBuilderException, java.security.InvalidAlgorithmParameterException;
+ method public java.security.cert.CertPathChecker engineGetRevocationChecker();
+ }
+
+ public abstract interface CertPathChecker {
+ method public abstract void check(java.security.cert.Certificate) throws java.security.cert.CertPathValidatorException;
+ method public abstract void init(boolean) throws java.security.cert.CertPathValidatorException;
+ method public abstract boolean isForwardCheckingSupported();
}
public abstract interface CertPathParameters implements java.lang.Cloneable {
@@ -56709,6 +56810,7 @@
method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
method public final java.security.Provider getProvider();
+ method public final java.security.cert.CertPathChecker getRevocationChecker();
method public final java.security.cert.CertPathValidatorResult validate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
}
@@ -56745,6 +56847,7 @@
public abstract class CertPathValidatorSpi {
ctor public CertPathValidatorSpi();
+ method public java.security.cert.CertPathChecker engineGetRevocationChecker();
method public abstract java.security.cert.CertPathValidatorResult engineValidate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
}
@@ -56903,9 +57006,10 @@
method public java.security.cert.CertPath getCertPath();
}
- public abstract class PKIXCertPathChecker implements java.lang.Cloneable {
+ public abstract class PKIXCertPathChecker implements java.security.cert.CertPathChecker java.lang.Cloneable {
ctor protected PKIXCertPathChecker();
method public abstract void check(java.security.cert.Certificate, java.util.Collection<java.lang.String>) throws java.security.cert.CertPathValidatorException;
+ method public void check(java.security.cert.Certificate) throws java.security.cert.CertPathValidatorException;
method public java.lang.Object clone();
method public abstract java.util.Set<java.lang.String> getSupportedExtensions();
method public abstract void init(boolean) throws java.security.cert.CertPathValidatorException;
@@ -56965,6 +57069,30 @@
enum_constant public static final java.security.cert.PKIXReason UNRECOGNIZED_CRIT_EXT;
}
+ public abstract class PKIXRevocationChecker extends java.security.cert.PKIXCertPathChecker {
+ ctor protected PKIXRevocationChecker();
+ method public java.util.List<java.security.cert.Extension> getOcspExtensions();
+ method public java.net.URI getOcspResponder();
+ method public java.security.cert.X509Certificate getOcspResponderCert();
+ method public java.util.Map<java.security.cert.X509Certificate, byte[]> getOcspResponses();
+ method public java.util.Set<java.security.cert.PKIXRevocationChecker.Option> getOptions();
+ method public abstract java.util.List<java.security.cert.CertPathValidatorException> getSoftFailExceptions();
+ method public void setOcspExtensions(java.util.List<java.security.cert.Extension>);
+ method public void setOcspResponder(java.net.URI);
+ method public void setOcspResponderCert(java.security.cert.X509Certificate);
+ method public void setOcspResponses(java.util.Map<java.security.cert.X509Certificate, byte[]>);
+ method public void setOptions(java.util.Set<java.security.cert.PKIXRevocationChecker.Option>);
+ }
+
+ public static final class PKIXRevocationChecker.Option extends java.lang.Enum {
+ method public static java.security.cert.PKIXRevocationChecker.Option valueOf(java.lang.String);
+ method public static final java.security.cert.PKIXRevocationChecker.Option[] values();
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option NO_FALLBACK;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option ONLY_END_ENTITY;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option PREFER_CRLS;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option SOFT_FAIL;
+ }
+
public abstract interface PolicyNode {
method public abstract java.util.Iterator<? extends java.security.cert.PolicyNode> getChildren();
method public abstract int getDepth();
@@ -57124,6 +57252,7 @@
method public javax.security.auth.x500.X500Principal getSubjectX500Principal();
method public abstract byte[] getTBSCertificate() throws java.security.cert.CertificateEncodingException;
method public abstract int getVersion();
+ method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
}
public abstract interface X509Extension {
diff --git a/api/test-current.txt b/api/test-current.txt
index a159bfa..91dcf34 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -334,6 +334,7 @@
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844040; // 0x1010508
+ field public static final int canPerformGestures = 16844046; // 0x101050e
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
@@ -2610,6 +2611,7 @@
public abstract class AccessibilityService extends android.app.Service {
ctor public AccessibilityService();
+ method public final boolean dispatchGesture(android.accessibilityservice.GestureDescription, android.accessibilityservice.AccessibilityService.GestureResultCallback, android.os.Handler);
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
@@ -2649,6 +2651,12 @@
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
}
+ public static abstract class AccessibilityService.GestureResultCallback {
+ ctor public AccessibilityService.GestureResultCallback();
+ method public void onCancelled(android.accessibilityservice.GestureDescription);
+ method public void onCompleted(android.accessibilityservice.GestureDescription);
+ }
+
public static final class AccessibilityService.MagnificationController {
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener);
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener, android.os.Handler);
@@ -2681,6 +2689,7 @@
method public java.lang.String loadDescription(android.content.pm.PackageManager);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
+ field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
field public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 8; // 0x8
field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
@@ -2707,6 +2716,30 @@
field public java.lang.String[] packageNames;
}
+ public final class GestureDescription {
+ method public static android.accessibilityservice.GestureDescription createClick(int, int);
+ method public static android.accessibilityservice.GestureDescription createLongClick(int, int);
+ method public static android.accessibilityservice.GestureDescription createPinch(int, int, int, int, float, long);
+ method public static android.accessibilityservice.GestureDescription createSwipe(int, int, int, int, long);
+ method public android.accessibilityservice.GestureDescription.StrokeDescription getStroke(int);
+ method public int getStrokeCount();
+ field public static final long MAX_GESTURE_DURATION_MS = 60000L; // 0xea60L
+ field public static final int MAX_STROKE_COUNT = 10; // 0xa
+ }
+
+ public static class GestureDescription.Builder {
+ ctor public GestureDescription.Builder();
+ method public android.accessibilityservice.GestureDescription.Builder addStroke(android.accessibilityservice.GestureDescription.StrokeDescription);
+ method public android.accessibilityservice.GestureDescription build();
+ }
+
+ public static class GestureDescription.StrokeDescription {
+ ctor public GestureDescription.StrokeDescription(android.graphics.Path, long, long);
+ method public long getDuration();
+ method public android.graphics.Path getPath();
+ method public long getStartTime();
+ }
+
}
package android.accounts {
@@ -3464,6 +3497,7 @@
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public void onProvideAssistContent(android.app.assist.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public android.net.Uri onProvideReferrer();
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method protected void onRestart();
@@ -4148,6 +4182,7 @@
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public void onRestoreInstanceState(android.os.Bundle);
method public android.os.Bundle onSaveInstanceState();
method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5754,6 +5789,7 @@
method public boolean getCameraDisabled(android.content.ComponentName);
method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
+ method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
method public int getCurrentFailedPasswordAttempts();
method public java.lang.String getDeviceOwnerLockScreenInfo();
@@ -5818,6 +5854,7 @@
method public void setCameraDisabled(android.content.ComponentName, boolean);
method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
+ method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -6127,6 +6164,7 @@
method public int describeContents();
method public int getBackoffPolicy();
method public android.os.PersistableBundle getExtras();
+ method public long getFlexMillis();
method public int getId();
method public long getInitialBackoffMillis();
method public long getIntervalMillis();
@@ -6144,6 +6182,8 @@
field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR;
field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
+ field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L
+ field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6157,6 +6197,7 @@
method public android.app.job.JobInfo.Builder setMinimumLatency(long);
method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
method public android.app.job.JobInfo.Builder setPeriodic(long);
+ method public android.app.job.JobInfo.Builder setPeriodic(long, long);
method public android.app.job.JobInfo.Builder setPersisted(boolean);
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
@@ -6217,6 +6258,8 @@
public static class NetworkStats.Bucket {
ctor public NetworkStats.Bucket();
method public long getEndTimeStamp();
+ method public int getMetering();
+ method public int getRoaming();
method public long getRxBytes();
method public long getRxPackets();
method public long getStartTimeStamp();
@@ -6224,6 +6267,12 @@
method public long getTxBytes();
method public long getTxPackets();
method public int getUid();
+ field public static final int METERING_ALL = -1; // 0xffffffff
+ field public static final int METERING_DEFAULT = 1; // 0x1
+ field public static final int METERING_METERED = 2; // 0x2
+ field public static final int ROAMING_ALL = -1; // 0xffffffff
+ field public static final int ROAMING_DEFAULT = 1; // 0x1
+ field public static final int ROAMING_ROAMING = 2; // 0x2
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
@@ -9443,8 +9492,6 @@
method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
- method public abstract byte[] getEphemeralCookie();
- method public abstract int getEphemeralCookieMaxSizeBytes();
method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public abstract java.lang.String getInstallerPackageName(java.lang.String);
@@ -9478,7 +9525,6 @@
method public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract boolean hasSystemFeature(java.lang.String);
- method public abstract boolean isEphemeralApplication();
method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public abstract boolean isSafeMode();
method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -9496,7 +9542,6 @@
method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
method public abstract void setApplicationEnabledSetting(java.lang.String, int, int);
method public abstract void setComponentEnabledSetting(android.content.ComponentName, int, int);
- method public abstract boolean setEphemeralCookie(byte[]);
method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
method public abstract void verifyPendingInstall(int, int);
field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
@@ -12743,6 +12788,7 @@
method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
field public static final int PADDING_MODE_NEST = 0; // 0x0
field public static final int PADDING_MODE_STACK = 1; // 0x1
+ field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
}
public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -20327,8 +20373,6 @@
field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
- field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
- field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc";
field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
@@ -22538,7 +22582,16 @@
public class MtpEvent {
ctor public MtpEvent();
+ method public int getDevicePropCode();
method public int getEventCode();
+ method public int getObjectFormatCode();
+ method public int getObjectHandle();
+ method public int getObjectPropCode();
+ method public int getParameter1();
+ method public int getParameter2();
+ method public int getParameter3();
+ method public int getStorageId();
+ method public int getTransactionId();
}
public final class MtpObjectInfo {
@@ -27189,7 +27242,7 @@
ctor public GLException(int, java.lang.String);
}
- public class GLSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback {
+ public class GLSurfaceView extends android.view.SurfaceView implements android.view.SurfaceHolder.Callback2 {
ctor public GLSurfaceView(android.content.Context);
ctor public GLSurfaceView(android.content.Context, android.util.AttributeSet);
method public int getDebugFlags();
@@ -27213,6 +27266,7 @@
method public void surfaceChanged(android.view.SurfaceHolder, int, int, int);
method public void surfaceCreated(android.view.SurfaceHolder);
method public void surfaceDestroyed(android.view.SurfaceHolder);
+ method public void surfaceRedrawNeeded(android.view.SurfaceHolder);
field public static final int DEBUG_CHECK_GL_ERROR = 1; // 0x1
field public static final int DEBUG_LOG_GL_CALLS = 2; // 0x2
field public static final int RENDERMODE_CONTINUOUSLY = 1; // 0x1
@@ -31331,6 +31385,7 @@
field public static final java.lang.String AUTO_TIME = "auto_time";
field public static final java.lang.String AUTO_TIME_ZONE = "auto_time_zone";
field public static final java.lang.String BLUETOOTH_ON = "bluetooth_on";
+ field public static final java.lang.String CONTACT_METADATA_SYNC = "contact_metadata_sync";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DATA_ROAMING = "data_roaming";
field public static final java.lang.String DEBUG_APP = "debug_app";
@@ -33455,6 +33510,7 @@
method public boolean onMenuOpened(int, android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public boolean onSearchRequested(android.view.SearchEvent);
method public boolean onSearchRequested();
method public void onWakeUp();
@@ -33575,6 +33631,7 @@
field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_TOPIC_BANNED = 14; // 0xe
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
}
@@ -33675,17 +33732,24 @@
method public java.lang.CharSequence getContentDescription();
method public android.graphics.drawable.Icon getIcon();
method public java.lang.CharSequence getLabel();
+ method public int getState();
method public void setContentDescription(java.lang.CharSequence);
method public void setIcon(android.graphics.drawable.Icon);
method public void setLabel(java.lang.CharSequence);
+ method public void setState(int);
method public void updateTile();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.quicksettings.Tile> CREATOR;
+ field public static final int STATE_ACTIVE = 2; // 0x2
+ field public static final int STATE_INACTIVE = 1; // 0x1
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
public class TileService extends android.app.Service {
ctor public TileService();
method public final android.service.quicksettings.Tile getQsTile();
+ method public final boolean isLocked();
+ method public final boolean isSecure();
method public android.os.IBinder onBind(android.content.Intent);
method public void onClick();
method public void onStartListening();
@@ -33694,6 +33758,8 @@
method public void onTileRemoved();
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void showDialog(android.app.Dialog);
+ method public final void startActivityAndCollapse(android.content.Intent);
+ method public final void unlockAndRun(java.lang.Runnable);
field public static final java.lang.String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
field public static final int TILE_MODE_ACTIVE = 2; // 0x2
field public static final int TILE_MODE_PASSIVE = 1; // 0x1
@@ -36801,8 +36867,6 @@
method public android.graphics.drawable.Drawable getDefaultActivityIcon();
method public java.lang.String getDefaultBrowserPackageNameAsUser(int);
method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
- method public byte[] getEphemeralCookie();
- method public int getEphemeralCookieMaxSizeBytes();
method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public java.lang.String getInstallerPackageName(java.lang.String);
@@ -36835,7 +36899,6 @@
method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public boolean hasSystemFeature(java.lang.String);
- method public boolean isEphemeralApplication();
method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
method public boolean isSafeMode();
method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -36853,7 +36916,6 @@
method public android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
method public void setApplicationEnabledSetting(java.lang.String, int, int);
method public void setComponentEnabledSetting(android.content.ComponentName, int, int);
- method public boolean setEphemeralCookie(byte[]);
method public void setInstallerPackageName(java.lang.String, java.lang.String);
method public void verifyPendingInstall(int, int);
}
@@ -39084,7 +39146,9 @@
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
method public java.util.Locale getPrimary();
+ method public int indexOf(java.util.Locale);
method public boolean isEmpty();
+ method public static void setDefault(android.util.LocaleList);
method public int size();
method public java.lang.String toLanguageTags();
method public void writeToParcel(android.os.Parcel, int);
@@ -40346,6 +40410,27 @@
method public void startTracking(android.view.KeyEvent, java.lang.Object);
}
+ public final class KeyboardShortcutGroup implements android.os.Parcelable {
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence, java.util.List<android.view.KeyboardShortcutInfo>);
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence);
+ method public void addItem(android.view.KeyboardShortcutInfo);
+ method public int describeContents();
+ method public java.util.List<android.view.KeyboardShortcutInfo> getItems();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutGroup> CREATOR;
+ }
+
+ public final class KeyboardShortcutInfo implements android.os.Parcelable {
+ ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int);
+ method public int describeContents();
+ method public char getBaseCharacter();
+ method public java.lang.CharSequence getLabel();
+ method public int getModifiers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutInfo> CREATOR;
+ }
+
public abstract class LayoutInflater {
ctor protected LayoutInflater(android.content.Context);
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
@@ -42347,6 +42432,7 @@
method public abstract boolean onMenuOpened(int, android.view.Menu);
method public abstract void onPanelClosed(int, android.view.Menu);
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract boolean onSearchRequested(android.view.SearchEvent);
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -49508,6 +49594,8 @@
public class InternalError extends java.lang.VirtualMachineError {
ctor public InternalError();
ctor public InternalError(java.lang.String);
+ ctor public InternalError(java.lang.String, java.lang.Throwable);
+ ctor public InternalError(java.lang.Throwable);
}
public class InterruptedException extends java.lang.Exception {
@@ -50280,6 +50368,8 @@
public abstract class VirtualMachineError extends java.lang.Error {
ctor public VirtualMachineError();
ctor public VirtualMachineError(java.lang.String);
+ ctor public VirtualMachineError(java.lang.String, java.lang.Throwable);
+ ctor public VirtualMachineError(java.lang.Throwable);
}
public final class Void {
@@ -54022,6 +54112,7 @@
method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
method public static java.security.cert.CertPathBuilder getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
method public final java.security.Provider getProvider();
+ method public final java.security.cert.CertPathChecker getRevocationChecker();
}
public class CertPathBuilderException extends java.security.GeneralSecurityException {
@@ -54039,6 +54130,13 @@
public abstract class CertPathBuilderSpi {
ctor public CertPathBuilderSpi();
method public abstract java.security.cert.CertPathBuilderResult engineBuild(java.security.cert.CertPathParameters) throws java.security.cert.CertPathBuilderException, java.security.InvalidAlgorithmParameterException;
+ method public java.security.cert.CertPathChecker engineGetRevocationChecker();
+ }
+
+ public abstract interface CertPathChecker {
+ method public abstract void check(java.security.cert.Certificate) throws java.security.cert.CertPathValidatorException;
+ method public abstract void init(boolean) throws java.security.cert.CertPathValidatorException;
+ method public abstract boolean isForwardCheckingSupported();
}
public abstract interface CertPathParameters implements java.lang.Cloneable {
@@ -54053,6 +54151,7 @@
method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.lang.String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
method public static java.security.cert.CertPathValidator getInstance(java.lang.String, java.security.Provider) throws java.security.NoSuchAlgorithmException;
method public final java.security.Provider getProvider();
+ method public final java.security.cert.CertPathChecker getRevocationChecker();
method public final java.security.cert.CertPathValidatorResult validate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
}
@@ -54089,6 +54188,7 @@
public abstract class CertPathValidatorSpi {
ctor public CertPathValidatorSpi();
+ method public java.security.cert.CertPathChecker engineGetRevocationChecker();
method public abstract java.security.cert.CertPathValidatorResult engineValidate(java.security.cert.CertPath, java.security.cert.CertPathParameters) throws java.security.cert.CertPathValidatorException, java.security.InvalidAlgorithmParameterException;
}
@@ -54247,9 +54347,10 @@
method public java.security.cert.CertPath getCertPath();
}
- public abstract class PKIXCertPathChecker implements java.lang.Cloneable {
+ public abstract class PKIXCertPathChecker implements java.security.cert.CertPathChecker java.lang.Cloneable {
ctor protected PKIXCertPathChecker();
method public abstract void check(java.security.cert.Certificate, java.util.Collection<java.lang.String>) throws java.security.cert.CertPathValidatorException;
+ method public void check(java.security.cert.Certificate) throws java.security.cert.CertPathValidatorException;
method public java.lang.Object clone();
method public abstract java.util.Set<java.lang.String> getSupportedExtensions();
method public abstract void init(boolean) throws java.security.cert.CertPathValidatorException;
@@ -54309,6 +54410,30 @@
enum_constant public static final java.security.cert.PKIXReason UNRECOGNIZED_CRIT_EXT;
}
+ public abstract class PKIXRevocationChecker extends java.security.cert.PKIXCertPathChecker {
+ ctor protected PKIXRevocationChecker();
+ method public java.util.List<java.security.cert.Extension> getOcspExtensions();
+ method public java.net.URI getOcspResponder();
+ method public java.security.cert.X509Certificate getOcspResponderCert();
+ method public java.util.Map<java.security.cert.X509Certificate, byte[]> getOcspResponses();
+ method public java.util.Set<java.security.cert.PKIXRevocationChecker.Option> getOptions();
+ method public abstract java.util.List<java.security.cert.CertPathValidatorException> getSoftFailExceptions();
+ method public void setOcspExtensions(java.util.List<java.security.cert.Extension>);
+ method public void setOcspResponder(java.net.URI);
+ method public void setOcspResponderCert(java.security.cert.X509Certificate);
+ method public void setOcspResponses(java.util.Map<java.security.cert.X509Certificate, byte[]>);
+ method public void setOptions(java.util.Set<java.security.cert.PKIXRevocationChecker.Option>);
+ }
+
+ public static final class PKIXRevocationChecker.Option extends java.lang.Enum {
+ method public static java.security.cert.PKIXRevocationChecker.Option valueOf(java.lang.String);
+ method public static final java.security.cert.PKIXRevocationChecker.Option[] values();
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option NO_FALLBACK;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option ONLY_END_ENTITY;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option PREFER_CRLS;
+ enum_constant public static final java.security.cert.PKIXRevocationChecker.Option SOFT_FAIL;
+ }
+
public abstract interface PolicyNode {
method public abstract java.util.Iterator<? extends java.security.cert.PolicyNode> getChildren();
method public abstract int getDepth();
@@ -54468,6 +54593,7 @@
method public javax.security.auth.x500.X500Principal getSubjectX500Principal();
method public abstract byte[] getTBSCertificate() throws java.security.cert.CertificateEncodingException;
method public abstract int getVersion();
+ method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
}
public abstract interface X509Extension {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 468c145..3293c26 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -16,11 +16,13 @@
package android.accessibilityservice;
+import android.accessibilityservice.GestureDescription.MotionEventGenerator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ParceledListSlice;
import android.graphics.Region;
import android.os.Handler;
import android.os.IBinder;
@@ -29,8 +31,11 @@
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.KeyEvent;
+import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityEvent;
@@ -41,10 +46,7 @@
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
/**
* An accessibility service runs in the background and receives callbacks by the system
@@ -376,6 +378,7 @@
public boolean onKeyEvent(KeyEvent event);
public void onMagnificationChanged(@NonNull Region region,
float scale, float centerX, float centerY);
+ public void onPerformGestureResult(int sequence, boolean completedSuccessfully);
}
private int mConnectionId;
@@ -388,6 +391,12 @@
private MagnificationController mMagnificationController;
+ private int mGestureStatusCallbackSequence;
+
+ private SparseArray<GestureResultCallbackInfo> mGestureStatusCallbackInfos;
+
+ private final Object mLock = new Object();
+
/**
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
*
@@ -551,6 +560,88 @@
return mMagnificationController;
}
+ /**
+ * Dispatch a gesture to the touch screen. Any gestures currently in progress, whether from
+ * the user, this service, or another service, will be cancelled.
+ * <p>
+ * <strong>Note:</strong> In order to dispatch gestures, your service
+ * must declare the capability by setting the
+ * {@link android.R.styleable#AccessibilityService_canPerformGestures}
+ * property in its meta-data. For more information, see
+ * {@link #SERVICE_META_DATA}.
+ *
+ * @param gesture The gesture to dispatch
+ * @param callback The object to call back when the status of the gesture is known. If
+ * {@code null}, no status is reported.
+ * @param handler The handler on which to call back the {@code callback} object. If
+ * {@code null}, the object is called back on the service's main thread.
+ *
+ * @return {@code true} if the gesture is dispatched, {@code false} if not.
+ */
+ public final boolean dispatchGesture(@NonNull GestureDescription gesture,
+ @Nullable GestureResultCallback callback,
+ @Nullable Handler handler) {
+ final IAccessibilityServiceConnection connection =
+ AccessibilityInteractionClient.getInstance().getConnection(
+ mConnectionId);
+ if (connection == null) {
+ return false;
+ }
+ List<MotionEvent> events = MotionEventGenerator.getMotionEventsFromGestureDescription(
+ gesture, 100);
+ try {
+ synchronized (mLock) {
+ connection.sendMotionEvents(++mGestureStatusCallbackSequence,
+ new ParceledListSlice<>(events));
+ if (callback != null) {
+ if (mGestureStatusCallbackInfos == null) {
+ mGestureStatusCallbackInfos = new SparseArray<>();
+ }
+ GestureResultCallbackInfo callbackInfo = new GestureResultCallbackInfo(gesture,
+ callback, handler);
+ mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo);
+ }
+ }
+ } catch (RemoteException re) {
+ throw new RuntimeException(re);
+ }
+ return true;
+ }
+
+ void onPerformGestureResult(int sequence, final boolean completedSuccessfully) {
+ if (mGestureStatusCallbackInfos == null) {
+ return;
+ }
+ GestureResultCallbackInfo callbackInfo;
+ synchronized (mLock) {
+ callbackInfo = mGestureStatusCallbackInfos.get(sequence);
+ }
+ final GestureResultCallbackInfo finalCallbackInfo = callbackInfo;
+ if ((callbackInfo != null) && (callbackInfo.gestureDescription != null)
+ && (callbackInfo.callback != null)) {
+ if (callbackInfo.handler != null) {
+ callbackInfo.handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (completedSuccessfully) {
+ finalCallbackInfo.callback
+ .onCompleted(finalCallbackInfo.gestureDescription);
+ } else {
+ finalCallbackInfo.callback
+ .onCancelled(finalCallbackInfo.gestureDescription);
+ }
+ }
+ });
+ return;
+ }
+ if (completedSuccessfully) {
+ callbackInfo.callback.onCompleted(callbackInfo.gestureDescription);
+ } else {
+ callbackInfo.callback.onCancelled(callbackInfo.gestureDescription);
+ }
+ }
+ }
+
private void onMagnificationChanged(@NonNull Region region, float scale,
float centerX, float centerY) {
if (mMagnificationController != null) {
@@ -1082,6 +1173,11 @@
float scale, float centerX, float centerY) {
AccessibilityService.this.onMagnificationChanged(region, scale, centerX, centerY);
}
+
+ @Override
+ public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
+ AccessibilityService.this.onPerformGestureResult(sequence, completedSuccessfully);
+ }
});
}
@@ -1100,6 +1196,7 @@
private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5;
private static final int DO_ON_KEY_EVENT = 6;
private static final int DO_ON_MAGNIFICATION_CHANGED = 7;
+ private static final int DO_GESTURE_COMPLETE = 8;
private final HandlerCaller mCaller;
@@ -1158,6 +1255,12 @@
mCaller.sendMessage(message);
}
+ public void onPerformGestureResult(int sequence, boolean successfully) {
+ Message message = mCaller.obtainMessageII(DO_GESTURE_COMPLETE, sequence,
+ successfully ? 1 : 0);
+ mCaller.sendMessage(message);
+ }
+
@Override
public void executeMessage(Message message) {
switch (message.what) {
@@ -1242,9 +1345,47 @@
mCallback.onMagnificationChanged(region, scale, centerX, centerY);
} return;
+ case DO_GESTURE_COMPLETE: {
+ final boolean successfully = message.arg2 == 1;
+ mCallback.onPerformGestureResult(message.arg1, successfully);
+ } return;
+
default :
Log.w(LOG_TAG, "Unknown message type " + message.what);
}
}
}
+
+ /**
+ * Class used to report status of dispatched gestures
+ */
+ public static abstract class GestureResultCallback {
+ /** Called when the gesture has completed successfully
+ *
+ * @param gestureDescription The description of the gesture that completed.
+ */
+ public void onCompleted(GestureDescription gestureDescription) {
+ }
+
+ /** Called when the gesture was cancelled
+ *
+ * @param gestureDescription The description of the gesture that was cancelled.
+ */
+ public void onCancelled(GestureDescription gestureDescription) {
+ }
+ }
+
+ /* Object to keep track of gesture result callbacks */
+ private static class GestureResultCallbackInfo {
+ GestureDescription gestureDescription;
+ GestureResultCallback callback;
+ Handler handler;
+
+ GestureResultCallbackInfo(GestureDescription gestureDescription,
+ GestureResultCallback callback, Handler handler) {
+ this.gestureDescription = gestureDescription;
+ this.callback = callback;
+ this.handler = handler;
+ }
+ }
}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 2c98fef..079bdfc 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -110,6 +110,12 @@
*/
public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0x00000010;
+ /**
+ * Capability: This accessibility service can perform gestures.
+ * @see android.R.styleable#AccessibilityService_canPerformGestures
+ */
+ public static final int CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020;
+
private static final SparseArray<CapabilityInfo> sAvailableCapabilityInfos =
new SparseArray<CapabilityInfo>();
static {
@@ -133,6 +139,10 @@
new CapabilityInfo(CAPABILITY_CAN_CONTROL_MAGNIFICATION,
R.string.capability_title_canControlMagnification,
R.string.capability_desc_canControlMagnification));
+ sAvailableCapabilityInfos.put(CAPABILITY_CAN_PERFORM_GESTURES,
+ new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES,
+ R.string.capability_title_canPerformGestures,
+ R.string.capability_desc_canPerformGestures));
}
/**
@@ -276,12 +286,7 @@
/**
* This flag requests from the system to filter key events. If this flag
* is set the accessibility service will receive the key events before
- * applications allowing it implement global shortcuts. Setting this flag
- * does not guarantee that this service will filter key events since only
- * one service can do so at any given time. This avoids user confusion due
- * to behavior change in case different key filtering services are enabled.
- * If there is already another key filtering service enabled, this one will
- * not receive key events.
+ * applications allowing it implement global shortcuts.
* <p>
* Services that want to set this flag have to declare this capability
* in their meta-data by setting the attribute {@link android.R.attr
@@ -516,6 +521,10 @@
.AccessibilityService_canControlMagnification, false)) {
mCapabilities |= CAPABILITY_CAN_CONTROL_MAGNIFICATION;
}
+ if (asAttributes.getBoolean(com.android.internal.R.styleable
+ .AccessibilityService_canPerformGestures, false)) {
+ mCapabilities |= CAPABILITY_CAN_PERFORM_GESTURES;
+ }
TypedValue peekedValue = asAttributes.peekValue(
com.android.internal.R.styleable.AccessibilityService_description);
if (peekedValue != null) {
@@ -616,6 +625,8 @@
* @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
* @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
* @see #CAPABILITY_FILTER_KEY_EVENTS
+ * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
+ * @see #CAPABILITY_CAN_PERFORM_GESTURES
*/
public int getCapabilities() {
return mCapabilities;
@@ -631,6 +642,8 @@
* @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
* @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
* @see #CAPABILITY_FILTER_KEY_EVENTS
+ * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION
+ * @see #CAPABILITY_CAN_PERFORM_GESTURES
*
* @hide
*/
@@ -933,6 +946,8 @@
return "CAPABILITY_CAN_FILTER_KEY_EVENTS";
case CAPABILITY_CAN_CONTROL_MAGNIFICATION:
return "CAPABILITY_CAN_CONTROL_MAGNIFICATION";
+ case CAPABILITY_CAN_PERFORM_GESTURES:
+ return "CAPABILITY_CAN_PERFORM_GESTURES";
default:
return "UNKNOWN";
}
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
new file mode 100644
index 0000000..14aabcf
--- /dev/null
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.accessibilityservice;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.RectF;
+import android.view.InputDevice;
+import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
+import android.view.ViewConfiguration;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Accessibility services with the
+ * {@link android.R.styleable#AccessibilityService_canPerformGestures} property can dispatch
+ * gestures. This class describes those gestures. Gestures are made up of one or more strokes.
+ * Gestures are immutable; use the {@code create} methods to get common gesture, or a
+ * {@code Builder} to create a new one.
+ * <p>
+ * Spatial dimensions throughout are in screen pixels. Time is measured in milliseconds.
+ */
+public final class GestureDescription {
+ /** Gestures may contain no more than this many strokes */
+ public static final int MAX_STROKE_COUNT = 10;
+
+ /**
+ * Upper bound on total gesture duration. Nearly all gestures will be much shorter.
+ */
+ public static final long MAX_GESTURE_DURATION_MS = 60 * 1000;
+
+ private final List<StrokeDescription> mStrokes = new ArrayList<>();
+ private final float[] mTempPos = new float[2];
+
+ /**
+ * Create a description of a click gesture
+ *
+ * @param x The x coordinate to click. Must not be negative.
+ * @param y The y coordinate to click. Must not be negative.
+ *
+ * @return A description of a click at (x, y)
+ */
+ public static GestureDescription createClick(@IntRange(from = 0) int x,
+ @IntRange(from = 0) int y) {
+ Path clickPath = new Path();
+ clickPath.moveTo(x, y);
+ clickPath.lineTo(x + 1, y);
+ return new GestureDescription(
+ new StrokeDescription(clickPath, 0, ViewConfiguration.getTapTimeout()));
+ }
+
+ /**
+ * Create a description of a long click gesture
+ *
+ * @param x The x coordinate to click. Must not be negative.
+ * @param y The y coordinate to click. Must not be negative.
+ *
+ * @return A description of a click at (x, y)
+ */
+ public static GestureDescription createLongClick(@IntRange(from = 0) int x,
+ @IntRange(from = 0) int y) {
+ Path clickPath = new Path();
+ clickPath.moveTo(x, y);
+ clickPath.lineTo(x + 1, y);
+ int longPressTime = ViewConfiguration.getLongPressTimeout();
+ return new GestureDescription(
+ new StrokeDescription(clickPath, 0, longPressTime + (longPressTime / 2)));
+ }
+
+ /**
+ * Create a description of a swipe gesture
+ *
+ * @param startX The x coordinate of the starting point. Must not be negative.
+ * @param startY The y coordinate of the starting point. Must not be negative.
+ * @param endX The x coordinate of the ending point. Must not be negative.
+ * @param endY The y coordinate of the ending point. Must not be negative.
+ * @param duration The time, in milliseconds, to complete the gesture. Must not be negative.
+ *
+ * @return A description of a swipe from ({@code startX}, {@code startY}) to
+ * ({@code endX}, {@code endY}) that takes {@code duration} milliseconds. Returns {@code null}
+ * if the path specified for the swipe is invalid.
+ */
+ public static GestureDescription createSwipe(@IntRange(from = 0) int startX,
+ @IntRange(from = 0) int startY,
+ @IntRange(from = 0) int endX,
+ @IntRange(from = 0) int endY,
+ @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long duration) {
+ Path swipePath = new Path();
+ swipePath.moveTo(startX, startY);
+ swipePath.lineTo(endX, endY);
+ return new GestureDescription(new StrokeDescription(swipePath, 0, duration));
+ }
+
+ /**
+ * Create a description for a pinch (or zoom) gesture.
+ *
+ * @param centerX The x coordinate of the center of the pinch. Must not be negative.
+ * @param centerY The y coordinate of the center of the pinch. Must not be negative.
+ * @param startSpacing The spacing of the touch points at the beginning of the gesture. Must not
+ * be negative.
+ * @param endSpacing The spacing of the touch points at the end of the gesture. Must not be
+ * negative.
+ * @param orientation The angle, in degrees, of the gesture. 0 represents a horizontal pinch
+ * @param duration The time, in milliseconds, to complete the gesture. Must not be negative.
+ *
+ * @return A description of a pinch centered at ({code centerX}, {@code centerY}) that starts
+ * with the touch points spaced by {@code startSpacing} and ends with them spaced by
+ * {@code endSpacing} that lasts {@code duration} ms. Returns {@code null} if either path
+ * specified for the pinch is invalid.
+ */
+ public static GestureDescription createPinch(@IntRange(from = 0) int centerX,
+ @IntRange(from = 0) int centerY,
+ @IntRange(from = 0) int startSpacing,
+ @IntRange(from = 0) int endSpacing,
+ float orientation,
+ @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long duration) {
+ if ((startSpacing < 0) || (endSpacing < 0)) {
+ throw new IllegalArgumentException("Pinch spacing cannot be negative");
+ }
+ float[] startPoint1 = new float[2];
+ float[] endPoint1 = new float[2];
+ float[] startPoint2 = new float[2];
+ float[] endPoint2 = new float[2];
+
+ /* Build points for a horizontal gesture centered at the origin */
+ startPoint1[0] = startSpacing / 2;
+ startPoint1[1] = 0;
+ endPoint1[0] = endSpacing / 2;
+ endPoint1[1] = 0;
+ startPoint2[0] = -startSpacing / 2;
+ startPoint2[1] = 0;
+ endPoint2[0] = -endSpacing / 2;
+ endPoint2[1] = 0;
+
+ /* Rotate and translate the points */
+ Matrix matrix = new Matrix();
+ matrix.setRotate(orientation);
+ matrix.postTranslate(centerX, centerY);
+ matrix.mapPoints(startPoint1);
+ matrix.mapPoints(endPoint1);
+ matrix.mapPoints(startPoint2);
+ matrix.mapPoints(endPoint2);
+
+ Path path1 = new Path();
+ path1.moveTo(startPoint1[0], startPoint1[1]);
+ path1.lineTo(endPoint1[0], endPoint1[1]);
+ Path path2 = new Path();
+ path2.moveTo(startPoint2[0], startPoint2[1]);
+ path2.lineTo(endPoint2[0], endPoint2[1]);
+
+ return new GestureDescription(Arrays.asList(
+ new StrokeDescription(path1, 0, duration),
+ new StrokeDescription(path2, 0, duration)));
+ }
+
+ private GestureDescription() {}
+
+ private GestureDescription(List<StrokeDescription> strokes) {
+ mStrokes.addAll(strokes);
+ }
+
+ private GestureDescription(StrokeDescription stroke) {
+ mStrokes.add(stroke);
+ }
+
+ /**
+ * Get the number of stroke in the gesture.
+ *
+ * @return the number of strokes in this gesture
+ */
+ public int getStrokeCount() {
+ return mStrokes.size();
+ }
+
+ /**
+ * Read a stroke from the gesture
+ *
+ * @param index the index of the stroke
+ *
+ * @return A description of the stroke.
+ */
+ public StrokeDescription getStroke(@IntRange(from = 0) int index) {
+ return mStrokes.get(index);
+ }
+
+ /**
+ * Return the smallest key point (where a path starts or ends) that is at least a specified
+ * offset
+ * @param offset the minimum start time
+ * @return The next key time that is at least the offset or -1 if one can't be found
+ */
+ private long getNextKeyPointAtLeast(long offset) {
+ long nextKeyPoint = Long.MAX_VALUE;
+ for (int i = 0; i < mStrokes.size(); i++) {
+ long thisStartTime = mStrokes.get(i).mStartTime;
+ if ((thisStartTime < nextKeyPoint) && (thisStartTime >= offset)) {
+ nextKeyPoint = thisStartTime;
+ }
+ long thisEndTime = mStrokes.get(i).mEndTime;
+ if ((thisEndTime < nextKeyPoint) && (thisEndTime >= offset)) {
+ nextKeyPoint = thisEndTime;
+ }
+ }
+ return (nextKeyPoint == Long.MAX_VALUE) ? -1L : nextKeyPoint;
+ }
+
+ /**
+ * Get the points that correspond to a particular moment in time.
+ * @param time The time of interest
+ * @param touchPoints An array to hold the current touch points. Must be preallocated to at
+ * least the number of paths in the gesture to prevent going out of bounds
+ * @return The number of points found, and thus the number of elements set in each array
+ */
+ private int getPointsForTime(long time, TouchPoint[] touchPoints) {
+ int numPointsFound = 0;
+ for (int i = 0; i < mStrokes.size(); i++) {
+ StrokeDescription strokeDescription = mStrokes.get(i);
+ if (strokeDescription.hasPointForTime(time)) {
+ touchPoints[numPointsFound].mPathIndex = i;
+ touchPoints[numPointsFound].mIsStartOfPath = (time == strokeDescription.mStartTime);
+ touchPoints[numPointsFound].mIsEndOfPath = (time == strokeDescription.mEndTime);
+ strokeDescription.getPosForTime(time, mTempPos);
+ touchPoints[numPointsFound].mX = Math.round(mTempPos[0]);
+ touchPoints[numPointsFound].mY = Math.round(mTempPos[1]);
+ numPointsFound++;
+ }
+ }
+ return numPointsFound;
+ }
+
+ // Total duration assumes that the gesture starts at 0; waiting around to start a gesture
+ // counts against total duration
+ private static long getTotalDuration(List<StrokeDescription> paths) {
+ long latestEnd = Long.MIN_VALUE;
+ for (int i = 0; i < paths.size(); i++) {
+ StrokeDescription path = paths.get(i);
+ latestEnd = Math.max(latestEnd, path.mEndTime);
+ }
+ return Math.max(latestEnd, 0);
+ }
+
+ /**
+ * Builder for a {@code GestureDescription}
+ */
+ public static class Builder {
+
+ private final List<StrokeDescription> mStrokes = new ArrayList<>();
+
+ /**
+ * Add a stroke to the gesture description. Up to {@code MAX_STROKE_COUNT} paths may be
+ * added to a gesture, and the total gesture duration (earliest path start time to latest path
+ * end time) may not exceed {@code MAX_GESTURE_DURATION_MS}.
+ *
+ * @param strokeDescription the stroke to add.
+ *
+ * @return this
+ */
+ public Builder addStroke(@NonNull StrokeDescription strokeDescription) {
+ if (mStrokes.size() >= MAX_STROKE_COUNT) {
+ throw new RuntimeException("Attempting to add too many strokes to a gesture");
+ }
+
+ mStrokes.add(strokeDescription);
+
+ if (getTotalDuration(mStrokes) > MAX_GESTURE_DURATION_MS) {
+ mStrokes.remove(strokeDescription);
+ throw new RuntimeException("Gesture would exceed maximum duration with new stroke");
+ }
+ return this;
+ }
+
+ public GestureDescription build() {
+ if (mStrokes.size() == 0) {
+ throw new RuntimeException("Gestures must have at least one stroke");
+ }
+ return new GestureDescription(mStrokes);
+ }
+ }
+
+ /**
+ * Immutable description of stroke that can be part of a gesture.
+ */
+ public static class StrokeDescription {
+ Path mPath;
+ long mStartTime;
+ long mEndTime;
+ private float mTimeToLengthConversion;
+ private PathMeasure mPathMeasure;
+
+ /**
+ * @param path The path to follow. Must have exactly one contour, and that contour must
+ * have nonzero length. The bounds of the path must not be negative.
+ * @param startTime The time, in milliseconds, from the time the gesture starts to the
+ * time the stroke should start. Must not be negative.
+ * @param duration The duration, in milliseconds, the stroke takes to traverse the path.
+ * Must not be negative.
+ */
+ public StrokeDescription(@NonNull Path path,
+ @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long startTime,
+ @IntRange(from = 0, to = MAX_GESTURE_DURATION_MS) long duration) {
+ if (duration <= 0) {
+ throw new IllegalArgumentException("Duration must be positive");
+ }
+ if (startTime < 0) {
+ throw new IllegalArgumentException("Start time must not be negative");
+ }
+ RectF bounds = new RectF();
+ path.computeBounds(bounds, false /* unused */);
+ if ((bounds.bottom < 0) || (bounds.top < 0) || (bounds.right < 0)
+ || (bounds.left < 0)) {
+ throw new IllegalArgumentException("Path bounds must not be negative");
+ }
+ mPath = new Path(path);
+ mPathMeasure = new PathMeasure(path, false);
+ if (mPathMeasure.getLength() == 0) {
+ throw new IllegalArgumentException("Path has zero length");
+ }
+ if (mPathMeasure.nextContour()) {
+ throw new IllegalArgumentException("Path has more than one contour");
+ }
+ /*
+ * Calling nextContour has moved mPathMeasure off the first contour, which is the only
+ * one we care about. Set the path again to go back to the first contour.
+ */
+ mPathMeasure.setPath(path, false);
+ mStartTime = startTime;
+ mEndTime = startTime + duration;
+ if (duration > 0) {
+ mTimeToLengthConversion = getLength() / duration;
+ }
+ }
+
+ /**
+ * Retrieve a copy of the path for this stroke
+ *
+ * @return A copy of the path
+ */
+ public Path getPath() {
+ return new Path(mPath);
+ }
+
+ /**
+ * Get the stroke's start time
+ *
+ * @return the start time for this stroke.
+ */
+ public long getStartTime() {
+ return mStartTime;
+ }
+
+ /**
+ * Get the stroke's duration
+ *
+ * @return the duration for this stroke
+ */
+ public long getDuration() {
+ return mEndTime - mStartTime;
+ }
+
+ float getLength() {
+ return mPathMeasure.getLength();
+ }
+
+ /* Assumes hasPointForTime returns true */
+ boolean getPosForTime(long time, float[] pos) {
+ if (time == mEndTime) {
+ // Close to the end time, roundoff can be a problem
+ return mPathMeasure.getPosTan(getLength(), pos, null);
+ }
+ float length = mTimeToLengthConversion * ((float) (time - mStartTime));
+ return mPathMeasure.getPosTan(length, pos, null);
+ }
+
+ boolean hasPointForTime(long time) {
+ return ((time >= mStartTime) && (time <= mEndTime));
+ }
+ }
+
+ private static class TouchPoint {
+ int mPathIndex;
+ boolean mIsStartOfPath;
+ boolean mIsEndOfPath;
+ float mX;
+ float mY;
+
+ void copyFrom(TouchPoint other) {
+ mPathIndex = other.mPathIndex;
+ mIsStartOfPath = other.mIsStartOfPath;
+ mIsEndOfPath = other.mIsEndOfPath;
+ mX = other.mX;
+ mY = other.mY;
+ }
+ }
+
+ /**
+ * Class to convert a GestureDescription to a series of MotionEvents.
+ */
+ static class MotionEventGenerator {
+ /**
+ * Constants used to initialize all MotionEvents
+ */
+ private static final int EVENT_META_STATE = 0;
+ private static final int EVENT_BUTTON_STATE = 0;
+ private static final int EVENT_DEVICE_ID = 0;
+ private static final int EVENT_EDGE_FLAGS = 0;
+ private static final int EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
+ private static final int EVENT_FLAGS = 0;
+ private static final float EVENT_X_PRECISION = 1;
+ private static final float EVENT_Y_PRECISION = 1;
+
+ /* Lazily-created scratch memory for processing touches */
+ private static TouchPoint[] sCurrentTouchPoints;
+ private static TouchPoint[] sLastTouchPoints;
+ private static PointerCoords[] sPointerCoords;
+ private static PointerProperties[] sPointerProps;
+
+ static List<MotionEvent> getMotionEventsFromGestureDescription(
+ GestureDescription description, int sampleTimeMs) {
+ final List<MotionEvent> motionEvents = new ArrayList<>();
+
+ // Point data at each time we generate an event for
+ final TouchPoint[] currentTouchPoints =
+ getCurrentTouchPoints(description.getStrokeCount());
+ // Point data sent in last touch event
+ int lastTouchPointSize = 0;
+ final TouchPoint[] lastTouchPoints =
+ getLastTouchPoints(description.getStrokeCount());
+
+ /* Loop through each time slice where there are touch points */
+ long timeSinceGestureStart = 0;
+ long nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart);
+ while (nextKeyPointTime >= 0) {
+ timeSinceGestureStart = (lastTouchPointSize == 0) ? nextKeyPointTime
+ : Math.min(nextKeyPointTime, timeSinceGestureStart + sampleTimeMs);
+ int currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart,
+ currentTouchPoints);
+
+ appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize,
+ currentTouchPoints, currentTouchPointSize, timeSinceGestureStart);
+ lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints,
+ lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
+ timeSinceGestureStart);
+ lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints,
+ lastTouchPointSize, currentTouchPoints, currentTouchPointSize,
+ timeSinceGestureStart);
+
+ /* Move to next time slice */
+ nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1);
+ }
+ return motionEvents;
+ }
+
+ private static TouchPoint[] getCurrentTouchPoints(int requiredCapacity) {
+ if ((sCurrentTouchPoints == null) || (sCurrentTouchPoints.length < requiredCapacity)) {
+ sCurrentTouchPoints = new TouchPoint[requiredCapacity];
+ for (int i = 0; i < requiredCapacity; i++) {
+ sCurrentTouchPoints[i] = new TouchPoint();
+ }
+ }
+ return sCurrentTouchPoints;
+ }
+
+ private static TouchPoint[] getLastTouchPoints(int requiredCapacity) {
+ if ((sLastTouchPoints == null) || (sLastTouchPoints.length < requiredCapacity)) {
+ sLastTouchPoints = new TouchPoint[requiredCapacity];
+ for (int i = 0; i < requiredCapacity; i++) {
+ sLastTouchPoints[i] = new TouchPoint();
+ }
+ }
+ return sLastTouchPoints;
+ }
+
+ private static PointerCoords[] getPointerCoords(int requiredCapacity) {
+ if ((sPointerCoords == null) || (sPointerCoords.length < requiredCapacity)) {
+ sPointerCoords = new PointerCoords[requiredCapacity];
+ for (int i = 0; i < requiredCapacity; i++) {
+ sPointerCoords[i] = new PointerCoords();
+ }
+ }
+ return sPointerCoords;
+ }
+
+ private static PointerProperties[] getPointerProps(int requiredCapacity) {
+ if ((sPointerProps == null) || (sPointerProps.length < requiredCapacity)) {
+ sPointerProps = new PointerProperties[requiredCapacity];
+ for (int i = 0; i < requiredCapacity; i++) {
+ sPointerProps[i] = new PointerProperties();
+ }
+ }
+ return sPointerProps;
+ }
+
+ private static void appendMoveEventIfNeeded(List<MotionEvent> motionEvents,
+ TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for pointers that have moved */
+ boolean moveFound = false;
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ int lastPointsIndex = findPointByPathIndex(lastTouchPoints, lastTouchPointsSize,
+ currentTouchPoints[i].mPathIndex);
+ if (lastPointsIndex >= 0) {
+ moveFound |= (lastTouchPoints[lastPointsIndex].mX != currentTouchPoints[i].mX)
+ || (lastTouchPoints[lastPointsIndex].mY != currentTouchPoints[i].mY);
+ lastTouchPoints[lastPointsIndex].copyFrom(currentTouchPoints[i]);
+ }
+ }
+
+ if (moveFound) {
+ long downTime = motionEvents.get(motionEvents.size() - 1).getDownTime();
+ motionEvents.add(obtainMotionEvent(downTime, currentTime, MotionEvent.ACTION_MOVE,
+ lastTouchPoints, lastTouchPointsSize));
+ }
+ }
+
+ private static int appendUpEvents(List<MotionEvent> motionEvents,
+ TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for a pointer at the end of its path */
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ if (currentTouchPoints[i].mIsEndOfPath) {
+ int indexOfUpEvent = findPointByPathIndex(lastTouchPoints, lastTouchPointsSize,
+ currentTouchPoints[i].mPathIndex);
+ if (indexOfUpEvent < 0) {
+ continue; // Should not happen
+ }
+ long downTime = motionEvents.get(motionEvents.size() - 1).getDownTime();
+ int action = (lastTouchPointsSize == 1) ? MotionEvent.ACTION_UP
+ : MotionEvent.ACTION_POINTER_UP;
+ action |= indexOfUpEvent << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ motionEvents.add(obtainMotionEvent(downTime, currentTime, action,
+ lastTouchPoints, lastTouchPointsSize));
+ /* Remove this point from lastTouchPoints */
+ for (int j = indexOfUpEvent; j < lastTouchPointsSize - 1; j++) {
+ lastTouchPoints[j].copyFrom(lastTouchPoints[j+1]);
+ }
+ lastTouchPointsSize--;
+ }
+ }
+ return lastTouchPointsSize;
+ }
+
+ private static int appendDownEvents(List<MotionEvent> motionEvents,
+ TouchPoint[] lastTouchPoints, int lastTouchPointsSize,
+ TouchPoint[] currentTouchPoints, int currentTouchPointsSize, long currentTime) {
+ /* Look for a pointer that is just starting */
+ for (int i = 0; i < currentTouchPointsSize; i++) {
+ if (currentTouchPoints[i].mIsStartOfPath) {
+ /* Add the point to last coords and use the new array to generate the event */
+ lastTouchPoints[lastTouchPointsSize++].copyFrom(currentTouchPoints[i]);
+ int action = (lastTouchPointsSize == 1) ? MotionEvent.ACTION_DOWN
+ : MotionEvent.ACTION_POINTER_DOWN;
+ long downTime = (action == MotionEvent.ACTION_DOWN) ? currentTime :
+ motionEvents.get(motionEvents.size() - 1).getDownTime();
+ action |= i << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ motionEvents.add(obtainMotionEvent(downTime, currentTime, action,
+ lastTouchPoints, lastTouchPointsSize));
+ }
+ }
+ return lastTouchPointsSize;
+ }
+
+ private static MotionEvent obtainMotionEvent(long downTime, long eventTime, int action,
+ TouchPoint[] touchPoints, int touchPointsSize) {
+ PointerCoords[] pointerCoords = getPointerCoords(touchPointsSize);
+ PointerProperties[] pointerProperties = getPointerProps(touchPointsSize);
+ for (int i = 0; i < touchPointsSize; i++) {
+ pointerProperties[i].id = touchPoints[i].mPathIndex;
+ pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN;
+ pointerCoords[i].clear();
+ pointerCoords[i].pressure = 1.0f;
+ pointerCoords[i].size = 1.0f;
+ pointerCoords[i].x = touchPoints[i].mX;
+ pointerCoords[i].y = touchPoints[i].mY;
+ }
+ return MotionEvent.obtain(downTime, eventTime, action, touchPointsSize,
+ pointerProperties, pointerCoords, EVENT_META_STATE, EVENT_BUTTON_STATE,
+ EVENT_X_PRECISION, EVENT_Y_PRECISION, EVENT_DEVICE_ID, EVENT_EDGE_FLAGS,
+ EVENT_SOURCE, EVENT_FLAGS);
+ }
+
+ private static int findPointByPathIndex(TouchPoint[] touchPoints, int touchPointsSize,
+ int pathIndex) {
+ for (int i = 0; i < touchPointsSize; i++) {
+ if (touchPoints[i].mPathIndex == pathIndex) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ }
+}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index 15666bf..6280542 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -42,4 +42,6 @@
void onKeyEvent(in KeyEvent event, int sequence);
void onMagnificationChanged(in Region region, float scale, float centerX, float centerY);
+
+ void onPerformGestureResult(int sequence, boolean completedSuccessfully);
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 6ac50bd..a65b87b 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -16,10 +16,12 @@
package android.accessibilityservice;
-import android.os.Bundle;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.pm.ParceledListSlice;
import android.graphics.Region;
+import android.os.Bundle;
import android.view.MagnificationSpec;
+import android.view.MotionEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.accessibility.AccessibilityWindowInfo;
@@ -79,4 +81,6 @@
boolean animate);
void setMagnificationCallbackEnabled(boolean enabled);
+
+ void sendMotionEvents(int sequence, in ParceledListSlice events);
}
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 8928e99..e993cca 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -861,22 +861,23 @@
if (mProperty != null) {
Object value = convertBack(mProperty.get(target));
kf.setValue(value);
- }
- try {
- if (mGetter == null) {
- Class targetClass = target.getClass();
- setupGetter(targetClass);
+ } else {
+ try {
if (mGetter == null) {
- // Already logged the error - just return to avoid NPE
- return;
+ Class targetClass = target.getClass();
+ setupGetter(targetClass);
+ if (mGetter == null) {
+ // Already logged the error - just return to avoid NPE
+ return;
+ }
}
+ Object value = convertBack(mGetter.invoke(target));
+ kf.setValue(value);
+ } catch (InvocationTargetException e) {
+ Log.e("PropertyValuesHolder", e.toString());
+ } catch (IllegalAccessException e) {
+ Log.e("PropertyValuesHolder", e.toString());
}
- Object value = convertBack(mGetter.invoke(target));
- kf.setValue(value);
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
}
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 64642ac..e312596 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -62,6 +62,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.media.AudioManager;
import android.media.session.MediaController;
import android.net.Uri;
@@ -71,6 +72,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.StrictMode;
import android.os.UserHandle;
@@ -78,23 +80,28 @@
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
+import android.transition.Scene;
+import android.transition.TransitionManager;
+import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SuperNotCalledException;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextThemeWrapper;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
+import android.view.KeyboardShortcutInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
-import com.android.internal.policy.PhoneWindow;
import android.view.SearchEvent;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
@@ -103,10 +110,17 @@
import android.view.ViewManager;
import android.view.ViewRootImpl;
import android.view.Window;
+import android.view.Window.WindowControllerCallback;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
+import android.widget.Toolbar;
+
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.ToolbarActionBar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.policy.PhoneWindow;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -116,6 +130,8 @@
import java.util.HashMap;
import java.util.List;
+import static java.lang.Character.MIN_VALUE;
+
/**
* An activity is a single, focused thing that the user can do. Almost all
* activities interact with the user, so the Activity class takes care of
@@ -1594,6 +1610,30 @@
public void onProvideAssistContent(AssistContent outContent) {
}
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ if (menu == null) {
+ return;
+ }
+ KeyboardShortcutGroup group = null;
+ int menuSize = menu.size();
+ for (int i = 0; i < menuSize; ++i) {
+ final MenuItem item = menu.getItem(i);
+ final CharSequence title = item.getTitle();
+ final char alphaShortcut = item.getAlphabeticShortcut();
+ if (title != null && alphaShortcut != MIN_VALUE) {
+ if (group == null) {
+ group = new KeyboardShortcutGroup(null /* no label */);
+ }
+ group.addItem(new KeyboardShortcutInfo(
+ title, alphaShortcut, KeyEvent.META_CTRL_ON));
+ }
+ }
+ if (group != null) {
+ data.add(group);
+ }
+ }
+
/**
* Ask to have the current assistant shown to the user. This only works if the calling
* activity is the current foreground activity. It is the same as calling
@@ -2843,16 +2883,15 @@
if (keyCode == KeyEvent.KEYCODE_MENU &&
mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
return true;
- } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
- // Capture the Alt-up and send focus to the ActionBar
+ } else if (event.isCtrlPressed() &&
+ event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK) == '<') {
+ // Capture the Control-< and send focus to the ActionBar
final int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
- if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
- final ActionBar actionBar = getActionBar();
- if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) {
- mEatKeyUpEvent = true;
- return true;
- }
+ final ActionBar actionBar = getActionBar();
+ if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) {
+ mEatKeyUpEvent = true;
+ return true;
}
} else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) {
mEatKeyUpEvent = false;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9540ae1..2175a9e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -592,6 +592,14 @@
public static boolean isAlwaysOnTop(int stackId) {
return stackId == PINNED_STACK_ID;
}
+
+ /**
+ * Returns true if the top task in the task is allowed to return home when finished and
+ * there are other tasks in the stack.
+ */
+ public static boolean allowTopTaskToReturnHome(int stackId) {
+ return stackId != PINNED_STACK_ID;
+ }
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4531a74..4e55c89 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1815,7 +1815,9 @@
ApplicationInfo ai = null;
try {
ai = getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES, userId);
+ PackageManager.GET_SHARED_LIBRARY_FILES
+ | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ userId);
} catch (RemoteException e) {
// Ignore
}
@@ -2013,7 +2015,7 @@
private static final String ONE_COUNT_COLUMN_HEADER = "%21s %8s";
// Formatting for checkin service - update version if row format changes
- private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 3;
+ private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 4;
static void printRow(PrintWriter pw, String format, Object...objs) {
pw.println(String.format(format, objs));
@@ -2089,6 +2091,25 @@
pw.print(memInfo.otherPrivateClean); pw.print(',');
pw.print(memInfo.getTotalPrivateClean()); pw.print(',');
+ // Heap info - swapped out
+ pw.print(memInfo.nativeSwappedOut); pw.print(',');
+ pw.print(memInfo.dalvikSwappedOut); pw.print(',');
+ pw.print(memInfo.otherSwappedOut); pw.print(',');
+ pw.print(memInfo.getTotalSwappedOut()); pw.print(',');
+
+ // Heap info - swapped out pss
+ if (memInfo.hasSwappedOutPss) {
+ pw.print(memInfo.nativeSwappedOutPss); pw.print(',');
+ pw.print(memInfo.dalvikSwappedOutPss); pw.print(',');
+ pw.print(memInfo.otherSwappedOutPss); pw.print(',');
+ pw.print(memInfo.getTotalSwappedOutPss()); pw.print(',');
+ } else {
+ pw.print("N/A,");
+ pw.print("N/A,");
+ pw.print("N/A,");
+ pw.print("N/A,");
+ }
+
// Heap info - other areas
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
pw.print(Debug.MemoryInfo.getOtherLabel(i)); pw.print(',');
@@ -2098,6 +2119,12 @@
pw.print(memInfo.getOtherSharedClean(i)); pw.print(',');
pw.print(memInfo.getOtherPrivateDirty(i)); pw.print(',');
pw.print(memInfo.getOtherPrivateClean(i)); pw.print(',');
+ pw.print(memInfo.getOtherSwappedOut(i)); pw.print(',');
+ if (memInfo.hasSwappedOutPss) {
+ pw.print(memInfo.getOtherSwappedOutPss(i)); pw.print(',');
+ } else {
+ pw.print("N/A,");
+ }
}
return;
}
@@ -2105,35 +2132,44 @@
if (!dumpSummaryOnly) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
- "Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
+ "Shared", "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
+ "Heap", "Heap", "Heap");
printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
- "Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
+ "Clean", "Clean", "Dirty",
+ "Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
"------", "------", "------", "------", "------", "------");
printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
- memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
+ memInfo.nativePrivateClean, memInfo.hasSwappedOutPss ?
+ memInfo.nativeSwappedOut : memInfo.nativeSwappedOutPss,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
- memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
+ memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss ?
+ memInfo.dalvikSwappedOut : memInfo.dalvikSwappedOutPss,
dalvikMax, dalvikAllocated, dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
- "Private", "Swapped", "Heap", "Heap", "Heap");
+ "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
+ "Heap", "Heap", "Heap");
printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
"Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
"------", "------", "------", "------", "------");
printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativePrivateDirty,
- memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
+ memInfo.nativePrivateClean,
+ memInfo.hasSwappedOutPss ? memInfo.nativeSwappedOutPss :
+ memInfo.nativeSwappedOut,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikPrivateDirty,
- memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
+ memInfo.dalvikPrivateClean,
+ memInfo.hasSwappedOutPss ? memInfo.dalvikSwappedOutPss :
+ memInfo.dalvikSwappedOut,
dalvikMax, dalvikAllocated, dalvikFree);
}
@@ -2144,6 +2180,7 @@
int otherSharedClean = memInfo.otherSharedClean;
int otherPrivateClean = memInfo.otherPrivateClean;
int otherSwappedOut = memInfo.otherSwappedOut;
+ int otherSwappedOutPss = memInfo.otherSwappedOutPss;
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
final int myPss = memInfo.getOtherPss(i);
@@ -2153,16 +2190,22 @@
final int mySharedClean = memInfo.getOtherSharedClean(i);
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
+ final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
- || mySharedClean != 0 || myPrivateClean != 0 || mySwappedOut != 0) {
+ || mySharedClean != 0 || myPrivateClean != 0
+ || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
- mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
+ mySharedClean, myPrivateClean,
+ memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
+ "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, myPrivateDirty,
- myPrivateClean, mySwappedOut, "", "", "");
+ myPrivateClean,
+ memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
+ "", "", "");
}
otherPss -= myPss;
otherSwappablePss -= mySwappablePss;
@@ -2171,26 +2214,32 @@
otherSharedClean -= mySharedClean;
otherPrivateClean -= myPrivateClean;
otherSwappedOut -= mySwappedOut;
+ otherSwappedOutPss -= mySwappedOutPss;
}
}
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
- otherSwappedOut, "", "", "");
+ memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
+ "", "", "");
printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
- memInfo.getTotalSwappedOut(), nativeMax+dalvikMax,
- nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
+ memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOut() :
+ memInfo.getTotalSwappedOutPss(),
+ nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
+ nativeFree+dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
- otherPrivateDirty, otherPrivateClean, otherSwappedOut,
+ otherPrivateDirty, otherPrivateClean,
+ memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
"", "", "");
printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalPrivateDirty(),
memInfo.getTotalPrivateClean(),
+ memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
memInfo.getTotalSwappedOut(),
nativeMax+dalvikMax,
nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
@@ -2209,16 +2258,22 @@
final int mySharedClean = memInfo.getOtherSharedClean(i);
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
+ final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
- || mySharedClean != 0 || myPrivateClean != 0) {
+ || mySharedClean != 0 || myPrivateClean != 0
+ || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
- mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
+ mySharedClean, myPrivateClean,
+ memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
+ "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, myPrivateDirty,
- myPrivateClean, mySwappedOut, "", "", "");
+ myPrivateClean,
+ memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
+ "", "", "");
}
}
}
@@ -2244,9 +2299,15 @@
printRow(pw, ONE_COUNT_COLUMN,
"System:", memInfo.getSummarySystem());
pw.println(" ");
- printRow(pw, TWO_COUNT_COLUMNS,
- "TOTAL:", memInfo.getSummaryTotalPss(),
- "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
+ if (memInfo.hasSwappedOutPss) {
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "TOTAL:", memInfo.getSummaryTotalPss(),
+ "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
+ } else {
+ printRow(pw, TWO_COUNT_COLUMNS,
+ "TOTAL:", memInfo.getSummaryTotalPss(),
+ "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
+ }
}
public void registerOnActivityPausedListener(Activity activity,
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 42b18384..0afca9d 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -221,7 +221,7 @@
public int[] getPackageGids(String packageName, int flags)
throws NameNotFoundException {
try {
- int[] gids = mPM.getPackageGidsEtc(packageName, flags, mContext.getUserId());
+ int[] gids = mPM.getPackageGids(packageName, flags, mContext.getUserId());
if (gids != null) {
return gids;
}
@@ -246,7 +246,7 @@
public int getPackageUidAsUser(String packageName, int flags, int userId)
throws NameNotFoundException {
try {
- int uid = mPM.getPackageUidEtc(packageName, flags, userId);
+ int uid = mPM.getPackageUid(packageName, flags, userId);
if (uid >= 0) {
return uid;
}
@@ -314,8 +314,14 @@
@Override
public ApplicationInfo getApplicationInfo(String packageName, int flags)
throws NameNotFoundException {
+ return getApplicationInfoAsUser(packageName, flags, mContext.getUserId());
+ }
+
+ @Override
+ public ApplicationInfo getApplicationInfoAsUser(String packageName, int flags, int userId)
+ throws NameNotFoundException {
try {
- ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, mContext.getUserId());
+ ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, userId);
if (ai != null) {
// This is a temporary hack. Callers must use
// createPackageContext(packageName).getApplicationInfo() to
@@ -352,7 +358,6 @@
}
}
-
@Override
public ActivityInfo getActivityInfo(ComponentName className, int flags)
throws NameNotFoundException {
@@ -1169,8 +1174,10 @@
throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
}
- int mCachedSafeMode = -1;
- @Override public boolean isSafeMode() {
+ volatile int mCachedSafeMode = -1;
+
+ @Override
+ public boolean isSafeMode() {
try {
if (mCachedSafeMode < 0) {
mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 569ab11..fab3740 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1762,10 +1762,6 @@
@Override
public Context createDeviceEncryptedStorageContext() {
- if (!StorageManager.isFileBasedEncryptionEnabled()) {
- return null;
- }
-
final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_ENCRYPTED_STORAGE)
| Context.CONTEXT_DEVICE_ENCRYPTED_STORAGE;
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6e8e2c4..79461b4 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -21,9 +21,8 @@
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
-import android.annotation.StringRes;
-
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.content.ComponentName;
import android.content.Context;
@@ -44,11 +43,11 @@
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
-import com.android.internal.policy.PhoneWindow;
import android.view.SearchEvent;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
@@ -60,8 +59,10 @@
import com.android.internal.R;
import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.policy.PhoneWindow;
import java.lang.ref.WeakReference;
+import java.util.List;
/**
* Base class for Dialogs.
@@ -1081,6 +1082,13 @@
}
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ }
+
+ /**
* @return The activity associated with this dialog, or null if there is no associated activity.
*/
private ComponentName getAssociatedActivity() {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index a73ad09..e163b1c 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -409,9 +409,6 @@
// If set this fragment is being removed from its activity.
boolean mRemoving;
- // True if the fragment is in the resumed state.
- boolean mResumed;
-
// Set to true if this fragment was instantiated from a layout file.
boolean mFromLayout;
@@ -928,7 +925,7 @@
* for the duration of {@link #onResume()} and {@link #onPause()} as well.
*/
final public boolean isResumed() {
- return mResumed;
+ return mState >= RESUMED;
}
/**
@@ -1630,7 +1627,6 @@
mWho = null;
mAdded = false;
mRemoving = false;
- mResumed = false;
mFromLayout = false;
mInLayout = false;
mRestored = false;
@@ -2113,7 +2109,6 @@
writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
writer.print(" mRemoving="); writer.print(mRemoving);
- writer.print(" mResumed="); writer.print(mResumed);
writer.print(" mFromLayout="); writer.print(mFromLayout);
writer.print(" mInLayout="); writer.println(mInLayout);
writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
@@ -2208,6 +2203,7 @@
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
}
+ mState = CREATED;
mCalled = false;
onCreate(savedInstanceState);
if (!mCalled) {
@@ -2238,6 +2234,7 @@
if (mChildFragmentManager != null) {
mChildFragmentManager.noteStateNotSaved();
}
+ mState = ACTIVITY_CREATED;
mCalled = false;
onActivityCreated(savedInstanceState);
if (!mCalled) {
@@ -2254,6 +2251,7 @@
mChildFragmentManager.noteStateNotSaved();
mChildFragmentManager.execPendingActions();
}
+ mState = STARTED;
mCalled = false;
onStart();
if (!mCalled) {
@@ -2273,6 +2271,7 @@
mChildFragmentManager.noteStateNotSaved();
mChildFragmentManager.execPendingActions();
}
+ mState = RESUMED;
mCalled = false;
onResume();
if (!mCalled) {
@@ -2389,6 +2388,7 @@
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchPause();
}
+ mState = STARTED;
mCalled = false;
onPause();
if (!mCalled) {
@@ -2401,6 +2401,7 @@
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchStop();
}
+ mState = STOPPED;
mCalled = false;
onStop();
if (!mCalled) {
@@ -2428,6 +2429,7 @@
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchDestroyView();
}
+ mState = CREATED;
mCalled = false;
onDestroyView();
if (!mCalled) {
@@ -2443,6 +2445,7 @@
if (mChildFragmentManager != null) {
mChildFragmentManager.dispatchDestroy();
}
+ mState = INITIALIZING;
mCalled = false;
onDestroy();
if (!mCalled) {
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 696ccdb..84ae09d 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1004,7 +1004,6 @@
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
- f.mResumed = true;
f.performResume();
// Get rid of this in case we saved it and never needed it.
f.mSavedFragmentState = null;
@@ -1017,7 +1016,6 @@
if (newState < Fragment.RESUMED) {
if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
f.performPause();
- f.mResumed = false;
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
@@ -1096,6 +1094,8 @@
if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
if (!f.mRetaining) {
f.performDestroy();
+ } else {
+ f.mState = Fragment.INITIALIZING;
}
f.mCalled = false;
@@ -1119,7 +1119,11 @@
}
}
- f.mState = newState;
+ if (f.mState != newState) {
+ Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
+ + "expected state " + newState + " found " + f.mState);
+ f.mState = newState;
+ }
}
void moveToState(Fragment f) {
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 8475840..dce2e51 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1031,6 +1031,11 @@
float scale, float centerX, float centerY) {
/* do nothing */
}
+
+ @Override
+ public void onPerformGestureResult(int sequence, boolean completedSuccessfully) {
+ /* do nothing */
+ }
});
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 08e9b1e..bebc8cf 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -620,6 +620,21 @@
"android.app.extra.PROVISIONING_LOGO_URI";
/**
+ * A boolean extra indicating if user setup should be skipped, for when provisioning is started
+ * during setup-wizard.
+ *
+ * <p>If unspecified, defaults to {@code true} to match the behavior in
+ * {@link android.os.Build.VERSION_CODES#M} and earlier.
+ *
+ * <p>Use in an intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE},
+ * {@link #ACTION_PROVISION_MANAGED_DEVICE} or {@link #ACTION_PROVISION_MANAGED_USER}.
+ *
+ * @hide
+ */
+ public static final String EXTRA_PROVISIONING_SKIP_USER_SETUP =
+ "android.app.extra.PROVISIONING_SKIP_USER_SETUP";
+
+ /**
* This MIME type is used for starting the Device Owner provisioning.
*
* <p>During device owner provisioning a device admin app is set as the owner of the device.
@@ -941,6 +956,22 @@
}
/**
+ * Returns true if the Profile Challenge is available to use for the given profile user.
+ *
+ * @hide
+ */
+ public boolean isSeparateProfileChallengeAllowed(int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.isSeparateProfileChallengeAllowed(userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ return false;
+ }
+
+ /**
* Constant for {@link #setPasswordQuality}: the policy has no requirements
* for the password. Note that quality constants are ordered so that higher
* values are more restrictive.
@@ -3540,6 +3571,66 @@
}
/**
+ * Called by a profile owner of a managed profile to set whether contacts search from
+ * the managed profile will be shown in the parent profile, for incoming calls.
+ *
+ * <p>The calling device admin must be a profile owner. If it is not, a
+ * security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param disabled If true contacts search in the managed profile is not displayed.
+ */
+ public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin,
+ boolean disabled) {
+ if (mService != null) {
+ try {
+ mService.setCrossProfileContactsSearchDisabled(admin, disabled);
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ }
+
+ /**
+ * Called by a profile owner of a managed profile to determine whether or not contacts search
+ * has been disabled.
+ *
+ * <p>The calling device admin must be a profile owner. If it is not, a
+ * security exception will be thrown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ */
+ public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getCrossProfileContactsSearchDisabled(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Determine whether or not contacts search has been disabled.
+ *
+ * @param userHandle The user for whom to check the contacts search permission
+ * @hide
+ */
+ public boolean getCrossProfileContactsSearchDisabled(@NonNull UserHandle userHandle) {
+ if (mService != null) {
+ try {
+ return mService
+ .getCrossProfileContactsSearchDisabledForUser(userHandle.getIdentifier());
+ } catch (RemoteException e) {
+ Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ }
+ }
+ return false;
+ }
+
+ /**
* Start Quick Contact on the managed profile for the user, if the policy allows.
* @hide
*/
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 754cb43..995ce00 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -202,6 +202,9 @@
void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled);
boolean getCrossProfileCallerIdDisabled(in ComponentName who);
boolean getCrossProfileCallerIdDisabledForUser(int userId);
+ void setCrossProfileContactsSearchDisabled(in ComponentName who, boolean disabled);
+ boolean getCrossProfileContactsSearchDisabled(in ComponentName who);
+ boolean getCrossProfileContactsSearchDisabledForUser(int userId);
void startManagedQuickContact(String lookupKey, long contactId, long directoryId, in Intent originalIntent);
void setBluetoothContactSharingDisabled(in ComponentName who, boolean disabled);
@@ -253,4 +256,6 @@
String getShortSupportMessageForUser(in ComponentName admin, int userHandle);
String getLongSupportMessageForUser(in ComponentName admin, int userHandle);
+
+ boolean isSeparateProfileChallengeAllowed(int userHandle);
}
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 0d9e778..b899710 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -64,6 +64,11 @@
*/
public static final int BACKOFF_POLICY_EXPONENTIAL = 1;
+ /* Minimum interval for a periodic job, in milliseconds. */
+ public static final long MIN_PERIOD_MILLIS = 60 * 60 * 1000L; // 60 minutes
+ /* Minimum flex for a periodic job, in milliseconds. */
+ public static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes
+
/**
* Default type of backoff.
* @hide
@@ -83,6 +88,7 @@
private final boolean isPeriodic;
private final boolean isPersisted;
private final long intervalMillis;
+ private final long flexMillis;
private final long initialBackoffMillis;
private final int backoffPolicy;
@@ -165,7 +171,17 @@
* job does not recur periodically.
*/
public long getIntervalMillis() {
- return intervalMillis;
+ return intervalMillis >= MIN_PERIOD_MILLIS ? intervalMillis : MIN_PERIOD_MILLIS;
+ }
+
+ /**
+ * Flex time for this job. Only valid if this is a periodic job.
+ */
+ public long getFlexMillis() {
+ long interval = getIntervalMillis();
+ long percentClamp = 5 * interval / 100;
+ long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, MIN_FLEX_MILLIS));
+ return clampedFlex <= interval ? clampedFlex : interval;
}
/**
@@ -216,6 +232,7 @@
isPeriodic = in.readInt() == 1;
isPersisted = in.readInt() == 1;
intervalMillis = in.readLong();
+ flexMillis = in.readLong();
initialBackoffMillis = in.readLong();
backoffPolicy = in.readInt();
hasEarlyConstraint = in.readInt() == 1;
@@ -234,6 +251,7 @@
isPeriodic = b.mIsPeriodic;
isPersisted = b.mIsPersisted;
intervalMillis = b.mIntervalMillis;
+ flexMillis = b.mFlexMillis;
initialBackoffMillis = b.mInitialBackoffMillis;
backoffPolicy = b.mBackoffPolicy;
hasEarlyConstraint = b.mHasEarlyConstraint;
@@ -258,6 +276,7 @@
out.writeInt(isPeriodic ? 1 : 0);
out.writeInt(isPersisted ? 1 : 0);
out.writeLong(intervalMillis);
+ out.writeLong(flexMillis);
out.writeLong(initialBackoffMillis);
out.writeInt(backoffPolicy);
out.writeInt(hasEarlyConstraint ? 1 : 0);
@@ -299,6 +318,7 @@
private boolean mHasEarlyConstraint;
private boolean mHasLateConstraint;
private long mIntervalMillis;
+ private long mFlexMillis;
// Back-off parameters.
private long mInitialBackoffMillis = DEFAULT_INITIAL_BACKOFF_MILLIS;
private int mBackoffPolicy = DEFAULT_BACKOFF_POLICY;
@@ -373,8 +393,21 @@
* @param intervalMillis Millisecond interval for which this job will repeat.
*/
public Builder setPeriodic(long intervalMillis) {
+ return setPeriodic(intervalMillis, intervalMillis);
+ }
+
+ /**
+ * Specify that this job should recur with the provided interval and flex. The job can
+ * execute at any time in a window of flex length at the end of the period.
+ * @param intervalMillis Millisecond interval for which this job will repeat.
+ * @param flexMillis Millisecond flex for this job. Flex is clamped to be at least
+ * {@link #MIN_FLEX_MILLIS} or 5 percent of the period, whichever is
+ * higher.
+ */
+ public Builder setPeriodic(long intervalMillis, long flexMillis) {
mIsPeriodic = true;
mIntervalMillis = intervalMillis;
+ mFlexMillis = flexMillis;
mHasEarlyConstraint = mHasLateConstraint = true;
return this;
}
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index ef08eb9..5f97c9e 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -121,12 +121,12 @@
*/
public static class Bucket {
/**
- * Combined usage across all other states.
+ * Combined usage across all states.
*/
public static final int STATE_ALL = -1;
/**
- * Usage not accounted in any other states.
+ * Usage not accounted for in any other state.
*/
public static final int STATE_DEFAULT = 0x1;
@@ -150,8 +150,40 @@
*/
public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
+ /**
+ * Combined usage across all metering states.
+ */
+ public static final int METERING_ALL = -1;
+
+ /**
+ * Usage not accounted for in any other metering state.
+ */
+ public static final int METERING_DEFAULT = 0x1;
+
+ /**
+ * Metered usage.
+ */
+ public static final int METERING_METERED = 0x2;
+
+ /**
+ * Combined usage across all roaming states.
+ */
+ public static final int ROAMING_ALL = -1;
+
+ /**
+ * Usage not accounted for in any other roaming state.
+ */
+ public static final int ROAMING_DEFAULT = 0x1;
+
+ /**
+ * Roaming usage.
+ */
+ public static final int ROAMING_ROAMING = 0x2;
+
private int mUid;
private int mState;
+ private int mMetering;
+ private int mRoaming;
private long mBeginTimeStamp;
private long mEndTimeStamp;
private long mRxBytes;
@@ -206,6 +238,30 @@
}
/**
+ * Metering state. One of the following values:<p/>
+ * <ul>
+ * <li>{@link #METERING_ALL}</li>
+ * <li>{@link #METERING_DEFAULT}</li>
+ * <li>{@link #METERING_METERED}</li>
+ * </ul>
+ */
+ public int getMetering() {
+ return mMetering;
+ }
+
+ /**
+ * Roaming state. One of the following values:<p/>
+ * <ul>
+ * <li>{@link #ROAMING_ALL}</li>
+ * <li>{@link #ROAMING_DEFAULT}</li>
+ * <li>{@link #ROAMING_ROAMING}</li>
+ * </ul>
+ */
+ public int getRoaming() {
+ return mRoaming;
+ }
+
+ /**
* Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @return Start of interval.
@@ -398,6 +454,9 @@
private void fillBucketFromSummaryEntry(Bucket bucketOut) {
bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
+ // TODO: Implement metering/roaming tracking.
+ bucketOut.mMetering = Bucket.METERING_ALL;
+ bucketOut.mRoaming = Bucket.ROAMING_ALL;
bucketOut.mBeginTimeStamp = mStartTimeStamp;
bucketOut.mEndTimeStamp = mEndTimeStamp;
bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes;
@@ -444,6 +503,8 @@
mRecycledHistoryEntry);
bucketOut.mUid = Bucket.convertUid(getUid());
bucketOut.mState = Bucket.STATE_ALL;
+ bucketOut.mMetering = Bucket.METERING_ALL;
+ bucketOut.mRoaming = Bucket.ROAMING_ALL;
bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
mRecycledHistoryEntry.bucketDuration;
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 9221fbb..4135487 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -148,7 +148,8 @@
return null;
}
- if ("com.google.android.gms".equals(mPackageName)) {
+ if ("com.google.android.gms".equals(mPackageName)
+ || "com.google.android.syncadapters.contacts".equals(mPackageName)) {
// They're casting to a concrete subclass, sigh
return cursor;
} else {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a6036bb..e9d83eb 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -329,6 +329,15 @@
public static final int BIND_NOT_VISIBLE = 0x40000000;
/**
+ * Flag for {@link #bindService}: The service being bound is an
+ * {@link android.R.attr#isolatedProcess isolated},
+ * {@link android.R.attr#externalService external} service. This binds the service into the
+ * calling application's package, rather than the package in which the service is declared.
+ * @hide
+ */
+ public static final int BIND_EXTERNAL_SERVICE = 0x80000000;
+
+ /**
* Returns an AssetManager instance for the application's package.
* <p>
* <strong>Note:</strong> Implementations of this method should return
@@ -4021,13 +4030,16 @@
* Because device-encrypted data is available before user authentication,
* you should carefully consider what data you store using this Context.
* <p>
+ * If the underlying device does not have the ability to store
+ * device-encrypted and credential-encrypted data using different keys, then
+ * both storage areas will become available at the same time. They remain
+ * two distinct storage areas, and only the window of availability changes.
+ * <p>
* Each call to this method returns a new instance of a Context object;
* Context objects are not shared, however common state (ClassLoader, other
* Resources for the same configuration) may be so the Context itself can be
* fairly lightweight.
*
- * @return new Context or {@code null} if device-encrypted storage is not
- * supported or available on this device.
* @see #isDeviceEncryptedStorage()
*/
public abstract Context createDeviceEncryptedStorageContext();
@@ -4041,6 +4053,11 @@
* <em>only after</em> the user has entered their credentials (such as a
* lock pattern or PIN).
* <p>
+ * If the underlying device does not have the ability to store
+ * device-encrypted and credential-encrypted data using different keys, then
+ * both storage areas will become available at the same time. They remain
+ * two distinct storage areas, and only the window of availability changes.
+ * <p>
* Each call to this method returns a new instance of a Context object;
* Context objects are not shared, however common state (ClassLoader, other
* Resources for the same configuration) may be so the Context itself can be
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 35cd2be..519e5a0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3034,6 +3034,24 @@
public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
/**
+ * Broadcast Action: Sent when media resource is granted.
+ * <p>
+ * {@link #EXTRA_PACKAGES} specifies the packages on the process holding the media resource
+ * granted.
+ * </p>
+ * <p class="note">
+ * This is a protected intent that can only be sent by the system.
+ * </p>
+ * <p class="note">
+ * This requires the RECEIVE_MEDIA_RESOURCE_USAGE permission.
+ * </p>
+ *
+ * @hide
+ */
+ public static final String ACTION_MEDIA_RESOURCE_GRANTED =
+ "android.intent.action.MEDIA_RESOURCE_GRANTED";
+
+ /**
* Activity Action: Allow the user to select and return one or more existing
* documents. When invoked, the system will display the various
* {@link DocumentsProvider} instances installed on the device, letting the
@@ -4077,6 +4095,34 @@
* Optional boolean extra indicating whether quiet mode has been switched on or off.
*/
public static final String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
+
+ /**
+ * Used as an int extra field in {@link android.content.Intent#ACTION_MEDIA_RESOURCE_GRANTED}
+ * intents to specify the resource type granted. Possible values are
+ * {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC} or
+ * {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC}.
+ *
+ * @hide
+ */
+ public static final String EXTRA_MEDIA_RESOURCE_TYPE =
+ "android.intent.extra.MEDIA_RESOURCE_TYPE";
+
+ /**
+ * Used as an int value for {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE}
+ * to represent that a video codec is allowed to use.
+ *
+ * @hide
+ */
+ public static final int EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC = 0;
+
+ /**
+ * Used as an int value for {@link android.content.Intent#EXTRA_MEDIA_RESOURCE_TYPE}
+ * to represent that a audio codec is allowed to use.
+ *
+ * @hide
+ */
+ public static final int EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC = 1;
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 39f59554..f611991 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -64,10 +64,8 @@
void checkPackageStartable(String packageName, int userId);
boolean isPackageAvailable(String packageName, int userId);
PackageInfo getPackageInfo(String packageName, int flags, int userId);
- int getPackageUid(String packageName, int userId);
- int getPackageUidEtc(String packageName, int flags, int userId);
- int[] getPackageGids(String packageName, int userId);
- int[] getPackageGidsEtc(String packageName, int flags, int userId);
+ int getPackageUid(String packageName, int flags, int userId);
+ int[] getPackageGids(String packageName, int flags, int userId);
String[] currentToCanonicalPackageNames(in String[] names);
String[] canonicalToCurrentPackageNames(in String[] names);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index cc00308..5113e19 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -110,21 +110,22 @@
/** @hide */
@IntDef(flag = true, value = {
GET_ACTIVITIES,
- GET_RECEIVERS,
- GET_SERVICES,
- GET_PROVIDERS,
+ GET_CONFIGURATIONS,
+ GET_GIDS,
GET_INSTRUMENTATION,
GET_INTENT_FILTERS,
- GET_SIGNATURES,
GET_META_DATA,
- GET_GIDS,
- GET_SHARED_LIBRARY_FILES,
- GET_URI_PERMISSION_PATTERNS,
GET_PERMISSIONS,
- GET_CONFIGURATIONS,
+ GET_PROVIDERS,
+ GET_RECEIVERS,
+ GET_SERVICES,
+ GET_SHARED_LIBRARY_FILES,
+ GET_SIGNATURES,
+ GET_URI_PERMISSION_PATTERNS,
MATCH_UNINSTALLED_PACKAGES,
MATCH_DISABLED_COMPONENTS,
MATCH_DISABLED_UNTIL_USED_COMPONENTS,
+ MATCH_SYSTEM_ONLY,
MATCH_DEBUG_TRIAGED_MISSING,
})
@Retention(RetentionPolicy.SOURCE)
@@ -145,16 +146,16 @@
@IntDef(flag = true, value = {
GET_META_DATA,
GET_SHARED_LIBRARY_FILES,
- MATCH_UNINSTALLED_PACKAGES,
+ MATCH_ALL,
+ MATCH_DEBUG_TRIAGED_MISSING,
+ MATCH_DEFAULT_ONLY,
MATCH_DISABLED_COMPONENTS,
MATCH_DISABLED_UNTIL_USED_COMPONENTS,
- MATCH_ALL,
- MATCH_DEFAULT_ONLY,
MATCH_ENCRYPTION_AWARE,
MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
MATCH_ENCRYPTION_UNAWARE,
MATCH_SYSTEM_ONLY,
- MATCH_DEBUG_TRIAGED_MISSING,
+ MATCH_UNINSTALLED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ComponentInfoFlags {}
@@ -162,18 +163,18 @@
/** @hide */
@IntDef(flag = true, value = {
GET_META_DATA,
- GET_SHARED_LIBRARY_FILES,
GET_RESOLVED_FILTER,
- MATCH_UNINSTALLED_PACKAGES,
+ GET_SHARED_LIBRARY_FILES,
+ MATCH_ALL,
+ MATCH_DEBUG_TRIAGED_MISSING,
MATCH_DISABLED_COMPONENTS,
MATCH_DISABLED_UNTIL_USED_COMPONENTS,
- MATCH_ALL,
MATCH_DEFAULT_ONLY,
MATCH_ENCRYPTION_AWARE,
MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
MATCH_ENCRYPTION_UNAWARE,
MATCH_SYSTEM_ONLY,
- MATCH_DEBUG_TRIAGED_MISSING,
+ MATCH_UNINSTALLED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ResolveInfoFlags {}
@@ -403,16 +404,17 @@
public static final int MATCH_DEBUG_TRIAGED_MISSING = 0x10000000;
/**
- * Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
- * when resolving an intent that matches the {@link CrossProfileIntentFilter}, the current
- * profile will be skipped.
- * Only activities in the target user can respond to the intent.
+ * Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when
+ * resolving an intent that matches the {@code CrossProfileIntentFilter},
+ * the current profile will be skipped. Only activities in the target user
+ * can respond to the intent.
+ *
* @hide
*/
public static final int SKIP_CURRENT_PROFILE = 0x00000002;
/**
- * Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
+ * Flag for {@link #addCrossProfileIntentFilter}: if this flag is set:
* activities in the other profiles can respond to the intent only if no activity with
* non-negative priority in current profile can respond to the intent.
* @hide
@@ -519,17 +521,37 @@
*/
public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;
+ /** @hide */
+ @IntDef(flag = true, value = {
+ INSTALL_FORWARD_LOCK,
+ INSTALL_REPLACE_EXISTING,
+ INSTALL_ALLOW_TEST,
+ INSTALL_EXTERNAL,
+ INSTALL_INTERNAL,
+ INSTALL_FROM_ADB,
+ INSTALL_ALL_USERS,
+ INSTALL_ALLOW_DOWNGRADE,
+ INSTALL_GRANT_RUNTIME_PERMISSIONS,
+ INSTALL_FORCE_VOLUME_UUID,
+ INSTALL_FORCE_PERMISSION_PROMPT,
+ INSTALL_EPHEMERAL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InstallFlags {}
+
/**
- * Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
- * indicate that this package should be installed as forward locked, i.e. only the app itself
- * should have access to its code and non-resource assets.
+ * Flag parameter for {@link #installPackage} to indicate that this package
+ * should be installed as forward locked, i.e. only the app itself should
+ * have access to its code and non-resource assets.
+ *
* @hide
*/
public static final int INSTALL_FORWARD_LOCK = 0x00000001;
/**
- * Flag parameter for {@link #installPackage} to indicate that you want to replace an already
- * installed package, if one exists.
+ * Flag parameter for {@link #installPackage} to indicate that you want to
+ * replace an already installed package, if one exists.
+ *
* @hide
*/
public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
@@ -622,170 +644,181 @@
public static final int DONT_KILL_APP = 0x00000001;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} on success.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} on success.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_SUCCEEDED = 1;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package is
- * already installed.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the package is already installed.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package archive
- * file is invalid.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the package archive file is invalid.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_INVALID_APK = -2;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the URI passed in
- * is invalid.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the URI passed in is invalid.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_INVALID_URI = -3;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if the package manager
- * service found that the device didn't have enough storage space to install the app.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the package manager service found that
+ * the device didn't have enough storage space to install the app.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if a
- * package is already installed with the same name.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if a package is already installed with
+ * the same name.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the requested shared user does not exist.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the requested shared user does not
+ * exist.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_NO_SHARED_USER = -6;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * a previously installed package of the same name has a different signature
- * than the new package (and the old package's data was not removed).
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if a previously installed package of the
+ * same name has a different signature than the new package (and the old
+ * package's data was not removed).
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package is requested a shared user which is already installed on the
- * device and does not have matching signature.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package is requested a shared
+ * user which is already installed on the device and does not have matching
+ * signature.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package uses a shared library that is not available.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package uses a shared library
+ * that is not available.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package uses a shared library that is not available.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package uses a shared library
+ * that is not available.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package failed while optimizing and validating its dex files,
- * either because there was not enough storage or the validation failed.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package failed while
+ * optimizing and validating its dex files, either because there was not
+ * enough storage or the validation failed.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_DEXOPT = -11;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package failed because the current SDK version is older than
- * that required by the package.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package failed because the
+ * current SDK version is older than that required by the package.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_OLDER_SDK = -12;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package failed because it contains a content provider with the
- * same authority as a provider already installed in the system.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package failed because it
+ * contains a content provider with the same authority as a provider already
+ * installed in the system.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package failed because the current SDK version is newer than
- * that required by the package.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package failed because the
+ * current SDK version is newer than that required by the package.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_NEWER_SDK = -14;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package failed because it has specified that it is a test-only
- * package and the caller has not supplied the {@link #INSTALL_ALLOW_TEST}
- * flag.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package failed because it has
+ * specified that it is a test-only package and the caller has not supplied
+ * the {@link #INSTALL_ALLOW_TEST} flag.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_TEST_ONLY = -15;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the package being installed contains native code, but none that is
- * compatible with the device's CPU_ABI.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the package being installed contains
+ * native code, but none that is compatible with the device's CPU_ABI.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package uses a feature that is not available.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package uses a feature that is
+ * not available.
+ *
* @hide
*/
@SystemApi
@@ -793,217 +826,234 @@
// ------ Errors related to sdcard
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * a secure container mount point couldn't be accessed on external media.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if a secure container mount point
+ * couldn't be accessed on external media.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_CONTAINER_ERROR = -18;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package couldn't be installed in the specified install
- * location.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package couldn't be installed
+ * in the specified install location.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package couldn't be installed in the specified install
- * location because the media is not available.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package couldn't be installed
+ * in the specified install location because the media is not available.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package couldn't be installed because the verification timed out.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package couldn't be installed
+ * because the verification timed out.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package couldn't be installed because the verification did not succeed.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package couldn't be installed
+ * because the verification did not succeed.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the package changed from what the calling program expected.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the package changed from what the
+ * calling program expected.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package is assigned a different UID than it previously held.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package is assigned a
+ * different UID than it previously held.
+ *
* @hide
*/
public static final int INSTALL_FAILED_UID_CHANGED = -24;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the new package has an older version code than the currently installed package.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package has an older version
+ * code than the currently installed package.
+ *
* @hide
*/
public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25;
/**
- * Installation return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
- * the old package has target SDK high enough to support runtime permission and
- * the new package has target SDK low enough to not support runtime permissions.
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the old package has target SDK high
+ * enough to support runtime permission and the new package has target SDK
+ * low enough to not support runtime permissions.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE = -26;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser was given a path that is not a file, or does not end with the expected
- * '.apk' extension.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser was given a path that is
+ * not a file, or does not end with the expected '.apk' extension.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_NOT_APK = -100;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser was unable to retrieve the AndroidManifest.xml file.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser was unable to retrieve the
+ * AndroidManifest.xml file.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered an unexpected exception.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser encountered an unexpected
+ * exception.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser did not find any certificates in the .apk.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser did not find any
+ * certificates in the .apk.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser found inconsistent certificates on the files in the .apk.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser found inconsistent
+ * certificates on the files in the .apk.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered a CertificateEncodingException in one of the
- * files in the .apk.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser encountered a
+ * CertificateEncodingException in one of the files in the .apk.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered a bad or missing package name in the manifest.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser encountered a bad or
+ * missing package name in the manifest.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered a bad shared user id name in the manifest.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser encountered a bad shared
+ * user id name in the manifest.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser encountered some structural problem in the manifest.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser encountered some structural
+ * problem in the manifest.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108;
/**
- * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the parser did not find any actionable tags (instrumentation or application)
- * in the manifest.
+ * Installation parse return code: this is passed to the
+ * {@link IPackageInstallObserver} if the parser did not find any actionable
+ * tags (instrumentation or application) in the manifest.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;
/**
- * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the system failed to install the package because of system issues.
+ * Installation failed return code: this is passed to the
+ * {@link IPackageInstallObserver} if the system failed to install the
+ * package because of system issues.
+ *
* @hide
*/
@SystemApi
public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
/**
- * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the system failed to install the package because the user is restricted from installing
- * apps.
+ * Installation failed return code: this is passed to the
+ * {@link IPackageInstallObserver} if the system failed to install the
+ * package because the user is restricted from installing apps.
+ *
* @hide
*/
public static final int INSTALL_FAILED_USER_RESTRICTED = -111;
/**
- * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the system failed to install the package because it is attempting to define a
- * permission that is already defined by some existing package.
+ * Installation failed return code: this is passed to the
+ * {@link IPackageInstallObserver} if the system failed to install the
+ * package because it is attempting to define a permission that is already
+ * defined by some existing package.
+ * <p>
+ * The package name of the app which has already defined the permission is
+ * passed to a {@link PackageInstallObserver}, if any, as the
+ * {@link #EXTRA_FAILURE_EXISTING_PACKAGE} string extra; and the name of the
+ * permission being redefined is passed in the
+ * {@link #EXTRA_FAILURE_EXISTING_PERMISSION} string extra.
*
- * <p>The package name of the app which has already defined the permission is passed to
- * a {@link PackageInstallObserver}, if any, as the {@link #EXTRA_EXISTING_PACKAGE}
- * string extra; and the name of the permission being redefined is passed in the
- * {@link #EXTRA_EXISTING_PERMISSION} string extra.
* @hide
*/
public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112;
/**
- * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
- * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
- * if the system failed to install the package because its packaged native code did not
- * match any of the ABIs supported by the system.
+ * Installation failed return code: this is passed to the
+ * {@link IPackageInstallObserver} if the system failed to install the
+ * package because its packaged native code did not match any of the ABIs
+ * supported by the system.
*
* @hide
*/
@@ -1029,6 +1079,15 @@
*/
public static final int INSTALL_FAILED_EPHEMERAL_INVALID = -116;
+ /** @hide */
+ @IntDef(flag = true, value = {
+ DELETE_KEEP_DATA,
+ DELETE_ALL_USERS,
+ DELETE_SYSTEM_APP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeleteFlags {}
+
/**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.
@@ -1058,8 +1117,8 @@
/**
* Return code for when package deletion succeeds. This is passed to the
- * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
- * succeeded in deleting the package.
+ * {@link IPackageDeleteObserver} if the system succeeded in deleting the
+ * package.
*
* @hide
*/
@@ -1067,8 +1126,8 @@
/**
* Deletion failed return code: this is passed to the
- * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
- * failed to delete the package for an unspecified reason.
+ * {@link IPackageDeleteObserver} if the system failed to delete the package
+ * for an unspecified reason.
*
* @hide
*/
@@ -1076,9 +1135,8 @@
/**
* Deletion failed return code: this is passed to the
- * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
- * failed to delete the package because it is the active DevicePolicy
- * manager.
+ * {@link IPackageDeleteObserver} if the system failed to delete the package
+ * because it is the active DevicePolicy manager.
*
* @hide
*/
@@ -1086,8 +1144,8 @@
/**
* Deletion failed return code: this is passed to the
- * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
- * failed to delete the package since the user is restricted.
+ * {@link IPackageDeleteObserver} if the system failed to delete the package
+ * since the user is restricted.
*
* @hide
*/
@@ -1095,9 +1153,9 @@
/**
* Deletion failed return code: this is passed to the
- * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
- * failed to delete the package because a profile
- * or device owner has marked the package as uninstallable.
+ * {@link IPackageDeleteObserver} if the system failed to delete the package
+ * because a profile or device owner has marked the package as
+ * uninstallable.
*
* @hide
*/
@@ -1107,8 +1165,7 @@
public static final int DELETE_FAILED_ABORTED = -5;
/**
- * Return code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)} when the
+ * Return code that is passed to the {@link IPackageMoveObserver} when the
* package has been successfully moved by the system.
*
* @hide
@@ -1116,59 +1173,57 @@
public static final int MOVE_SUCCEEDED = -100;
/**
- * Error code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
- * when the package hasn't been successfully moved by the system
- * because of insufficient memory on specified media.
+ * Error code that is passed to the {@link IPackageMoveObserver} when the
+ * package hasn't been successfully moved by the system because of
+ * insufficient memory on specified media.
+ *
* @hide
*/
public static final int MOVE_FAILED_INSUFFICIENT_STORAGE = -1;
/**
- * Error code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
- * if the specified package doesn't exist.
+ * Error code that is passed to the {@link IPackageMoveObserver} if the
+ * specified package doesn't exist.
+ *
* @hide
*/
public static final int MOVE_FAILED_DOESNT_EXIST = -2;
/**
- * Error code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
- * if the specified package cannot be moved since its a system package.
+ * Error code that is passed to the {@link IPackageMoveObserver} if the
+ * specified package cannot be moved since its a system package.
+ *
* @hide
*/
public static final int MOVE_FAILED_SYSTEM_PACKAGE = -3;
/**
- * Error code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
- * if the specified package cannot be moved since its forward locked.
+ * Error code that is passed to the {@link IPackageMoveObserver} if the
+ * specified package cannot be moved since its forward locked.
+ *
* @hide
*/
public static final int MOVE_FAILED_FORWARD_LOCKED = -4;
/**
- * Error code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
- * if the specified package cannot be moved to the specified location.
+ * Error code that is passed to the {@link IPackageMoveObserver} if the
+ * specified package cannot be moved to the specified location.
+ *
* @hide
*/
public static final int MOVE_FAILED_INVALID_LOCATION = -5;
/**
- * Error code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
- * if the specified package cannot be moved to the specified location.
+ * Error code that is passed to the {@link IPackageMoveObserver} if the
+ * specified package cannot be moved to the specified location.
+ *
* @hide
*/
public static final int MOVE_FAILED_INTERNAL_ERROR = -6;
/**
- * Error code that is passed to the {@link IPackageMoveObserver} by
- * {@link #movePackage(android.net.Uri, IPackageMoveObserver)} if the
- * specified package already has an operation pending in the
- * {@link PackageHandler} queue.
+ * Error code that is passed to the {@link IPackageMoveObserver} if the
+ * specified package already has an operation pending in the queue.
*
* @hide
*/
@@ -1244,28 +1299,31 @@
public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED = 0;
/**
- * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
- * to indicate that the User will always be prompted the Intent Disambiguation Dialog if there
- * are two or more Intent resolved for the IntentFilter's domain(s).
+ * Used as the {@code status} argument for
+ * {@link #updateIntentVerificationStatusAsUser} to indicate that the User
+ * will always be prompted the Intent Disambiguation Dialog if there are two
+ * or more Intent resolved for the IntentFilter's domain(s).
*
* @hide
*/
public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK = 1;
/**
- * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
- * to indicate that the User will never be prompted the Intent Disambiguation Dialog if there
- * are two or more resolution of the Intent. The default App for the domain(s) specified in the
- * IntentFilter will also ALWAYS be used.
+ * Used as the {@code status} argument for
+ * {@link #updateIntentVerificationStatusAsUser} to indicate that the User
+ * will never be prompted the Intent Disambiguation Dialog if there are two
+ * or more resolution of the Intent. The default App for the domain(s)
+ * specified in the IntentFilter will also ALWAYS be used.
*
* @hide
*/
public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS = 2;
/**
- * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
- * to indicate that the User may be prompted the Intent Disambiguation Dialog if there
- * are two or more Intent resolved. The default App for the domain(s) specified in the
+ * Used as the {@code status} argument for
+ * {@link #updateIntentVerificationStatusAsUser} to indicate that the User
+ * may be prompted the Intent Disambiguation Dialog if there are two or more
+ * Intent resolved. The default App for the domain(s) specified in the
* IntentFilter will also NEVER be presented to the User.
*
* @hide
@@ -1273,12 +1331,13 @@
public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER = 3;
/**
- * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
- * to indicate that this app should always be considered as an ambiguous candidate for
- * handling the matching Intent even if there are other candidate apps in the "always"
- * state. Put another way: if there are any 'always ask' apps in a set of more than
- * one candidate app, then a disambiguation is *always* presented even if there is
- * another candidate app with the 'always' state.
+ * Used as the {@code status} argument for
+ * {@link #updateIntentVerificationStatusAsUser} to indicate that this app
+ * should always be considered as an ambiguous candidate for handling the
+ * matching Intent even if there are other candidate apps in the "always"
+ * state. Put another way: if there are any 'always ask' apps in a set of
+ * more than one candidate app, then a disambiguation is *always* presented
+ * even if there is another candidate app with the 'always' state.
*
* @hide
*/
@@ -2061,9 +2120,9 @@
= "android.content.pm.extra.VERIFICATION_VERSION_CODE";
/**
- * Extra field name for the ID of a intent filter pending verification. Passed to
- * an intent filter verifier and is used to call back to
- * {@link PackageManager#verifyIntentFilter(int, int)}
+ * Extra field name for the ID of a intent filter pending verification.
+ * Passed to an intent filter verifier and is used to call back to
+ * {@link #verifyIntentFilter}
*
* @hide
*/
@@ -2233,16 +2292,21 @@
* installed on the system.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of the
- * desired package.
+ * desired package.
* @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES}, {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS}, {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES}, {@link #GET_UNINSTALLED_PACKAGES} to
- * modify the data returned.
+ * {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+ * {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+ * {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+ * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+ * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+ * {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
+ *
* @return A PackageInfo object containing information about the
- * package. If flag GET_UNINSTALLED_PACKAGES is set and if the
+ * package. If flag {@code MATCH_UNINSTALLED_PACKAGES} is set and if the
* package is not found in the list of installed applications, the
* package information is retrieved from the list of uninstalled
* applications (which includes installed applications as well as
@@ -2251,15 +2315,21 @@
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
* @see #GET_ACTIVITIES
- * @see #GET_GIDS
* @see #GET_CONFIGURATIONS
+ * @see #GET_GIDS
* @see #GET_INSTRUMENTATION
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
+ * @see #GET_SHARED_LIBRARY_FILES
* @see #GET_SIGNATURES
- * @see #GET_UNINSTALLED_PACKAGES
+ * @see #GET_URI_PERMISSION_PATTERNS
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags)
throws NameNotFoundException;
@@ -2270,17 +2340,22 @@
* installed on the system.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of the
- * desired package.
+ * desired package.
* @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES}, {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS}, {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES}, {@link #GET_UNINSTALLED_PACKAGES} to
- * modify the data returned.
+ * {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+ * {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+ * {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+ * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+ * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+ * {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
* @param userId The user id.
+ *
* @return A PackageInfo object containing information about the
- * package. If flag GET_UNINSTALLED_PACKAGES is set and if the
+ * package. If flag {@code MATCH_UNINSTALLED_PACKAGES} is set and if the
* package is not found in the list of installed applications, the
* package information is retrieved from the list of uninstalled
* applications (which includes installed applications as well as
@@ -2289,15 +2364,21 @@
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
* @see #GET_ACTIVITIES
- * @see #GET_GIDS
* @see #GET_CONFIGURATIONS
+ * @see #GET_GIDS
* @see #GET_INSTRUMENTATION
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
+ * @see #GET_SHARED_LIBRARY_FILES
* @see #GET_SIGNATURES
- * @see #GET_UNINSTALLED_PACKAGES
+ * @see #GET_URI_PERMISSION_PATTERNS
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
@RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
public abstract PackageInfo getPackageInfoAsUser(String packageName,
@@ -2356,7 +2437,7 @@
* to a package.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of the
- * desired package.
+ * desired package.
* @return Returns an int array of the assigned gids, or null if there are
* none.
* @throws NameNotFoundException if a package with the given name cannot be
@@ -2423,14 +2504,16 @@
* Retrieve all of the information we know about a particular permission.
*
* @param name The fully qualified name (i.e. com.google.permission.LOGIN)
- * of the permission you are interested in.
+ * of the permission you are interested in.
* @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permission.
+ * retrieve any meta-data associated with the permission.
*
* @return Returns a {@link PermissionInfo} containing information about the
* permission.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
+ *
+ * @see #GET_META_DATA
*/
public abstract PermissionInfo getPermissionInfo(String name, @PermissionInfoFlags int flags)
throws NameNotFoundException;
@@ -2439,15 +2522,17 @@
* Query for all of the permissions associated with a particular group.
*
* @param group The fully qualified name (i.e. com.google.permission.LOGIN)
- * of the permission group you are interested in. Use null to
- * find all of the permissions not associated with a group.
+ * of the permission group you are interested in. Use null to
+ * find all of the permissions not associated with a group.
* @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permissions.
+ * retrieve any meta-data associated with the permissions.
*
* @return Returns a list of {@link PermissionInfo} containing information
- * about all of the permissions in the given group.
+ * about all of the permissions in the given group.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
+ *
+ * @see #GET_META_DATA
*/
public abstract List<PermissionInfo> queryPermissionsByGroup(String group,
@PermissionInfoFlags int flags) throws NameNotFoundException;
@@ -2457,14 +2542,16 @@
* permissions.
*
* @param name The fully qualified name (i.e. com.google.permission_group.APPS)
- * of the permission you are interested in.
+ * of the permission you are interested in.
* @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permission group.
+ * retrieve any meta-data associated with the permission group.
*
* @return Returns a {@link PermissionGroupInfo} containing information
- * about the permission.
+ * about the permission.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
+ *
+ * @see #GET_META_DATA
*/
public abstract PermissionGroupInfo getPermissionGroupInfo(String name,
@PermissionGroupInfoFlags int flags) throws NameNotFoundException;
@@ -2473,10 +2560,12 @@
* Retrieve all of the known permission groups in the system.
*
* @param flags Additional option flags. Use {@link #GET_META_DATA} to
- * retrieve any meta-data associated with the permission group.
+ * retrieve any meta-data associated with the permission group.
*
* @return Returns a list of {@link PermissionGroupInfo} containing
- * information about all of the known permission groups.
+ * information about all of the known permission groups.
+ *
+ * @see #GET_META_DATA
*/
public abstract List<PermissionGroupInfo> getAllPermissionGroups(
@PermissionGroupInfoFlags int flags);
@@ -2486,30 +2575,34 @@
* package/application.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of an
- * application.
+ * application.
* @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return {@link ApplicationInfo} Returns ApplicationInfo object containing
- * information about the package.
- * If flag GET_UNINSTALLED_PACKAGES is set and if the package is not
- * found in the list of installed applications,
- * the application information is retrieved from the
- * list of uninstalled applications(which includes
- * installed applications as well as applications
- * with data directory ie applications which had been
+ * @return An {@link ApplicationInfo} containing information about the
+ * package. If flag {@code MATCH_UNINSTALLED_PACKAGES} is set and if the
+ * package is not found in the list of installed applications, the
+ * application information is retrieved from the list of uninstalled
+ * applications (which includes installed applications as well as
+ * applications with data directory i.e. applications which had been
* deleted with {@code DONT_DELETE_DATA} flag set).
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
- * @see #GET_UNINSTALLED_PACKAGES
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ApplicationInfo getApplicationInfo(String packageName,
@ApplicationInfoFlags int flags) throws NameNotFoundException;
+ /** {@hide} */
+ public abstract ApplicationInfo getApplicationInfoAsUser(String packageName,
+ @ApplicationInfoFlags int flags, @UserIdInt int userId) throws NameNotFoundException;
+
/**
* Retrieve all of the information we know about a particular activity
* class.
@@ -2518,16 +2611,30 @@
* com.google.apps.contacts/com.google.apps.contacts.ContactsList) of an Activity
* class.
* @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * to modify the data (in ApplicationInfo) returned.
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
+ * {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return {@link ActivityInfo} containing information about the activity.
+ * @return An {@link ActivityInfo} containing information about the activity.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*
- * @see #GET_INTENT_FILTERS
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DEBUG_TRIAGED_MISSING
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ActivityInfo getActivityInfo(ComponentName component,
@ComponentInfoFlags int flags) throws NameNotFoundException;
@@ -2539,17 +2646,31 @@
* @param component The full component name (i.e.
* com.google.apps.calendar/com.google.apps.calendar.CalendarAlarm) of a Receiver
* class.
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * to modify the data returned.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
+ * {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return {@link ActivityInfo} containing information about the receiver.
+ * @return An {@link ActivityInfo} containing information about the receiver.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*
- * @see #GET_INTENT_FILTERS
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DEBUG_TRIAGED_MISSING
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ActivityInfo getReceiverInfo(ComponentName component,
@ComponentInfoFlags int flags) throws NameNotFoundException;
@@ -2561,16 +2682,31 @@
* @param component The full component name (i.e.
* com.google.apps.media/com.google.apps.media.BackgroundPlayback) of a Service
* class.
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * to modify the data returned.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
+ * {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return ServiceInfo containing information about the service.
+ * @return A {@link ServiceInfo} object containing information about the service.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DEBUG_TRIAGED_MISSING
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ServiceInfo getServiceInfo(ComponentName component,
@ComponentInfoFlags int flags) throws NameNotFoundException;
@@ -2582,16 +2718,31 @@
* @param component The full component name (i.e.
* com.google.providers.media/com.google.providers.media.MediaProvider) of a
* ContentProvider class.
- * @param flags Additional option flags. Use any combination of
- * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * to modify the data returned.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
+ * {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return ProviderInfo containing information about the service.
+ * @return A {@link ProviderInfo} object containing information about the provider.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DEBUG_TRIAGED_MISSING
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ProviderInfo getProviderInfo(ComponentName component,
@ComponentInfoFlags int flags) throws NameNotFoundException;
@@ -2601,34 +2752,42 @@
* on the device.
*
* @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
+ * {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+ * {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+ * {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+ * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+ * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+ * {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return A List of PackageInfo objects, one for each package that is
- * installed on the device. In the unlikely case of there being no
- * installed packages, an empty list is returned.
- * If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with {@code DONT_DELETE_DATA}
- * (partially installed apps with data directory) will be returned.
+ * @return A List of PackageInfo objects, one for each installed package,
+ * containing information about the package. In the unlikely case
+ * there are no installed packages, an empty list is returned. If
+ * flag {@code MATCH_UNINSTALLED_PACKAGES} is set, the package
+ * information is retrieved from the list of uninstalled
+ * applications (which includes installed applications as well as
+ * applications with data directory i.e. applications which had been
+ * deleted with {@code DONT_DELETE_DATA} flag set).
*
* @see #GET_ACTIVITIES
- * @see #GET_GIDS
* @see #GET_CONFIGURATIONS
+ * @see #GET_GIDS
* @see #GET_INSTRUMENTATION
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
+ * @see #GET_SHARED_LIBRARY_FILES
* @see #GET_SIGNATURES
- * @see #GET_UNINSTALLED_PACKAGES
+ * @see #GET_URI_PERMISSION_PATTERNS
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<PackageInfo> getInstalledPackages(@PackageInfoFlags int flags);
@@ -2637,30 +2796,43 @@
* holding any of the given permissions.
*
* @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
+ * {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+ * {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+ * {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+ * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+ * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+ * {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return Returns a List of PackageInfo objects, one for each installed
- * application that is holding any of the permissions that were provided.
+ * @return A List of PackageInfo objects, one for each installed package
+ * that holds any of the permissions that were provided, containing
+ * information about the package. If no installed packages hold any
+ * of the permissions, an empty list is returned. If flag
+ * {@code MATCH_UNINSTALLED_PACKAGES} is set, the package information
+ * is retrieved from the list of uninstalled applications (which
+ * includes installed applications as well as applications with data
+ * directory i.e. applications which had been deleted with
+ * {@code DONT_DELETE_DATA} flag set).
*
* @see #GET_ACTIVITIES
- * @see #GET_GIDS
* @see #GET_CONFIGURATIONS
+ * @see #GET_GIDS
* @see #GET_INSTRUMENTATION
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
+ * @see #GET_SHARED_LIBRARY_FILES
* @see #GET_SIGNATURES
- * @see #GET_UNINSTALLED_PACKAGES
+ * @see #GET_URI_PERMISSION_PATTERNS
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<PackageInfo> getPackagesHoldingPermissions(
String[] permissions, @PackageInfoFlags int flags);
@@ -2669,36 +2841,45 @@
* Return a List of all packages that are installed on the device, for a specific user.
* Requesting a list of installed packages for another user
* will require the permission INTERACT_ACROSS_USERS_FULL.
+ *
* @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
+ * {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+ * {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+ * {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+ * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+ * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+ * {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
* @param userId The user for whom the installed packages are to be listed
*
- * @return A List of PackageInfo objects, one for each package that is
- * installed on the device. In the unlikely case of there being no
- * installed packages, an empty list is returned.
- * If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with {@code DONT_DELETE_DATA}
- * (partially installed apps with data directory) will be returned.
+ * @return A List of PackageInfo objects, one for each installed package,
+ * containing information about the package. In the unlikely case
+ * there are no installed packages, an empty list is returned. If
+ * flag {@code MATCH_UNINSTALLED_PACKAGES} is set, the package
+ * information is retrieved from the list of uninstalled
+ * applications (which includes installed applications as well as
+ * applications with data directory i.e. applications which had been
+ * deleted with {@code DONT_DELETE_DATA} flag set).
*
* @see #GET_ACTIVITIES
- * @see #GET_GIDS
* @see #GET_CONFIGURATIONS
+ * @see #GET_GIDS
* @see #GET_INSTRUMENTATION
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
+ * @see #GET_SHARED_LIBRARY_FILES
* @see #GET_SIGNATURES
- * @see #GET_UNINSTALLED_PACKAGES
+ * @see #GET_URI_PERMISSION_PATTERNS
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_UNINSTALLED_PACKAGES
*
* @hide
*/
@@ -2992,7 +3173,7 @@
* @return Returns an array of one or more packages assigned to the user
* id, or null if there are no known packages with the given id.
*/
- public abstract String[] getPackagesForUid(int uid);
+ public abstract @Nullable String[] getPackagesForUid(int uid);
/**
* Retrieve the official name associated with a user id. This name is
@@ -3005,7 +3186,7 @@
* @return Returns a unique name for the given user id, or null if the
* user id is not currently assigned.
*/
- public abstract String getNameForUid(int uid);
+ public abstract @Nullable String getNameForUid(int uid);
/**
* Return the user id associated with a shared user name. Multiple
@@ -3031,18 +3212,21 @@
*
* @param flags Additional option flags. Use any combination of
* {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
- * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return Returns a List of ApplicationInfo objects, one for each application that
- * is installed on the device. In the unlikely case of there being
- * no installed applications, an empty list is returned.
- * If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with {@code DONT_DELETE_DATA}
- * (partially installed apps with data directory) will be returned.
+ * @return A List of ApplicationInfo objects, one for each installed application.
+ * In the unlikely case there are no installed packages, an empty list
+ * is returned. If flag {@code MATCH_UNINSTALLED_PACKAGES} is set, the
+ * application information is retrieved from the list of uninstalled
+ * applications (which includes installed applications as well as
+ * applications with data directory i.e. applications which had been
+ * deleted with {@code DONT_DELETE_DATA} flag set).
*
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
- * @see #GET_UNINSTALLED_PACKAGES
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<ApplicationInfo> getInstalledApplications(@ApplicationInfoFlags int flags);
@@ -3074,6 +3258,8 @@
* @see #setEphemeralCookie(byte[])
* @see #getEphemeralCookie()
* @see #getEphemeralCookieMaxSizeBytes()
+ *
+ * @hide
*/
public abstract boolean isEphemeralApplication();
@@ -3086,6 +3272,8 @@
* @see #isEphemeralApplication()
* @see #setEphemeralCookie(byte[])
* @see #getEphemeralCookie()
+ *
+ * @hide
*/
public abstract int getEphemeralCookieMaxSizeBytes();
@@ -3102,6 +3290,8 @@
* @see #isEphemeralApplication()
* @see #setEphemeralCookie(byte[])
* @see #getEphemeralCookieMaxSizeBytes()
+ *
+ * @hide
*/
public abstract @NonNull byte[] getEphemeralCookie();
@@ -3119,7 +3309,9 @@
*
* @see #isEphemeralApplication()
* @see #getEphemeralCookieMaxSizeBytes()
- * @see #getEphemeralCookie();
+ * @see #getEphemeralCookie()
+ *
+ * @hide
*/
public abstract boolean setEphemeralCookie(@NonNull byte[] cookie);
@@ -3165,19 +3357,35 @@
*
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
- * @param flags Additional option flags. The most important is
- * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
- * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned. The most important is
+ * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+ * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
*
- * @return Returns a ResolveInfo containing the final activity intent that
- * was determined to be the best action. Returns null if no
+ * @return Returns a ResolveInfo object containing the final activity intent
+ * that was determined to be the best action. Returns null if no
* matching activity was found. If multiple matching activities are
- * found and there is no default set, returns a ResolveInfo
+ * found and there is no default set, returns a ResolveInfo object
* containing something else, such as the activity resolver.
*
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ResolveInfo resolveActivity(Intent intent, @ResolveInfoFlags int flags);
@@ -3195,20 +3403,36 @@
*
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
- * @param flags Additional option flags. The most important is
- * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
- * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned. The most important is
+ * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+ * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
* @param userId The user id.
*
- * @return Returns a ResolveInfo containing the final activity intent that
- * was determined to be the best action. Returns null if no
+ * @return Returns a ResolveInfo object containing the final activity intent
+ * that was determined to be the best action. Returns null if no
* matching activity was found. If multiple matching activities are
- * found and there is no default set, returns a ResolveInfo
+ * found and there is no default set, returns a ResolveInfo object
* containing something else, such as the activity resolver.
*
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*
* @hide
*/
@@ -3219,21 +3443,35 @@
* Retrieve all activities that can be performed for the given intent.
*
* @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags. The most important is
- * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
- * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned. The most important is
+ * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+ * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * Or, set {@link #MATCH_ALL} to prevent any filtering of the results.
*
- * You can also set {@link #MATCH_ALL} for preventing the filtering of the results.
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching activity, ordered from best to worst. In other words, the
+ * first item is what would be returned by {@link #resolveActivity}.
+ * If there are no matching activities, an empty list is returned.
*
- * @return A List<ResolveInfo> containing one entry for each matching
- * Activity. These are ordered from best to worst match -- that
- * is, the first item in the list is what is returned by
- * {@link #resolveActivity}. If there are no matching activities, an empty
- * list is returned.
- *
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
@ResolveInfoFlags int flags);
@@ -3242,21 +3480,36 @@
* Retrieve all activities that can be performed for the given intent, for a specific user.
*
* @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags. The most important is
- * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
- * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned. The most important is
+ * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+ * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * Or, set {@link #MATCH_ALL} to prevent any filtering of the results.
*
- * You can also set {@link #MATCH_ALL} for preventing the filtering of the results.
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching activity, ordered from best to worst. In other words, the
+ * first item is what would be returned by {@link #resolveActivity}.
+ * If there are no matching activities, an empty list is returned.
*
- * @return A List<ResolveInfo> containing one entry for each matching
- * Activity. These are ordered from best to worst match -- that
- * is, the first item in the list is what is returned by
- * {@link #resolveActivity}. If there are no matching activities, an empty
- * list is returned.
- *
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
+ *
* @hide
*/
public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
@@ -3276,20 +3529,36 @@
* @param specifics An array of Intents that should be resolved to the
* first specific results. Can be null.
* @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags. The most important is
- * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
- * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned. The most important is
+ * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+ * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
*
- * @return A List<ResolveInfo> containing one entry for each matching
- * Activity. These are ordered first by all of the intents resolved
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching activity. The list is ordered first by all of the intents resolved
* in <var>specifics</var> and then any additional activities that
* can handle <var>intent</var> but did not get included by one of
* the <var>specifics</var> intents. If there are no matching
* activities, an empty list is returned.
*
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<ResolveInfo> queryIntentActivityOptions(
ComponentName caller, Intent[] specifics, Intent intent, @ResolveInfoFlags int flags);
@@ -3298,15 +3567,31 @@
* Retrieve all receivers that can handle a broadcast of the given intent.
*
* @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return A List<ResolveInfo> containing one entry for each matching
- * Receiver. These are ordered from first to last in priority. If
- * there are no matching receivers, an empty list is returned.
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching receiver, ordered from best to worst. If there are no matching
+ * receivers, an empty list or null is returned.
*
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<ResolveInfo> queryBroadcastReceivers(Intent intent,
@ResolveInfoFlags int flags);
@@ -3316,16 +3601,33 @@
* user.
*
* @param intent The desired intent as per resolveActivity().
- * @param flags Additional option flags.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
* @param userId The userId of the user being queried.
*
- * @return A List<ResolveInfo> containing one entry for each matching
- * Receiver. These are ordered from first to last in priority. If
- * there are no matching receivers, an empty list or {@code null} is returned.
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching receiver, ordered from best to worst. If there are no matching
+ * receivers, an empty list or null is returned.
*
- * @see #MATCH_DEFAULT_ONLY
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
+ *
* @hide
*/
public abstract List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent,
@@ -3344,14 +3646,31 @@
*
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
- * @param flags Additional option flags.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return Returns a ResolveInfo containing the final service intent that
- * was determined to be the best action. Returns null if no
+ * @return Returns a ResolveInfo object containing the final service intent
+ * that was determined to be the best action. Returns null if no
* matching service was found.
*
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ResolveInfo resolveService(Intent intent, @ResolveInfoFlags int flags);
@@ -3359,16 +3678,32 @@
* Retrieve all services that can match the given intent.
*
* @param intent The desired intent as per resolveService().
- * @param flags Additional option flags.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return A List<ResolveInfo> containing one entry for each matching
- * ServiceInfo. These are ordered from best to worst match -- that
- * is, the first item in the list is what is returned by
- * resolveService(). If there are no matching services, an empty
- * list or {@code null} is returned.
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching service, ordered from best to worst. In other words, the first
+ * item is what would be returned by {@link #resolveService}. If there are
+ * no matching services, an empty list or null is returned.
*
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<ResolveInfo> queryIntentServices(Intent intent,
@ResolveInfoFlags int flags);
@@ -3377,24 +3712,73 @@
* Retrieve all services that can match the given intent for a given user.
*
* @param intent The desired intent as per resolveService().
- * @param flags Additional option flags.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
* @param userId The user id.
*
- * @return A List<ResolveInfo> containing one entry for each matching
- * ServiceInfo. These are ordered from best to worst match -- that
- * is, the first item in the list is what is returned by
- * resolveService(). If there are no matching services, an empty
- * list or {@code null} is returned.
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching service, ordered from best to worst. In other words, the first
+ * item is what would be returned by {@link #resolveService}. If there are
+ * no matching services, an empty list or null is returned.
*
- * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*
* @hide
*/
public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent,
@ResolveInfoFlags int flags, @UserIdInt int userId);
- /** {@hide} */
+ /**
+ * Retrieve all providers that can match the given intent.
+ *
+ * @param intent An intent containing all of the desired specification
+ * (action, data, type, category, and/or component).
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
+ * @param userId The user id.
+ *
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching provider, ordered from best to worst. If there are no
+ * matching services, an empty list or null is returned.
+ *
+ * @see #GET_META_DATA
+ * @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
+ *
+ * @hide
+ */
public abstract List<ResolveInfo> queryIntentContentProvidersAsUser(
Intent intent, @ResolveInfoFlags int flags, @UserIdInt int userId);
@@ -3403,12 +3787,31 @@
*
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
- * @param flags Additional option flags.
- * @return A List<ResolveInfo> containing one entry for each matching
- * ProviderInfo. These are ordered from best to worst match. If
- * there are no matching providers, an empty list or {@code null} is returned.
- * @see #GET_INTENT_FILTERS
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_RESOLVED_FILTER},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #MATCH_ALL},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_DEFAULT_ONLY}, {@link #MATCH_ENCRYPTION_AWARE},
+ * {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
+ * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
+ *
+ * @return Returns a List of ResolveInfo objects containing one entry for each
+ * matching provider, ordered from best to worst. If there are no
+ * matching services, an empty list or null is returned.
+ *
+ * @see #GET_META_DATA
* @see #GET_RESOLVED_FILTER
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<ResolveInfo> queryIntentContentProviders(Intent intent,
@ResolveInfoFlags int flags);
@@ -3417,10 +3820,30 @@
* Find a single content provider by its base path name.
*
* @param name The name of the provider to find.
- * @param flags Additional option flags. Currently should always be 0.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
+ * {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return ContentProviderInfo Information about the provider, if found,
- * else null.
+ * @return A {@link ProviderInfo} object containing information about the provider.
+ * If a provider was not found, returns null.
+ *
+ * @see #GET_META_DATA
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DEBUG_TRIAGED_MISSING
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract ProviderInfo resolveContentProvider(String name,
@ComponentInfoFlags int flags);
@@ -3429,11 +3852,32 @@
* Find a single content provider by its base path name.
*
* @param name The name of the provider to find.
- * @param flags Additional option flags. Currently should always be 0.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
+ * {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
* @param userId The user id.
*
- * @return ContentProviderInfo Information about the provider, if found,
- * else null.
+ * @return A {@link ProviderInfo} object containing information about the provider.
+ * If a provider was not found, returns null.
+ *
+ * @see #GET_META_DATA
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DEBUG_TRIAGED_MISSING
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
+ *
* @hide
*/
public abstract ProviderInfo resolveContentProviderAsUser(String name,
@@ -3450,12 +3894,32 @@
* all content providers are returned.
* @param uid If <var>processName</var> is non-null, this is the required
* uid owning the requested content providers.
- * @param flags Additional option flags. Currently should always be 0.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
+ * {@link #MATCH_ALL}, {@link #MATCH_DEFAULT_ONLY},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_ENCRYPTION_AWARE}, {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE},
+ * {@link #MATCH_ENCRYPTION_UNAWARE}, {@link #MATCH_SYSTEM_ONLY}
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return A List<ContentProviderInfo> containing one entry for each
- * content provider either patching <var>processName</var> or, if
+ * @return A list of {@link ProviderInfo} objects containing one entry for
+ * each provider either matching <var>processName</var> or, if
* <var>processName</var> is null, all known content providers.
* <em>If there are no matching providers, null is returned.</em>
+ *
+ * @see #GET_META_DATA
+ * @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_ALL
+ * @see #MATCH_DEBUG_TRIAGED_MISSING
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_ENCRYPTION_AWARE
+ * @see #MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+ * @see #MATCH_ENCRYPTION_UNAWARE
+ * @see #MATCH_SYSTEM_ONLY
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<ProviderInfo> queryContentProviders(
String processName, int uid, @ComponentInfoFlags int flags);
@@ -3467,12 +3931,16 @@
* @param className The full name (i.e.
* com.google.apps.contacts.InstrumentList) of an
* Instrumentation class.
- * @param flags Additional option flags. Currently should always be 0.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}
+ * to modify the data returned.
*
- * @return InstrumentationInfo containing information about the
+ * @return An {@link InstrumentationInfo} object containing information about the
* instrumentation.
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
+ *
+ * @see #GET_META_DATA
*/
public abstract InstrumentationInfo getInstrumentationInfo(ComponentName className,
@InstrumentationInfoFlags int flags) throws NameNotFoundException;
@@ -3485,11 +3953,15 @@
* @param targetPackage If null, all instrumentation is returned; only the
* instrumentation targeting this package name is
* returned.
- * @param flags Additional option flags. Currently should always be 0.
+ * @param flags Additional option flags. Use any combination of
+ * {@link #GET_META_DATA}
+ * to modify the data returned.
*
- * @return A List<InstrumentationInfo> containing one entry for each
- * matching available Instrumentation. Returns an empty list if
- * there is no instrumentation available for the given package.
+ * @return A list of {@link InstrumentationInfo} objects containing one
+ * entry for each matching instrumentation. If there are no
+ * instrumentation available, returns and empty list.
+ *
+ * @see #GET_META_DATA
*/
public abstract List<InstrumentationInfo> queryInstrumentation(String targetPackage,
@InstrumentationInfoFlags int flags);
@@ -3904,34 +4376,52 @@
*
* @param archiveFilePath The path to the archive file
* @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES}, to modify the data returned.
+ * {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+ * {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+ * {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+ * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+ * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+ * {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return Returns the information about the package. Returns
- * null if the package could not be successfully parsed.
+ * @return A PackageInfo object containing information about the
+ * package archive. If the package could not be parsed,
+ * returns null.
*
* @see #GET_ACTIVITIES
- * @see #GET_GIDS
* @see #GET_CONFIGURATIONS
+ * @see #GET_GIDS
* @see #GET_INSTRUMENTATION
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
+ * @see #GET_SHARED_LIBRARY_FILES
* @see #GET_SIGNATURES
+ * @see #GET_URI_PERMISSION_PATTERNS
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_UNINSTALLED_PACKAGES
*
*/
public PackageInfo getPackageArchiveInfo(String archiveFilePath, @PackageInfoFlags int flags) {
final PackageParser parser = new PackageParser();
final File apkFile = new File(archiveFilePath);
try {
+ if ((flags & (MATCH_ENCRYPTION_UNAWARE | MATCH_ENCRYPTION_AWARE)) != 0) {
+ // Caller expressed an explicit opinion about what encryption
+ // aware/unaware components they want to see, so fall through and
+ // give them what they want
+ } else {
+ // Caller expressed no opinion, so match everything
+ flags |= MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+ }
+
PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0);
if ((flags & GET_SIGNATURES) != 0) {
parser.collectCertificates(pkg, 0);
@@ -3944,211 +4434,64 @@
}
/**
- * @hide Install a package. Since this may take a little while, the result
- * will be posted back to the given observer. An installation will
- * fail if the calling context lacks the
- * {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if
- * the package named in the package file's manifest is already
- * installed, or if there's no space available on the device.
- * @param packageURI The location of the package file to install. This can
- * be a 'file:' or a 'content:' URI.
- * @param observer An observer callback to get notified when the package
- * installation is complete.
- * {@link IPackageInstallObserver#packageInstalled(String, int)}
- * will be called when that happens. This parameter must not be
- * null.
- * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING},
- * {@link #INSTALL_ALLOW_TEST}.
- * @param installerPackageName Optional package name of the application that
- * is performing the installation. This identifies which market
- * the package came from.
- * @deprecated Use {@link #installPackage(Uri, PackageInstallObserver, int,
- * String)} instead. This method will continue to be supported
- * but the older observer interface will not get additional
- * failure details.
+ * @deprecated replaced by {@link PackageInstaller}
+ * @hide
*/
+ @Deprecated
public abstract void installPackage(
- Uri packageURI, IPackageInstallObserver observer, int flags,
+ Uri packageURI, IPackageInstallObserver observer, @InstallFlags int flags,
String installerPackageName);
/**
- * Similar to
- * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
- * with an extra verification file provided.
- *
- * @param packageURI The location of the package file to install. This can
- * be a 'file:' or a 'content:' URI.
- * @param observer An observer callback to get notified when the package
- * installation is complete.
- * {@link IPackageInstallObserver#packageInstalled(String, int)}
- * will be called when that happens. This parameter must not be
- * null.
- * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING},
- * {@link #INSTALL_ALLOW_TEST}.
- * @param installerPackageName Optional package name of the application that
- * is performing the installation. This identifies which market
- * the package came from.
- * @param verificationURI The location of the supplementary verification
- * file. This can be a 'file:' or a 'content:' URI. May be
- * {@code null}.
- * @param encryptionParams if the package to be installed is encrypted,
- * these parameters describing the encryption and authentication
- * used. May be {@code null}.
+ * @deprecated replaced by {@link PackageInstaller}
* @hide
- * @deprecated Use {@link #installPackageWithVerification(Uri,
- * PackageInstallObserver, int, String, Uri,
- * ContainerEncryptionParams)} instead. This method will
- * continue to be supported but the older observer interface
- * will not get additional failure details.
*/
+ @Deprecated
public abstract void installPackageWithVerification(Uri packageURI,
- IPackageInstallObserver observer, int flags, String installerPackageName,
- Uri verificationURI,
- ContainerEncryptionParams encryptionParams);
+ IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
+ Uri verificationURI, ContainerEncryptionParams encryptionParams);
/**
- * Similar to
- * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
- * with an extra verification information provided.
- *
- * @param packageURI The location of the package file to install. This can
- * be a 'file:' or a 'content:' URI.
- * @param observer An observer callback to get notified when the package
- * installation is complete.
- * {@link IPackageInstallObserver#packageInstalled(String, int)}
- * will be called when that happens. This parameter must not be
- * null.
- * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING},
- * {@link #INSTALL_ALLOW_TEST}.
- * @param installerPackageName Optional package name of the application that
- * is performing the installation. This identifies which market
- * the package came from.
- * @param verificationParams an object that holds signal information to
- * assist verification. May be {@code null}.
- * @param encryptionParams if the package to be installed is encrypted,
- * these parameters describing the encryption and authentication
- * used. May be {@code null}.
+ * @deprecated replaced by {@link PackageInstaller}
* @hide
- * @deprecated Use {@link #installPackageWithVerificationAndEncryption(Uri,
- * PackageInstallObserver, int, String, VerificationParams,
- * ContainerEncryptionParams)} instead. This method will
- * continue to be supported but the older observer interface
- * will not get additional failure details.
*/
@Deprecated
public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
- IPackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams,
- ContainerEncryptionParams encryptionParams);
-
- // Package-install variants that take the new, expanded form of observer interface.
- // Note that these *also* take the original observer type and will redundantly
- // report the same information to that observer if supplied; but it is not required.
+ IPackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
/**
+ * @deprecated replaced by {@link PackageInstaller}
* @hide
- *
- * Install a package. Since this may take a little while, the result will
- * be posted back to the given observer. An installation will fail if the calling context
- * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
- * package named in the package file's manifest is already installed, or if there's no space
- * available on the device.
- *
- * @param packageURI The location of the package file to install. This can be a 'file:' or a
- * 'content:' URI.
- * @param observer An observer callback to get notified when the package installation is
- * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
- * called when that happens. This parameter must not be null.
- * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
- * @param installerPackageName Optional package name of the application that is performing the
- * installation. This identifies which market the package came from.
*/
- public abstract void installPackage(
- Uri packageURI, PackageInstallObserver observer,
- int flags, String installerPackageName);
-
+ @Deprecated
+ public abstract void installPackage(Uri packageURI, PackageInstallObserver observer,
+ @InstallFlags int flags, String installerPackageName);
/**
+ * @deprecated replaced by {@link PackageInstaller}
* @hide
- * Install a package. Since this may take a little while, the result will be
- * posted back to the given observer. An installation will fail if the package named
- * in the package file's manifest is already installed, or if there's no space
- * available on the device.
- * @param packageURI The location of the package file to install. This can be a 'file:' or a
- * 'content:' URI.
- * @param observer An observer callback to get notified when the package installation is
- * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
- * called when that happens. This parameter must not be null.
- * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
- * @param installerPackageName Optional package name of the application that is performing the
- * installation. This identifies which market the package came from.
- * @param userId The user id.
*/
- @RequiresPermission(anyOf = {
- Manifest.permission.INSTALL_PACKAGES,
- Manifest.permission.INTERACT_ACROSS_USERS_FULL})
- public abstract void installPackageAsUser(
- Uri packageURI, PackageInstallObserver observer, int flags,
- String installerPackageName, @UserIdInt int userId);
+ @Deprecated
+ public abstract void installPackageAsUser(Uri packageURI, PackageInstallObserver observer,
+ @InstallFlags int flags, String installerPackageName, @UserIdInt int userId);
/**
- * Similar to
- * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
- * with an extra verification file provided.
- *
- * @param packageURI The location of the package file to install. This can
- * be a 'file:' or a 'content:' URI.
- * @param observer An observer callback to get notified when the package installation is
- * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
- * called when that happens. This parameter must not be null.
- * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
- * @param installerPackageName Optional package name of the application that
- * is performing the installation. This identifies which market
- * the package came from.
- * @param verificationURI The location of the supplementary verification
- * file. This can be a 'file:' or a 'content:' URI. May be
- * {@code null}.
- * @param encryptionParams if the package to be installed is encrypted,
- * these parameters describing the encryption and authentication
- * used. May be {@code null}.
+ * @deprecated replaced by {@link PackageInstaller}
* @hide
*/
+ @Deprecated
public abstract void installPackageWithVerification(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- Uri verificationURI,
- ContainerEncryptionParams encryptionParams);
+ PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
+ Uri verificationURI, ContainerEncryptionParams encryptionParams);
/**
- * Similar to
- * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
- * with an extra verification information provided.
- *
- * @param packageURI The location of the package file to install. This can
- * be a 'file:' or a 'content:' URI.
- * @param observer An observer callback to get notified when the package installation is
- * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
- * called when that happens. This parameter must not be null.
- * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
- * @param installerPackageName Optional package name of the application that
- * is performing the installation. This identifies which market
- * the package came from.
- * @param verificationParams an object that holds signal information to
- * assist verification. May be {@code null}.
- * @param encryptionParams if the package to be installed is encrypted,
- * these parameters describing the encryption and authentication
- * used. May be {@code null}.
- *
+ * @deprecated replaced by {@link PackageInstaller}
* @hide
*/
+ @Deprecated
public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
+ PackageInstallObserver observer, @InstallFlags int flags, String installerPackageName,
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
/**
@@ -4364,45 +4707,44 @@
String installerPackageName);
/**
- * Attempts to delete a package. Since this may take a little while, the result will
- * be posted back to the given observer. A deletion will fail if the calling context
- * lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
- * named package cannot be found, or if the named package is a "system package".
- * (TODO: include pointer to documentation on "system packages")
+ * Attempts to delete a package. Since this may take a little while, the
+ * result will be posted back to the given observer. A deletion will fail if
+ * the calling context lacks the
+ * {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
+ * named package cannot be found, or if the named package is a system
+ * package.
*
* @param packageName The name of the package to delete
- * @param observer An observer callback to get notified when the package deletion is
- * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
- * called when that happens. observer may be null to indicate that no callback is desired.
- * @param flags Possible values: {@link #DELETE_KEEP_DATA},
- * {@link #DELETE_ALL_USERS}.
- *
+ * @param observer An observer callback to get notified when the package
+ * deletion is complete.
+ * {@link android.content.pm.IPackageDeleteObserver#packageDeleted}
+ * will be called when that happens. observer may be null to
+ * indicate that no callback is desired.
* @hide
*/
- // @SystemApi
- public abstract void deletePackage(
- String packageName, IPackageDeleteObserver observer, int flags);
+ public abstract void deletePackage(String packageName, IPackageDeleteObserver observer,
+ @DeleteFlags int flags);
/**
- * Attempts to delete a package. Since this may take a little while, the result will
- * be posted back to the given observer. A deletion will fail if the named package cannot be
- * found, or if the named package is a "system package".
- * (TODO: include pointer to documentation on "system packages")
+ * Attempts to delete a package. Since this may take a little while, the
+ * result will be posted back to the given observer. A deletion will fail if
+ * the named package cannot be found, or if the named package is a system
+ * package.
*
* @param packageName The name of the package to delete
- * @param observer An observer callback to get notified when the package deletion is
- * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
- * called when that happens. observer may be null to indicate that no callback is desired.
- * @param flags Possible values: {@link #DELETE_KEEP_DATA}, {@link #DELETE_ALL_USERS}.
+ * @param observer An observer callback to get notified when the package
+ * deletion is complete.
+ * {@link android.content.pm.IPackageDeleteObserver#packageDeleted}
+ * will be called when that happens. observer may be null to
+ * indicate that no callback is desired.
* @param userId The user Id
- *
* @hide
*/
@RequiresPermission(anyOf = {
Manifest.permission.DELETE_PACKAGES,
Manifest.permission.INTERACT_ACROSS_USERS_FULL})
- public abstract void deletePackageAsUser(
- String packageName, IPackageDeleteObserver observer, int flags, @UserIdInt int userId);
+ public abstract void deletePackageAsUser(String packageName, IPackageDeleteObserver observer,
+ @DeleteFlags int flags, @UserIdInt int userId);
/**
* Retrieve the package name of the application that installed a package. This identifies
@@ -4469,7 +4811,6 @@
*
* @hide
*/
- // @SystemApi
public void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {
freeStorageAndNotify(null, freeStorageSize, observer);
}
@@ -4561,28 +4902,36 @@
* least preferred.
*
* @param flags Additional option flags. Use any combination of
- * {@link #GET_ACTIVITIES},
- * {@link #GET_GIDS},
- * {@link #GET_CONFIGURATIONS},
- * {@link #GET_INSTRUMENTATION},
- * {@link #GET_PERMISSIONS},
- * {@link #GET_PROVIDERS},
- * {@link #GET_RECEIVERS},
- * {@link #GET_SERVICES},
- * {@link #GET_SIGNATURES}, to modify the data returned.
+ * {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+ * {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+ * {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+ * {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+ * {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+ * {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+ * {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+ * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+ * {@link #MATCH_UNINSTALLED_PACKAGES}
+ * to modify the data returned.
*
- * @return Returns a list of PackageInfo objects describing each
- * preferred application, in order of preference.
+ * @return A List of PackageInfo objects, one for each preferred application,
+ * in order of preference.
*
* @see #GET_ACTIVITIES
- * @see #GET_GIDS
* @see #GET_CONFIGURATIONS
+ * @see #GET_GIDS
* @see #GET_INSTRUMENTATION
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_META_DATA
* @see #GET_PERMISSIONS
* @see #GET_PROVIDERS
* @see #GET_RECEIVERS
* @see #GET_SERVICES
+ * @see #GET_SHARED_LIBRARY_FILES
* @see #GET_SIGNATURES
+ * @see #GET_URI_PERMISSION_PATTERNS
+ * @see #MATCH_DISABLED_COMPONENTS
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ * @see #MATCH_UNINSTALLED_PACKAGES
*/
public abstract List<PackageInfo> getPreferredPackages(@PackageInfoFlags int flags);
@@ -4845,27 +5194,6 @@
public abstract boolean isSignedByExactly(String packageName, KeySet ks);
/**
- * Attempts to move package resources from internal to external media or vice versa.
- * Since this may take a little while, the result will
- * be posted back to the given observer. This call may fail if the calling context
- * lacks the {@link android.Manifest.permission#MOVE_PACKAGE} permission, if the
- * named package cannot be found, or if the named package is a "system package".
- *
- * @param packageName The name of the package to delete
- * @param observer An observer callback to get notified when the package move is
- * complete. {@link android.content.pm.IPackageMoveObserver#packageMoved(boolean)} will be
- * called when that happens. observer may be null to indicate that no callback is desired.
- * @param flags To indicate install location {@link #MOVE_INTERNAL} or
- * {@link #MOVE_EXTERNAL_MEDIA}
- *
- * @hide
- */
- @Deprecated
- public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
- throw new UnsupportedOperationException();
- }
-
- /**
* Puts the package in a suspended state, making the package un-runnable,
* but it doesn't remove the data or the actual package file. The application notifications
* will be hidden and also the application will not show up in recents.
@@ -4936,22 +5264,25 @@
public abstract @NonNull PackageInstaller getPackageInstaller();
/**
- * Adds a {@link CrossProfileIntentFilter}. After calling this method all intents sent from the
- * user with id sourceUserId can also be be resolved by activities in the user with id
- * targetUserId if they match the specified intent filter.
+ * Adds a {@code CrossProfileIntentFilter}. After calling this method all
+ * intents sent from the user with id sourceUserId can also be be resolved
+ * by activities in the user with id targetUserId if they match the
+ * specified intent filter.
+ *
* @param filter The {@link IntentFilter} the intent has to match
* @param sourceUserId The source user id.
* @param targetUserId The target user id.
- * @param flags The possible values are {@link SKIP_CURRENT_PROFILE} and
- * {@link ONLY_IF_NO_MATCH_FOUND}.
+ * @param flags The possible values are {@link #SKIP_CURRENT_PROFILE} and
+ * {@link #ONLY_IF_NO_MATCH_FOUND}.
* @hide
*/
public abstract void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId,
int targetUserId, int flags);
/**
- * Clearing {@link CrossProfileIntentFilter}s which have the specified user as their
- * source, and have been set by the app calling this method.
+ * Clearing {@code CrossProfileIntentFilter}s which have the specified user
+ * as their source, and have been set by the app calling this method.
+ *
* @param sourceUserId The source user id.
* @hide
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 236cf64a..6d360d7 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -37,7 +37,6 @@
import android.content.res.XmlResourceParser;
import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
import android.os.FileUtils;
import android.os.PatternMatcher;
import android.os.Trace;
@@ -52,6 +51,7 @@
import android.util.Pair;
import android.util.Slog;
import android.util.TypedValue;
+import android.util.jar.StrictJarFile;
import android.view.Gravity;
import com.android.internal.R;
@@ -86,8 +86,6 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.ZipEntry;
-import android.util.jar.StrictJarFile;
-
/**
* Parser for package files (APKs) on disk. This supports apps packaged either
* as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
@@ -421,8 +419,7 @@
public static PackageInfo generatePackageInfo(PackageParser.Package p,
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
Set<String> grantedPermissions, PackageUserState state, int userId) {
-
- if (!checkUseInstalledOrHidden(flags, state)) {
+ if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
return null;
}
PackageInfo pi = new PackageInfo();
@@ -466,92 +463,60 @@
p.featureGroups.toArray(pi.featureGroups);
}
}
- if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
- int N = p.activities.size();
+ if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
+ final int N = p.activities.size();
if (N > 0) {
- if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.activities = new ActivityInfo[N];
- } else {
- int num = 0;
- for (int i=0; i<N; i++) {
- if (p.activities.get(i).info.enabled) num++;
- }
- pi.activities = new ActivityInfo[num];
- }
- for (int i=0, j=0; i<N; i++) {
- final Activity activity = p.activities.get(i);
- if (activity.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags,
- state, userId);
+ int num = 0;
+ final ActivityInfo[] res = new ActivityInfo[N];
+ for (int i = 0; i < N; i++) {
+ final Activity a = p.activities.get(i);
+ if (state.isMatch(a.info, flags)) {
+ res[num++] = generateActivityInfo(a, flags, state, userId);
}
}
+ pi.activities = ArrayUtils.trimToSize(res, num);
}
}
- if ((flags&PackageManager.GET_RECEIVERS) != 0) {
- int N = p.receivers.size();
+ if ((flags & PackageManager.GET_RECEIVERS) != 0) {
+ final int N = p.receivers.size();
if (N > 0) {
- if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.receivers = new ActivityInfo[N];
- } else {
- int num = 0;
- for (int i=0; i<N; i++) {
- if (p.receivers.get(i).info.enabled) num++;
- }
- pi.receivers = new ActivityInfo[num];
- }
- for (int i=0, j=0; i<N; i++) {
- final Activity activity = p.receivers.get(i);
- if (activity.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags,
- state, userId);
+ int num = 0;
+ final ActivityInfo[] res = new ActivityInfo[N];
+ for (int i = 0; i < N; i++) {
+ final Activity a = p.receivers.get(i);
+ if (state.isMatch(a.info, flags)) {
+ res[num++] = generateActivityInfo(a, flags, state, userId);
}
}
+ pi.receivers = ArrayUtils.trimToSize(res, num);
}
}
- if ((flags&PackageManager.GET_SERVICES) != 0) {
- int N = p.services.size();
+ if ((flags & PackageManager.GET_SERVICES) != 0) {
+ final int N = p.services.size();
if (N > 0) {
- if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.services = new ServiceInfo[N];
- } else {
- int num = 0;
- for (int i=0; i<N; i++) {
- if (p.services.get(i).info.enabled) num++;
- }
- pi.services = new ServiceInfo[num];
- }
- for (int i=0, j=0; i<N; i++) {
- final Service service = p.services.get(i);
- if (service.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.services[j++] = generateServiceInfo(p.services.get(i), flags,
- state, userId);
+ int num = 0;
+ final ServiceInfo[] res = new ServiceInfo[N];
+ for (int i = 0; i < N; i++) {
+ final Service s = p.services.get(i);
+ if (state.isMatch(s.info, flags)) {
+ res[num++] = generateServiceInfo(s, flags, state, userId);
}
}
+ pi.services = ArrayUtils.trimToSize(res, num);
}
}
- if ((flags&PackageManager.GET_PROVIDERS) != 0) {
- int N = p.providers.size();
+ if ((flags & PackageManager.GET_PROVIDERS) != 0) {
+ final int N = p.providers.size();
if (N > 0) {
- if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.providers = new ProviderInfo[N];
- } else {
- int num = 0;
- for (int i=0; i<N; i++) {
- if (p.providers.get(i).info.enabled) num++;
- }
- pi.providers = new ProviderInfo[num];
- }
- for (int i=0, j=0; i<N; i++) {
- final Provider provider = p.providers.get(i);
- if (provider.info.enabled
- || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
- pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags,
- state, userId);
+ int num = 0;
+ final ProviderInfo[] res = new ProviderInfo[N];
+ for (int i = 0; i < N; i++) {
+ final Provider pr = p.providers.get(i);
+ if (state.isMatch(pr.info, flags)) {
+ res[num++] = generateProviderInfo(pr, flags, state, userId);
}
}
+ pi.providers = ArrayUtils.trimToSize(res, num);
}
}
if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) {
@@ -3921,6 +3886,11 @@
s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
}
if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestService_externalService,
+ false)) {
+ s.info.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
+ }
+ if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestService_singleUser,
false)) {
s.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
@@ -4623,6 +4593,13 @@
&& !isForwardLocked() && !applicationInfo.isExternalAsec();
}
+ public boolean isMatch(int flags) {
+ if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
+ return isSystemApp();
+ }
+ return true;
+ }
+
public String toString() {
return "Package{"
+ Integer.toHexString(System.identityHashCode(this))
@@ -4873,7 +4850,7 @@
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
PackageUserState state, int userId) {
if (p == null) return null;
- if (!checkUseInstalledOrHidden(flags, state)) {
+ if (!checkUseInstalledOrHidden(flags, state) || !p.isMatch(flags)) {
return null;
}
if (!copyNeeded(flags, p, state, null, userId)
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 91fdf7f..38e0044 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -17,9 +17,20 @@
package android.content.pm;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import android.util.ArraySet;
+import com.android.internal.util.ArrayUtils;
+
/**
* Per-user state information about a package.
* @hide
@@ -58,12 +69,77 @@
hidden = o.hidden;
suspended = o.suspended;
lastDisableAppCaller = o.lastDisableAppCaller;
- disabledComponents = o.disabledComponents != null
- ? new ArraySet<>(o.disabledComponents) : null;
- enabledComponents = o.enabledComponents != null
- ? new ArraySet<>(o.enabledComponents) : null;
+ disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
+ enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
blockUninstall = o.blockUninstall;
domainVerificationStatus = o.domainVerificationStatus;
appLinkGeneration = o.appLinkGeneration;
}
+
+ /**
+ * Test if this package is installed.
+ */
+ public boolean isInstalled(int flags) {
+ return (this.installed && !this.hidden)
+ || (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
+ }
+
+ /**
+ * Test if the given component is considered installed, enabled and a match
+ * for the given flags.
+ */
+ public boolean isMatch(ComponentInfo componentInfo, int flags) {
+ if (!isInstalled(flags)) return false;
+ if (!isEnabled(componentInfo, flags)) return false;
+
+ if ((flags & MATCH_SYSTEM_ONLY) != 0) {
+ if (!componentInfo.applicationInfo.isSystemApp()) {
+ return false;
+ }
+ }
+
+ final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
+ && !componentInfo.encryptionAware;
+ final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
+ && componentInfo.encryptionAware;
+ return matchesUnaware || matchesAware;
+ }
+
+ /**
+ * Test if the given component is considered enabled.
+ */
+ public boolean isEnabled(ComponentInfo componentInfo, int flags) {
+ if ((flags & MATCH_DISABLED_COMPONENTS) != 0) {
+ return true;
+ }
+
+ // First check if the overall package is disabled; if the package is
+ // enabled then fall through to check specific component
+ switch (this.enabled) {
+ case COMPONENT_ENABLED_STATE_DISABLED:
+ case COMPONENT_ENABLED_STATE_DISABLED_USER:
+ return false;
+ case COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
+ if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) {
+ return false;
+ }
+ case COMPONENT_ENABLED_STATE_DEFAULT:
+ if (!componentInfo.applicationInfo.enabled) {
+ return false;
+ }
+ case COMPONENT_ENABLED_STATE_ENABLED:
+ break;
+ }
+
+ // Check if component has explicit state before falling through to
+ // the manifest default
+ if (ArrayUtils.contains(this.enabledComponents, componentInfo.name)) {
+ return true;
+ }
+ if (ArrayUtils.contains(this.disabledComponents, componentInfo.name)) {
+ return false;
+ }
+
+ return componentInfo.enabled;
+ }
}
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 74e5c2a..eecf0de 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -49,6 +49,14 @@
public static final int FLAG_ISOLATED_PROCESS = 0x0002;
/**
+ * Bit in {@link #flags}: If set, the service can be bound and run in the
+ * calling application's package, rather than the package in which it is
+ * declared. Set from {@link android.R.attr#externalService} attribute.
+ * @hide
+ */
+ public static final int FLAG_EXTERNAL_SERVICE = 0x0004;
+
+ /**
* Bit in {@link #flags}: If set, a single instance of the service will
* run for all users on the device. Set from the
* {@link android.R.attr#singleUser} attribute.
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index f642f08..2826882 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1258,6 +1258,10 @@
*/
@CallSuper
public boolean onEvaluateInputViewShown() {
+ if (mSettingsObserver == null) {
+ Log.w(TAG, "onEvaluateInputViewShown: mSettingsObserver must not be null here.");
+ return false;
+ }
if (mSettingsObserver.shouldShowImeWithHardKeyboard()) {
return true;
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 515e9a2..176e923 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -19,11 +19,11 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.net.NetworkUtils;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
@@ -46,12 +46,12 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Protocol;
-import java.net.InetAddress;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.HashMap;
-
import libcore.net.event.NetworkEventDispatcher;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* Class that answers queries about the state of network connectivity. It also
* notifies applications when network connectivity changes. Get an instance
@@ -898,6 +898,24 @@
}
/**
+ * Gets the URL that should be used for resolving whether a captive portal is present.
+ * 1. This URL should respond with a 204 response to a GET request to indicate no captive
+ * portal is present.
+ * 2. This URL must be HTTP as redirect responses are used to find captive portal
+ * sign-in pages. Captive portals cannot respond to HTTPS requests with redirects.
+ *
+ * @hide
+ */
+ @SystemApi
+ public String getCaptivePortalServerUrl() {
+ try {
+ return mService.getCaptivePortalServerUrl();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Tells the underlying networking system that the caller wants to
* begin using the named feature. The interpretation of {@code feature}
* is completely up to each networking implementation.
@@ -1611,7 +1629,7 @@
// Have a provisioning app - must only let system apps (which check this app)
// turn on tethering
context.enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, "ConnectivityService");
+ android.Manifest.permission.TETHER_PRIVILEGED, "ConnectivityService");
} else {
int uid = Binder.getCallingUid();
Settings.checkAndNoteWriteSettingsOperation(context, uid, Settings
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index d4dd669..ef91137 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -165,4 +165,6 @@
in IBinder binder, String srcAddr, int srcPort, String dstAddr);
void stopKeepalive(in Network network, int slot);
+
+ String getCaptivePortalServerUrl();
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index fdd34f5..e58744b 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -130,6 +130,9 @@
/** The dirty dalvik pages that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int dalvikSwappedOut;
+ /** The dirty dalvik pages that have been swapped out, proportional. */
+ /** @hide We may want to expose this, eventually. */
+ public int dalvikSwappedOutPss;
/** The proportional set size for the native heap. */
public int nativePss;
@@ -149,6 +152,9 @@
/** The dirty native pages that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int nativeSwappedOut;
+ /** The dirty native pages that have been swapped out, proportional. */
+ /** @hide We may want to expose this, eventually. */
+ public int nativeSwappedOutPss;
/** The proportional set size for everything else. */
public int otherPss;
@@ -168,6 +174,13 @@
/** The dirty pages used by anyting else that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int otherSwappedOut;
+ /** The dirty pages used by anyting else that have been swapped out, proportional. */
+ /** @hide We may want to expose this, eventually. */
+ public int otherSwappedOutPss;
+
+ /** Whether the kernel reports proportional swap usage */
+ /** @hide */
+ public boolean hasSwappedOutPss;
/** @hide */
public static final int HEAP_UNKNOWN = 0;
@@ -235,7 +248,7 @@
public static final int NUM_DVK_STATS = 8;
/** @hide */
- public static final int NUM_CATEGORIES = 7;
+ public static final int NUM_CATEGORIES = 8;
/** @hide */
public static final int offsetPss = 0;
@@ -251,6 +264,8 @@
public static final int offsetSharedClean = 5;
/** @hide */
public static final int offsetSwappedOut = 6;
+ /** @hide */
+ public static final int offsetSwappedOutPss = 7;
private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
@@ -261,7 +276,7 @@
* Return total PSS memory usage in kB.
*/
public int getTotalPss() {
- return dalvikPss + nativePss + otherPss;
+ return dalvikPss + nativePss + otherPss + getTotalSwappedOutPss();
}
/**
@@ -274,7 +289,8 @@
}
/**
- * Return total PSS memory usage in kB.
+ * Return total PSS memory usage in kB mapping a file of one of the following extension:
+ * .so, .jar, .apk, .ttf, .dex, .odex, .oat, .art .
*/
public int getTotalSwappablePss() {
return dalvikSwappablePss + nativeSwappablePss + otherSwappablePss;
@@ -316,6 +332,14 @@
return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut;
}
+ /**
+ * Return total swapped out memory in kB, proportional.
+ * @hide
+ */
+ public int getTotalSwappedOutPss() {
+ return dalvikSwappedOutPss + nativeSwappedOutPss + otherSwappedOutPss;
+ }
+
/** @hide */
public int getOtherPss(int which) {
return otherStats[which*NUM_CATEGORIES + offsetPss];
@@ -359,6 +383,11 @@
}
/** @hide */
+ public int getOtherSwappedOutPss(int which) {
+ return otherStats[which*NUM_CATEGORIES + offsetSwappedOutPss];
+ }
+
+ /** @hide */
public static String getOtherLabel(int which) {
switch (which) {
case OTHER_DALVIK_OTHER: return "Dalvik Other";
@@ -632,12 +661,24 @@
* know if the Swap memory is shared or private, so we don't know
* what to blame on the application and what on the system.
* For now, just lump all the Swap in one place.
+ * For kernels reporting SwapPss {@link #getSummaryTotalSwapPss()}
+ * will report the application proportional Swap.
* @hide
*/
public int getSummaryTotalSwap() {
return getTotalSwappedOut();
}
+ /**
+ * Total proportional Swap in KB.
+ * Notes:
+ * * Always 0 if {@link #hasSwappedOutPss} is false.
+ * @hide
+ */
+ public int getSummaryTotalSwapPss() {
+ return getTotalSwappedOutPss();
+ }
+
public int describeContents() {
return 0;
}
@@ -664,6 +705,8 @@
dest.writeInt(otherPrivateClean);
dest.writeInt(otherSharedClean);
dest.writeInt(otherSwappedOut);
+ dest.writeInt(hasSwappedOutPss ? 1 : 0);
+ dest.writeInt(otherSwappedOutPss);
dest.writeIntArray(otherStats);
}
@@ -689,6 +732,8 @@
otherPrivateClean = source.readInt();
otherSharedClean = source.readInt();
otherSwappedOut = source.readInt();
+ hasSwappedOutPss = source.readInt() != 0;
+ otherSwappedOutPss = source.readInt();
otherStats = source.createIntArray();
}
@@ -1563,11 +1608,12 @@
/**
* Retrieves the PSS memory used by the process as given by the
- * smaps. Optionally supply a long array of 1 entry to also
- * receive the uss of the process, and another array to also
- * retrieve the separate memtrack size. @hide
+ * smaps. Optionally supply a long array of 2 entries to also
+ * receive the Uss and SwapPss of the process, and another array to also
+ * retrieve the separate memtrack size.
+ * @hide
*/
- public static native long getPss(int pid, long[] outUss, long[] outMemtrack);
+ public static native long getPss(int pid, long[] outUssSwapPss, long[] outMemtrack);
/** @hide */
public static final int MEMINFO_TOTAL = 0;
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 867d0b9..bcc1213 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -33,13 +33,13 @@
public static final int PER_USER_RANGE = 100000;
/** @hide A user id to indicate all users on the device */
- public static final int USER_ALL = -1;
+ public static final @UserIdInt int USER_ALL = -1;
/** @hide A user handle to indicate all users on the device */
public static final UserHandle ALL = new UserHandle(USER_ALL);
/** @hide A user id to indicate the currently active user */
- public static final int USER_CURRENT = -2;
+ public static final @UserIdInt int USER_CURRENT = -2;
/** @hide A user handle to indicate the current user of the device */
public static final UserHandle CURRENT = new UserHandle(USER_CURRENT);
@@ -47,7 +47,7 @@
/** @hide A user id to indicate that we would like to send to the current
* user, but if this is calling from a user process then we will send it
* to the caller's user instead of failing with a security exception */
- public static final int USER_CURRENT_OR_SELF = -3;
+ public static final @UserIdInt int USER_CURRENT_OR_SELF = -3;
/** @hide A user handle to indicate that we would like to send to the current
* user, but if this is calling from a user process then we will send it
@@ -55,14 +55,14 @@
public static final UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
/** @hide An undefined user id */
- public static final int USER_NULL = -10000;
+ public static final @UserIdInt int USER_NULL = -10000;
/**
* @hide A user id constant to indicate the "owner" user of the device
* @deprecated Consider using either {@link UserHandle#USER_SYSTEM} constant or
* check the target user's flag {@link android.content.pm.UserInfo#isAdmin}.
*/
- public static final int USER_OWNER = 0;
+ public static final @UserIdInt int USER_OWNER = 0;
/**
* @hide A user handle to indicate the primary/owner user of the device
@@ -72,7 +72,7 @@
public static final UserHandle OWNER = new UserHandle(USER_OWNER);
/** @hide A user id constant to indicate the "system" user of the device */
- public static final int USER_SYSTEM = 0;
+ public static final @UserIdInt int USER_SYSTEM = 0;
/** @hide A user handle to indicate the "system" user of the device */
public static final UserHandle SYSTEM = new UserHandle(USER_SYSTEM);
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index beda169..c8b942b 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -882,7 +882,8 @@
}
packageName = packageNames[0];
}
- final int uid = ActivityThread.getPackageManager().getPackageUid(packageName, userId);
+ final int uid = ActivityThread.getPackageManager().getPackageUid(packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
if (uid <= 0) {
return new StorageVolume[0];
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1908aea..a6485e4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -641,7 +641,7 @@
* provided by the platform for applications to operate correctly in the various power
* saving mode. This is only for unusual applications that need to deeply control their own
* execution, at the potential expense of the user's battery life. Note that these applications
- * greatly run the risk of showing to the user has how power consumers on their device.</p>
+ * greatly run the risk of showing to the user as high power consumers on their device.</p>
* <p>
* Input: The Intent's data URI must specify the application package name
* to be shown, with the "package" scheme. That is "package:com.my.app".
@@ -2606,6 +2606,15 @@
private static final Validator MICROPHONE_MUTE_VALIDATOR = sBooleanValidator;
/**
+ * Master mono (int 1 = mono, 0 = normal).
+ *
+ * @hide
+ */
+ public static final String MASTER_MONO = "master_mono";
+
+ private static final Validator MASTER_MONO_VALIDATOR = sBooleanValidator;
+
+ /**
* Whether the notifications should use the ring volume (value of 1) or
* a separate notification volume (value of 0). In most cases, users
* will have this enabled so the notification and ringer volumes will be
@@ -3372,6 +3381,7 @@
PRIVATE_SETTINGS.add(VOLUME_MASTER);
PRIVATE_SETTINGS.add(VOLUME_MASTER_MUTE);
PRIVATE_SETTINGS.add(MICROPHONE_MUTE);
+ PRIVATE_SETTINGS.add(MASTER_MONO);
PRIVATE_SETTINGS.add(NOTIFICATIONS_USE_RING_VOLUME);
PRIVATE_SETTINGS.add(VIBRATE_IN_SILENT);
PRIVATE_SETTINGS.add(MEDIA_BUTTON_RECEIVER);
@@ -3450,6 +3460,7 @@
VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR);
VALIDATORS.put(VOLUME_MASTER_MUTE, VOLUME_MASTER_MUTE_VALIDATOR);
VALIDATORS.put(MICROPHONE_MUTE, MICROPHONE_MUTE_VALIDATOR);
+ VALIDATORS.put(MASTER_MONO, MASTER_MONO_VALIDATOR);
VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR);
VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR);
VALIDATORS.put(MEDIA_BUTTON_RECEIVER, MEDIA_BUTTON_RECEIVER_VALIDATOR);
@@ -8277,7 +8288,6 @@
/**
* Whether to enable contacts metadata syncing or not
* The value 1 - enable, 0 - disable
- * @hide
*/
public static final String CONTACT_METADATA_SYNC = "contact_metadata_sync";
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index bb46e83..816ecde 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -15,9 +15,6 @@
*/
package android.service.dreams;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.Nullable;
@@ -33,27 +30,32 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.MathUtils;
import android.util.Slog;
import android.view.ActionMode;
import android.view.Display;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
-import com.android.internal.policy.PhoneWindow;
import android.view.SearchEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
-import android.util.MathUtils;
+import com.android.internal.policy.PhoneWindow;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils.Dump;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
/**
* Extend this class to implement a custom dream (available to the user as a "Daydream").
*
@@ -365,6 +367,11 @@
@Override
public void onActionModeFinished(ActionMode mode) {
}
+
+ /** {@inheritDoc} */
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ }
// end Window.Callback methods
// begin public api
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index aba82fa..035462d 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -95,6 +95,9 @@
/** Notification was canceled because it was an invisible member of a group. */
public static final int REASON_GROUP_OPTIMIZATION = 13;
+ /** Notification was canceled by the user banning the topic. */
+ public static final int REASON_TOPIC_BANNED = 14;
+
public class Adjustment {
int mImportance;
CharSequence mExplanation;
diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl
index 9991d41..4bfc9489 100644
--- a/core/java/android/service/quicksettings/IQSService.aidl
+++ b/core/java/android/service/quicksettings/IQSService.aidl
@@ -27,5 +27,9 @@
void updateStatusIcon(in Tile tile, in Icon icon,
String contentDescription);
void onShowDialog(in Tile tile);
+ void onStartActivity(in Tile tile);
void setTileMode(in ComponentName component, int mode);
+ boolean isLocked();
+ boolean isSecure();
+ void startUnlockAndRun(in Tile tile);
}
diff --git a/core/java/android/service/quicksettings/IQSTileService.aidl b/core/java/android/service/quicksettings/IQSTileService.aidl
index 4997f75..bfde870 100644
--- a/core/java/android/service/quicksettings/IQSTileService.aidl
+++ b/core/java/android/service/quicksettings/IQSTileService.aidl
@@ -29,4 +29,5 @@
void onStartListening();
void onStopListening();
void onClick(IBinder wtoken);
+ void onUnlockComplete();
}
diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java
index 6104913..85f1955 100644
--- a/core/java/android/service/quicksettings/Tile.java
+++ b/core/java/android/service/quicksettings/Tile.java
@@ -36,10 +36,37 @@
private static final String TAG = "Tile";
+ /**
+ * This is the default state of any tile, until updated by the {@link TileService}.
+ * <p>
+ * An unavailable state indicates that for some reason this tile is not currently
+ * available to the user for some reason, and will have no click action. The tile's
+ * icon will be tinted differently to reflect this state.
+ */
+ public static final int STATE_UNAVAILABLE = 0;
+
+ /**
+ * This represents a tile that is currently in a disabled state but is still interactable.
+ *
+ * A disabled state indicates that the tile is not currently active (e.g. wifi disconnected or
+ * bluetooth disabled), but is still interactable by the user to modify this state. Tiles
+ * that have boolean states should use this to represent one of their states. The tile's
+ * icon will be tinted differently to reflect this state, but still be distinct from unavailable.
+ */
+ public static final int STATE_INACTIVE = 1;
+
+ /**
+ * This represents a tile that is currently active. (e.g. wifi is connected, bluetooth is on,
+ * cast is casting).
+ */
+ public static final int STATE_ACTIVE = 2;
+
private ComponentName mComponentName;
private Icon mIcon;
private CharSequence mLabel;
private CharSequence mContentDescription;
+ // Default to active until clients of the new API can update.
+ private int mState = STATE_ACTIVE;
private IQSService mService;
@@ -79,6 +106,29 @@
}
/**
+ * The current state of the tile.
+ *
+ * @see #STATE_UNAVAILABLE
+ * @see #STATE_INACTIVE
+ * @see #STATE_ACTIVE
+ */
+ public int getState() {
+ return mState;
+ }
+
+ /**
+ * Sets the current state for the tile.
+ *
+ * Does not take effect until {@link #updateTile()} is called.
+ *
+ * @param state One of {@link #STATE_UNAVAILABLE}, {@link #STATE_INACTIVE},
+ * {@link #STATE_ACTIVE}
+ */
+ public void setState(int state) {
+ mState = state;
+ }
+
+ /**
* Gets the current icon for the tile.
*/
public Icon getIcon() {
@@ -165,6 +215,7 @@
} else {
dest.writeByte((byte) 0);
}
+ dest.writeInt(mState);
TextUtils.writeToParcel(mLabel, dest, flags);
TextUtils.writeToParcel(mContentDescription, dest, flags);
}
@@ -180,6 +231,7 @@
} else {
mIcon = null;
}
+ mState = source.readInt();
mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
}
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 6b12193..c02465b 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -118,6 +118,7 @@
private Tile mTile;
private IBinder mToken;
private IQSService mService;
+ private Runnable mUnlockRunnable;
@Override
public void onDestroy() {
@@ -199,6 +200,8 @@
* This will collapse the Quick Settings panel and show the dialog.
*
* @param dialog Dialog to show.
+ *
+ * @see #isLocked()
*/
public final void showDialog(Dialog dialog) {
dialog.getWindow().getAttributes().token = mToken;
@@ -211,6 +214,67 @@
}
/**
+ * Prompts the user to unlock the device before executing the Runnable.
+ * <p>
+ * The user will be prompted for their current security method if applicable
+ * and if successful, runnable will be executed. The Runnable will not be
+ * executed if the user fails to unlock the device or cancels the operation.
+ */
+ public final void unlockAndRun(Runnable runnable) {
+ mUnlockRunnable = runnable;
+ try {
+ mService.startUnlockAndRun(mTile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Checks if the device is in a secure state.
+ *
+ * TileServices should detect when the device is secure and change their behavior
+ * accordingly.
+ *
+ * @return true if the device is secure.
+ */
+ public final boolean isSecure() {
+ try {
+ return mService.isSecure();
+ } catch (RemoteException e) {
+ return true;
+ }
+ }
+
+ /**
+ * Checks if the lock screen is showing.
+ *
+ * When a device is locked, then {@link #showDialog} will not present a dialog, as it will
+ * be under the lock screen. If the behavior of the Tile is safe to do while locked,
+ * then the user should use {@link #startActivity} to launch an activity on top of the lock
+ * screen, otherwise the tile should use {@link #unlockAndRun(Runnable)} to give the
+ * user their security challenge.
+ *
+ * @return true if the device is locked.
+ */
+ public final boolean isLocked() {
+ try {
+ return mService.isLocked();
+ } catch (RemoteException e) {
+ return true;
+ }
+ }
+
+ /**
+ * Start an activity while collapsing the panel.
+ */
+ public final void startActivityAndCollapse(Intent intent) {
+ startActivity(intent);
+ try {
+ mService.onStartActivity(mTile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Gets the {@link Tile} for this service.
* <p/>
* This tile may be used to get or set the current state for this
@@ -258,6 +322,11 @@
public void onClick(IBinder wtoken) throws RemoteException {
mHandler.obtainMessage(H.MSG_TILE_CLICKED, wtoken).sendToTarget();
}
+
+ @Override
+ public void onUnlockComplete() throws RemoteException{
+ mHandler.sendEmptyMessage(H.MSG_UNLOCK_COMPLETE);
+ }
};
}
@@ -269,6 +338,7 @@
private static final int MSG_TILE_REMOVED = 5;
private static final int MSG_TILE_CLICKED = 6;
private static final int MSG_SET_SERVICE = 7;
+ private static final int MSG_UNLOCK_COMPLETE = 8;
public H(Looper looper) {
super(looper);
@@ -323,6 +393,11 @@
mToken = (IBinder) msg.obj;
TileService.this.onClick();
break;
+ case MSG_UNLOCK_COMPLETE:
+ if (mUnlockRunnable != null) {
+ mUnlockRunnable.run();
+ }
+ break;
}
}
}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index f9387b3..2c4241b 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1116,24 +1116,30 @@
public int getOffsetForHorizontal(int line, float horiz) {
// TODO: use Paint.getOffsetForAdvance to avoid binary search
final int lineEndOffset = getLineEnd(line);
+ final int lineStartOffset = getLineStart(line);
+
+ Directions dirs = getLineDirections(line);
+
+ TextLine tl = TextLine.obtain();
+ // XXX: we don't care about tabs as we just use TextLine#getOffsetToLeftRightOf here.
+ tl.set(mPaint, mText, lineStartOffset, lineEndOffset, getParagraphDirection(line), dirs,
+ false, null);
+
final int max;
if (line == getLineCount() - 1) {
max = lineEndOffset;
} else {
- max = mPaint.getTextRunCursor(mText, 0, mText.length(),
- isRtlCharAt(lineEndOffset) ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR,
- lineEndOffset, Paint.CURSOR_BEFORE);
+ max = tl.getOffsetToLeftRightOf(lineEndOffset - lineStartOffset,
+ !isRtlCharAt(lineEndOffset - 1)) + lineStartOffset;
}
- final int min = getLineStart(line);
- Directions dirs = getLineDirections(line);
-
- int best = min;
+ int best = lineStartOffset;
float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz);
for (int i = 0; i < dirs.mDirections.length; i += 2) {
- int here = min + dirs.mDirections[i];
+ int here = lineStartOffset + dirs.mDirections[i];
int there = here + (dirs.mDirections[i+1] & RUN_LENGTH_MASK);
- int swap = (dirs.mDirections[i+1] & RUN_RTL_FLAG) != 0 ? -1 : 1;
+ boolean isRtl = (dirs.mDirections[i+1] & RUN_RTL_FLAG) != 0;
+ int swap = isRtl ? -1 : 1;
if (there > max)
there = max;
@@ -1153,23 +1159,23 @@
low = here + 1;
if (low < there) {
- low = getOffsetAtStartOf(low);
+ int aft = tl.getOffsetToLeftRightOf(low - lineStartOffset, isRtl) + lineStartOffset;
+ low = tl.getOffsetToLeftRightOf(aft - lineStartOffset, !isRtl) + lineStartOffset;
+ if (low >= here && low < there) {
+ float dist = Math.abs(getPrimaryHorizontal(low) - horiz);
+ if (aft < there) {
+ float other = Math.abs(getPrimaryHorizontal(aft) - horiz);
- float dist = Math.abs(getPrimaryHorizontal(low) - horiz);
-
- int aft = TextUtils.getOffsetAfter(mText, low);
- if (aft < there) {
- float other = Math.abs(getPrimaryHorizontal(aft) - horiz);
-
- if (other < dist) {
- dist = other;
- low = aft;
+ if (other < dist) {
+ dist = other;
+ low = aft;
+ }
}
- }
- if (dist < bestdist) {
- bestdist = dist;
- best = low;
+ if (dist < bestdist) {
+ bestdist = dist;
+ best = low;
+ }
}
}
@@ -1188,6 +1194,7 @@
best = max;
}
+ TextLine.recycle(tl);
return best;
}
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index c42c791..2a52961 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -688,13 +688,14 @@
* @param bottom the bottom of the line
* @param fmi receives metrics information, can be null
* @param needWidth true if the width of the run is needed
+ * @param offset the offset for the purpose of measuring
* @return the signed width of the run based on the run direction; only
* valid if needWidth is true
*/
private float handleText(TextPaint wp, int start, int end,
int contextStart, int contextEnd, boolean runIsRtl,
Canvas c, float x, int top, int y, int bottom,
- FontMetricsInt fmi, boolean needWidth) {
+ FontMetricsInt fmi, boolean needWidth, int offset) {
// Get metrics first (even for empty strings or "0" width runs)
if (fmi != null) {
@@ -712,11 +713,11 @@
if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) {
if (mCharsValid) {
ret = wp.getRunAdvance(mChars, start, end, contextStart, contextEnd,
- runIsRtl, end);
+ runIsRtl, offset);
} else {
int delta = mStart;
ret = wp.getRunAdvance(mText, delta + start, delta + end,
- delta + contextStart, delta + contextEnd, runIsRtl, delta + end);
+ delta + contextStart, delta + contextEnd, runIsRtl, delta + offset);
}
}
@@ -865,8 +866,8 @@
TextPaint wp = mWorkPaint;
wp.set(mPaint);
final int mlimit = measureLimit;
- return handleText(wp, start, mlimit, start, limit, runIsRtl, c, x, top,
- y, bottom, fmi, needWidth || mlimit < measureLimit);
+ return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top,
+ y, bottom, fmi, needWidth || mlimit < measureLimit, mlimit);
}
mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
@@ -910,13 +911,14 @@
}
for (int j = i, jnext; j < mlimit; j = jnext) {
- jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
+ jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + inext) -
mStart;
+ int offset = Math.min(jnext, mlimit);
wp.set(mPaint);
for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
// Intentionally using >= and <= as explained above
- if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
+ if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + offset) ||
(mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
CharacterStyle span = mCharacterStyleSpanSet.spans[k];
@@ -928,7 +930,7 @@
wp.setHyphenEdit(0);
}
x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
- top, y, bottom, fmi, needWidth || jnext < measureLimit);
+ top, y, bottom, fmi, needWidth || jnext < measureLimit, offset);
}
}
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index f22cde0..24883e3 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -16,6 +16,7 @@
package android.util;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
@@ -56,10 +57,21 @@
return mList.length == 0;
}
+ @IntRange(from=0)
public int size() {
return mList.length;
}
+ @IntRange(from=-1)
+ public int indexOf(Locale locale) {
+ for (int i = 0; i < mList.length; i++) {
+ if (mList[i].equals(locale)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
@Override
public boolean equals(Object other) {
if (other == this)
@@ -69,7 +81,7 @@
final Locale[] otherList = ((LocaleList) other).mList;
if (mList.length != otherList.length)
return false;
- for (int i = 0; i < mList.length; ++i) {
+ for (int i = 0; i < mList.length; i++) {
if (!mList[i].equals(otherList[i]))
return false;
}
@@ -79,7 +91,7 @@
@Override
public int hashCode() {
int result = 1;
- for (int i = 0; i < mList.length; ++i) {
+ for (int i = 0; i < mList.length; i++) {
result = 31 * result + mList[i].hashCode();
}
return result;
@@ -89,7 +101,7 @@
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
- for (int i = 0; i < mList.length; ++i) {
+ for (int i = 0; i < mList.length; i++) {
sb.append(mList[i]);
if (i < mList.length - 1) {
sb.append(',');
@@ -150,12 +162,12 @@
final Locale[] localeList = new Locale[list.length];
final HashSet<Locale> seenLocales = new HashSet<Locale>();
final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < list.length; ++i) {
+ for (int i = 0; i < list.length; i++) {
final Locale l = list[i];
if (l == null) {
- throw new NullPointerException();
+ throw new NullPointerException("list[" + i + "] is null");
} else if (seenLocales.contains(l)) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("list[" + i + "] is a repetition");
} else {
final Locale localeClone = (Locale) l.clone();
localeList[i] = localeClone;
@@ -171,6 +183,55 @@
}
}
+ /**
+ * Constructs a locale list, with the topLocale moved to the front if it already is
+ * in otherLocales, or added to the front if it isn't.
+ *
+ * {@hide}
+ */
+ public LocaleList(@NonNull Locale topLocale, LocaleList otherLocales) {
+ if (topLocale == null) {
+ throw new NullPointerException("topLocale is null");
+ }
+
+ final int inputLength = (otherLocales == null) ? 0 : otherLocales.mList.length;
+ int topLocaleIndex = -1;
+ for (int i = 0; i < inputLength; i++) {
+ if (topLocale.equals(otherLocales.mList[i])) {
+ topLocaleIndex = i;
+ break;
+ }
+ }
+
+ final int outputLength = inputLength + (topLocaleIndex == -1 ? 1 : 0);
+ final Locale[] localeList = new Locale[outputLength];
+ localeList[0] = (Locale) topLocale.clone();
+ if (topLocaleIndex == -1) {
+ // topLocale was not in otherLocales
+ for (int i = 0; i < inputLength; i++) {
+ localeList[i + 1] = (Locale) otherLocales.mList[i].clone();
+ }
+ } else {
+ for (int i = 0; i < topLocaleIndex; i++) {
+ localeList[i + 1] = (Locale) otherLocales.mList[i].clone();
+ }
+ for (int i = topLocaleIndex + 1; i < inputLength; i++) {
+ localeList[i] = (Locale) otherLocales.mList[i].clone();
+ }
+ }
+
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < outputLength; i++) {
+ sb.append(localeList[i].toLanguageTag());
+ if (i < outputLength - 1) {
+ sb.append(',');
+ }
+ }
+
+ mList = localeList;
+ mStringRepresentation = sb.toString();
+ }
+
public static final Parcelable.Creator<LocaleList> CREATOR
= new Parcelable.Creator<LocaleList>() {
@Override
@@ -196,7 +257,7 @@
} else {
final String[] tags = list.split(",");
final Locale[] localeArray = new Locale[tags.length];
- for (int i = 0; i < localeArray.length; ++i) {
+ for (int i = 0; i < localeArray.length; i++) {
localeArray[i] = Locale.forLanguageTag(tags[i]);
}
return new LocaleList(localeArray);
@@ -227,6 +288,7 @@
return LOCALE_EN_XA.equals(locale) || LOCALE_AR_XB.equals(locale);
}
+ @IntRange(from=0, to=1)
private static int matchScore(Locale supported, Locale desired) {
if (supported.equals(desired)) {
return 1; // return early so we don't do unnecessary computation
@@ -330,18 +392,79 @@
private final static Object sLock = new Object();
@GuardedBy("sLock")
- private static LocaleList sDefaultLocaleList;
+ private static LocaleList sLastExplicitlySetLocaleList = null;
+ @GuardedBy("sLock")
+ private static LocaleList sDefaultLocaleList = null;
+ @GuardedBy("sLock")
+ private static Locale sLastDefaultLocale = null;
- // TODO: fix this to return the default system locale list once we have that
+ /**
+ * The result is guaranteed to include the default Locale returned by Locale.getDefault(), but
+ * not necessarily at the top of the list. The default locale not being at the top of the list
+ * is an indication that the system has set the default locale to one of the user's other
+ * preferred locales, having concluded that the primary preference is not supported but a
+ * secondary preference is.
+ *
+ * Note that the default LocaleList would change if Locale.setDefault() is called. This method
+ * takes that into account by always checking the output of Locale.getDefault() and adjusting
+ * the default LocaleList if needed.
+ */
@NonNull @Size(min=1)
public static LocaleList getDefault() {
- Locale defaultLocale = Locale.getDefault();
+ final Locale defaultLocale = Locale.getDefault();
synchronized (sLock) {
- if (sDefaultLocaleList == null || sDefaultLocaleList.size() != 1
- || !defaultLocale.equals(sDefaultLocaleList.getPrimary())) {
- sDefaultLocaleList = new LocaleList(defaultLocale);
+ if (!defaultLocale.equals(sLastDefaultLocale)) {
+ sLastDefaultLocale = defaultLocale;
+ // It's either the first time someone has asked for the default locale list, or
+ // someone has called Locale.setDefault() since we last set or adjusted the default
+ // locale list. So let's adjust the locale list.
+ if (sDefaultLocaleList != null
+ && defaultLocale.equals(sDefaultLocaleList.getPrimary())) {
+ // The default Locale has changed, but it happens to be the first locale in the
+ // default locale list, so we don't need to construct a new locale list.
+ return sDefaultLocaleList;
+ }
+ sDefaultLocaleList = new LocaleList(defaultLocale, sLastExplicitlySetLocaleList);
}
+ // sDefaultLocaleList can't be null, since it can't be set to null by
+ // LocaleList.setDefault(), and if getDefault() is called before a call to
+ // setDefault(), sLastDefaultLocale would be null and the check above would set
+ // sDefaultLocaleList.
+ return sDefaultLocaleList;
}
- return sDefaultLocaleList;
+ }
+
+ /**
+ * Also sets the default locale by calling Locale.setDefault() with the first locale in the
+ * list.
+ *
+ * @throws NullPointerException if the input is <code>null</code>.
+ * @throws IllegalArgumentException if the input is empty.
+ */
+ public static void setDefault(@NonNull @Size(min=1) LocaleList locales) {
+ setDefault(locales, 0);
+ }
+
+ /**
+ * This may be used directly by system processes to set the default locale list for apps. For
+ * such uses, the default locale list would always come from the user preferences, but the
+ * default locale may have been chosen to be a locale other than the first locale in the locale
+ * list (based on the locales the app supports).
+ *
+ * {@hide}
+ */
+ public static void setDefault(@NonNull @Size(min=1) LocaleList locales, int localeIndex) {
+ if (locales == null) {
+ throw new NullPointerException("locales is null");
+ }
+ if (locales.isEmpty()) {
+ throw new IllegalArgumentException("locales is empty");
+ }
+ synchronized (sLock) {
+ sLastDefaultLocale = locales.get(localeIndex);
+ Locale.setDefault(sLastDefaultLocale);
+ sLastExplicitlySetLocaleList = locales;
+ sDefaultLocaleList = locales;
+ }
}
}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 9e478c1..9231394 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -25,6 +25,8 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
+import com.android.internal.os.IResultReceiver;
+
/**
* API back to a client window that the Window Manager uses to inform it of
* interesting things happening.
@@ -83,4 +85,9 @@
* Called for non-application windows when the enter animation has completed.
*/
void dispatchWindowShown();
+
+ /**
+ * Called when Keyboard Shortcuts are requested for the window.
+ */
+ void requestAppKeyboardShortcuts(IResultReceiver receiver);
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 84d312d..b045c17a 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -17,6 +17,7 @@
package android.view;
import com.android.internal.app.IAssistScreenshotReceiver;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -370,4 +371,11 @@
* @param alpha The translucency of the dim layer, between 0 and 1.
*/
void setResizeDimLayer(boolean visible, int targetStackId, float alpha);
+
+ /**
+ * Requests Keyboard Shortcuts from the displayed window.
+ *
+ * @param receiver The receiver to deliver the results to.
+ */
+ void requestAppKeyboardShortcuts(IResultReceiver receiver);
}
diff --git a/core/java/android/view/KeyboardShortcutGroup.java b/core/java/android/view/KeyboardShortcutGroup.java
new file mode 100644
index 0000000..013255b
--- /dev/null
+++ b/core/java/android/view/KeyboardShortcutGroup.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+/**
+ * A group of {@link KeyboardShortcutInfo}.
+ */
+public final class KeyboardShortcutGroup implements Parcelable {
+ private final CharSequence mLabel;
+ private final List<KeyboardShortcutInfo> mItems;
+
+ /**
+ * @param label The title to be used for this group, or null if there is none.
+ * @param items The set of items to be included.
+ */
+ public KeyboardShortcutGroup(@Nullable CharSequence label,
+ @NonNull List<KeyboardShortcutInfo> items) {
+ mLabel = label;
+ mItems = new ArrayList<>(checkNotNull(items));
+ }
+
+ /**
+ * @param label The title to be used for this group, or null if there is none.
+ */
+ public KeyboardShortcutGroup(@Nullable CharSequence label) {
+ this(label, Collections.<KeyboardShortcutInfo>emptyList());
+ }
+
+ private KeyboardShortcutGroup(Parcel source) {
+ mItems = new ArrayList<>();
+ mLabel = source.readCharSequence();
+ source.readTypedList(mItems, KeyboardShortcutInfo.CREATOR);
+ }
+
+ /**
+ * Returns the label to be used to describe this group.
+ */
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Returns the list of items included in this group.
+ */
+ public List<KeyboardShortcutInfo> getItems() {
+ return mItems;
+ }
+
+ /**
+ * Adds an item to the existing list.
+ *
+ * @param item The item to be added.
+ */
+ public void addItem(KeyboardShortcutInfo item) {
+ mItems.add(item);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharSequence(mLabel);
+ dest.writeTypedList(mItems);
+ }
+
+ public static final Creator<KeyboardShortcutGroup> CREATOR =
+ new Creator<KeyboardShortcutGroup>() {
+ public KeyboardShortcutGroup createFromParcel(Parcel source) {
+ return new KeyboardShortcutGroup(source);
+ }
+ public KeyboardShortcutGroup[] newArray(int size) {
+ return new KeyboardShortcutGroup[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/core/java/android/view/KeyboardShortcutInfo.java b/core/java/android/view/KeyboardShortcutInfo.java
new file mode 100644
index 0000000..2c9006d
--- /dev/null
+++ b/core/java/android/view/KeyboardShortcutInfo.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view;
+
+import android.annotation.Nullable;
+import android.graphics.drawable.Icon;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+import static java.lang.Character.MIN_VALUE;
+
+/**
+ * Information about a Keyboard Shortcut.
+ */
+public final class KeyboardShortcutInfo implements Parcelable {
+ private final CharSequence mLabel;
+ private final Icon mIcon;
+ private final char mBaseCharacter;
+ private final int mModifiers;
+
+ /**
+ * @param label The label that identifies the action performed by this shortcut.
+ * @param icon An icon that identifies the action performed by this shortcut.
+ * @param baseCharacter The character that triggers the shortcut.
+ * @param modifiers The set of modifiers that, combined with the key, trigger the shortcut.
+ * These should be a combination of {@link KeyEvent#META_CTRL_ON},
+ * {@link KeyEvent#META_SHIFT_ON}, {@link KeyEvent#META_META_ON} and
+ * {@link KeyEvent#META_ALT_ON}.
+ *
+ * @hide
+ */
+ public KeyboardShortcutInfo(
+ @Nullable CharSequence label, @Nullable Icon icon, char baseCharacter, int modifiers) {
+ mLabel = label;
+ mIcon = icon;
+ checkArgument(baseCharacter != MIN_VALUE);
+ mBaseCharacter = baseCharacter;
+ mModifiers = modifiers;
+ }
+
+ /**
+ * Convenience constructor for shortcuts with a label and no icon.
+ *
+ * @param label The label that identifies the action performed by this shortcut.
+ * @param baseCharacter The character that triggers the shortcut.
+ * @param modifiers The set of modifiers that, combined with the key, trigger the shortcut.
+ * These should be a combination of {@link KeyEvent#META_CTRL_ON},
+ * {@link KeyEvent#META_SHIFT_ON}, {@link KeyEvent#META_META_ON} and
+ * {@link KeyEvent#META_ALT_ON}.
+ */
+ public KeyboardShortcutInfo(CharSequence label, char baseCharacter, int modifiers) {
+ mLabel = label;
+ checkArgument(baseCharacter != MIN_VALUE);
+ mBaseCharacter = baseCharacter;
+ mModifiers = modifiers;
+ mIcon = null;
+ }
+
+ private KeyboardShortcutInfo(Parcel source) {
+ mLabel = source.readCharSequence();
+ mIcon = (Icon) source.readParcelable(null);
+ mBaseCharacter = (char) source.readInt();
+ mModifiers = source.readInt();
+ }
+
+ /**
+ * Returns the label to be used to describe this shortcut.
+ */
+ @Nullable
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Returns the icon to be used to describe this shortcut.
+ *
+ * @hide
+ */
+ @Nullable
+ public Icon getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * Returns the base character that, combined with the modifiers, triggers this shortcut.
+ */
+ public char getBaseCharacter() {
+ return mBaseCharacter;
+ }
+
+ /**
+ * Returns the set of modifiers that, combined with the key, trigger this shortcut.
+ */
+ public int getModifiers() {
+ return mModifiers;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharSequence(mLabel);
+ dest.writeParcelable(mIcon, 0);
+ dest.writeInt(mBaseCharacter);
+ dest.writeInt(mModifiers);
+ }
+
+ public static final Creator<KeyboardShortcutInfo> CREATOR =
+ new Creator<KeyboardShortcutInfo>() {
+ public KeyboardShortcutInfo createFromParcel(Parcel source) {
+ return new KeyboardShortcutInfo(source);
+ }
+ public KeyboardShortcutInfo[] newArray(int size) {
+ return new KeyboardShortcutInfo[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 68f1ac3..5559d4d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -79,10 +79,11 @@
import android.util.SuperNotCalledException;
import android.util.TypedValue;
import android.view.ContextMenu.ContextMenuInfo;
-import android.view.AccessibilityIterators.TextSegmentIterator;
import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
-import android.view.AccessibilityIterators.WordTextSegmentIterator;
import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
+import android.view.AccessibilityIterators.TextSegmentIterator;
+import android.view.AccessibilityIterators.WordTextSegmentIterator;
+import android.view.ViewGroup.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
import android.view.accessibility.AccessibilityManager;
@@ -21715,6 +21716,13 @@
}
/**
+ * @hide
+ */
+ public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data) {
+ // Do nothing.
+ }
+
+ /**
* Interface definition for a callback to be invoked when a hardware key event is
* dispatched to this view. The callback will be invoked before the key event is
* given to the view. This is only useful for hardware keyboards; a software input
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1c24392..f674298 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5359,6 +5359,9 @@
void offsetRectBetweenParentAndChild(View descendant, Rect rect,
boolean offsetFromChildToParent, boolean clipToBounds) {
+ final RectF rectF = mAttachInfo != null ? mAttachInfo.mTmpTransformRect1 : new RectF();
+ final Matrix inverse = mAttachInfo != null ? mAttachInfo.mTmpMatrix : new Matrix();
+
// already in the same coord system :)
if (descendant == this) {
return;
@@ -5372,8 +5375,16 @@
&& (theParent != this)) {
if (offsetFromChildToParent) {
- rect.offset(descendant.mLeft - descendant.mScrollX,
- descendant.mTop - descendant.mScrollY);
+ rect.offset(-descendant.mScrollX, -descendant.mScrollY);
+
+ if (!descendant.hasIdentityMatrix()) {
+ rectF.set(rect);
+ descendant.getMatrix().mapRect(rectF);
+ rectF.roundOut(rect);
+ }
+
+ rect.offset(descendant.mLeft, descendant.mTop);
+
if (clipToBounds) {
View p = (View) theParent;
boolean intersected = rect.intersect(0, 0, p.mRight - p.mLeft,
@@ -5391,8 +5402,16 @@
rect.setEmpty();
}
}
- rect.offset(descendant.mScrollX - descendant.mLeft,
- descendant.mScrollY - descendant.mTop);
+ rect.offset(-descendant.mLeft, -descendant.mTop);
+
+ if (!descendant.hasIdentityMatrix()) {
+ descendant.getMatrix().invert(inverse);
+ rectF.set(rect);
+ inverse.mapRect(rectF);
+ rectF.roundOut(rect);
+ }
+
+ rect.offset(descendant.mScrollX, descendant.mScrollY);
}
descendant = (View) theParent;
@@ -5403,11 +5422,26 @@
// to get into our coordinate space
if (theParent == this) {
if (offsetFromChildToParent) {
- rect.offset(descendant.mLeft - descendant.mScrollX,
- descendant.mTop - descendant.mScrollY);
+ rect.offset(-descendant.mScrollX, -descendant.mScrollY);
+
+ if (!descendant.hasIdentityMatrix()) {
+ rectF.set(rect);
+ descendant.getMatrix().mapRect(rectF);
+ rectF.roundOut(rect);
+ }
+
+ rect.offset(descendant.mLeft, descendant.mTop);
} else {
- rect.offset(descendant.mScrollX - descendant.mLeft,
- descendant.mScrollY - descendant.mTop);
+ rect.offset(-descendant.mLeft, -descendant.mTop);
+
+ if (!descendant.hasIdentityMatrix()) {
+ descendant.getMatrix().invert(inverse);
+ rectF.set(rect);
+ inverse.mapRect(rectF);
+ rectF.roundOut(rect);
+ }
+
+ rect.offset(descendant.mScrollX, descendant.mScrollY);
}
} else {
throw new IllegalArgumentException("parameter must be a descendant of this view");
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0fb3951..a14f0dc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -79,6 +79,7 @@
import android.widget.Scroller;
import com.android.internal.R;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
import com.android.internal.policy.PhoneFallbackEventHandler;
import com.android.internal.view.BaseSurfaceHolder;
@@ -1488,7 +1489,8 @@
if ((lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
|| lp.height == ViewGroup.LayoutParams.WRAP_CONTENT)
&& (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL
- || lp.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD)) {
+ || lp.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
+ || lp.type == WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)) {
windowSizeMayChange = true;
// NOTE -- system code, won't try to do compat mode.
Point size = new Point();
@@ -3234,6 +3236,7 @@
private final static int MSG_WINDOW_MOVED = 23;
private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24;
private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
+ private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
final class ViewRootHandler extends Handler {
@Override
@@ -3510,7 +3513,11 @@
} break;
case MSG_DISPATCH_WINDOW_SHOWN: {
handleDispatchWindowShown();
- }
+ } break;
+ case MSG_REQUEST_KEYBOARD_SHORTCUTS: {
+ IResultReceiver receiver = (IResultReceiver) msg.obj;
+ handleRequestKeyboardShortcuts(receiver);
+ } break;
}
}
}
@@ -5403,6 +5410,19 @@
mAttachInfo.mTreeObserver.dispatchOnWindowShown();
}
+ public void handleRequestKeyboardShortcuts(IResultReceiver receiver) {
+ Bundle data = new Bundle();
+ ArrayList<KeyboardShortcutGroup> list = new ArrayList<>();
+ if (mView != null) {
+ mView.requestKeyboardShortcuts(list);
+ }
+ data.putParcelableArrayList(WindowManager.PARCEL_KEY_SHORTCUTS_ARRAY, list);
+ try {
+ receiver.send(0, data);
+ } catch (RemoteException e) {
+ }
+ }
+
public void getLastTouchPoint(Point outLocation) {
outLocation.x = (int) mLastTouchPoint.x;
outLocation.y = (int) mLastTouchPoint.y;
@@ -6332,6 +6352,10 @@
}
}
+ public void dispatchRequestKeyboardShortcuts(IResultReceiver receiver) {
+ mHandler.obtainMessage(MSG_REQUEST_KEYBOARD_SHORTCUTS, receiver).sendToTarget();
+ }
+
/**
* Post a callback to send a
* {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
@@ -6905,6 +6929,14 @@
viewAncestor.dispatchWindowShown();
}
}
+
+ @Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) {
+ ViewRootImpl viewAncestor = mViewAncestor.get();
+ if (viewAncestor != null) {
+ viewAncestor.dispatchRequestKeyboardShortcuts(receiver);
+ }
+ }
}
public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0b06d15..d89369b 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -42,6 +42,8 @@
import android.transition.TransitionManager;
import android.view.accessibility.AccessibilityEvent;
+import java.util.List;
+
/**
* Abstract base class for a top-level window look and behavior policy. An
* instance of this class should be used as the top-level view added to the
@@ -556,6 +558,15 @@
* @param mode The mode that was just finished.
*/
public void onActionModeFinished(ActionMode mode);
+
+ /**
+ * Called when Keyboard Shortcuts are requested for the current window.
+ *
+ * @param data The data list to populate with shortcuts.
+ * @param menu The current menu, which may be null.
+ */
+ public void onProvideKeyboardShortcuts(
+ List<KeyboardShortcutGroup> data, @Nullable Menu menu);
}
/** @hide */
diff --git a/core/java/android/view/WindowCallbackWrapper.java b/core/java/android/view/WindowCallbackWrapper.java
index 8ce1f8c..bed74e9 100644
--- a/core/java/android/view/WindowCallbackWrapper.java
+++ b/core/java/android/view/WindowCallbackWrapper.java
@@ -19,6 +19,8 @@
import android.view.accessibility.AccessibilityEvent;
+import java.util.List;
+
/**
* A simple decorator stub for Window.Callback that passes through any calls
* to the wrapped instance as a base implementation. Call super.foo() to call into
@@ -150,5 +152,10 @@
public void onActionModeFinished(ActionMode mode) {
mWrapped.onActionModeFinished(mode);
}
+
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ mWrapped.onProvideKeyboardShortcuts(data, menu);
+ }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 251f4c8..772eeec 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -29,6 +29,8 @@
import android.text.TextUtils;
import android.util.Log;
+import java.util.List;
+
/**
* The interface that apps use to talk to the window manager.
@@ -118,6 +120,34 @@
*/
public void removeViewImmediate(View view);
+ /**
+ * Used to asynchronously request Keyboard Shortcuts from the focused window.
+ *
+ * @hide
+ */
+ public interface KeyboardShortcutsReceiver {
+ /**
+ * Callback used when the focused window keyboard shortcuts are ready to be displayed.
+ *
+ * @param result The keyboard shortcuts to be displayed.
+ */
+ void onKeyboardShortcutsReceived(List<KeyboardShortcutGroup> result);
+ }
+
+ /**
+ * @hide
+ */
+ public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array";
+
+ /**
+ * Request for keyboard shortcuts to be retrieved asynchronously.
+ *
+ * @param receiver The callback to be triggered when the result is ready.
+ *
+ * @hide
+ */
+ public void requestAppKeyboardShortcuts(final KeyboardShortcutsReceiver receiver);
+
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
/**
* X position for this window. With the default gravity it is ignored.
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 98e9f54..6e11671 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,7 +17,15 @@
package android.view;
import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.os.IResultReceiver;
+import com.android.internal.R;
+
+import java.util.List;
/**
* Provides low-level communication with the system window manager for
@@ -117,6 +125,23 @@
}
@Override
+ public void requestAppKeyboardShortcuts(final KeyboardShortcutsReceiver receiver) {
+ IResultReceiver resultReceiver = new IResultReceiver.Stub() {
+ @Override
+ public void send(int resultCode, Bundle resultData) throws RemoteException {
+ List<KeyboardShortcutGroup> result =
+ resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY);
+ receiver.onKeyboardShortcutsReceived(result);
+ }
+ };
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .requestAppKeyboardShortcuts(resultReceiver);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
public Display getDefaultDisplay() {
return mDisplay;
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index ecec258..a78b56a 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1328,4 +1328,15 @@
* @param fadeoutDuration the duration of the exit animation, in milliseconds
*/
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
+
+ /**
+ * Calculates the stable insets without running a layout.
+ *
+ * @param displayRotation the current display rotation
+ * @param outInsets the insets to return
+ * @param displayWidth the current display width
+ * @param displayHeight the current display height
+ */
+ public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
+ Rect outInsets);
}
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index e0dbe2f..1536c29 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -850,7 +850,7 @@
normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
}
- final boolean expired = normalizedTime >= 1.0f;
+ final boolean expired = normalizedTime >= 1.0f || isCanceled();
mMore = !expired;
if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
@@ -875,7 +875,7 @@
}
if (expired) {
- if (mRepeatCount == mRepeated) {
+ if (mRepeatCount == mRepeated || isCanceled()) {
if (!mEnded) {
mEnded = true;
guard.close();
@@ -905,6 +905,10 @@
return mMore;
}
+ private boolean isCanceled() {
+ return mStartTime == Long.MIN_VALUE;
+ }
+
private void fireAnimationStart() {
if (mListener != null) {
if (mListenerHandler == null) mListener.onAnimationStart(this);
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index ba5d6c2..6e5e591 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -201,10 +201,17 @@
}
/**
- * The default implementation performs the deletion around the current
- * selection position of the editable text.
- * @param beforeLength
- * @param afterLength
+ * The default implementation performs the deletion around the current selection position of the
+ * editable text.
+ *
+ * @param beforeLength The number of characters before the cursor to be deleted, in code unit.
+ * If this is greater than the number of existing characters between the beginning of the
+ * text and the cursor, then this method does not fail but deletes all the characters in
+ * that range.
+ * @param afterLength The number of characters after the cursor to be deleted, in code unit.
+ * If this is greater than the number of existing characters between the cursor and
+ * the end of the text, then this method does not fail but deletes all the characters in
+ * that range.
*/
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
if (DEBUG) Log.v(TAG, "deleteSurroundingText " + beforeLength
@@ -213,7 +220,7 @@
if (content == null) return false;
beginBatchEdit();
-
+
int a = Selection.getSelectionStart(content);
int b = Selection.getSelectionEnd(content);
@@ -253,9 +260,9 @@
content.delete(b, end);
}
-
+
endBatchEdit();
-
+
return true;
}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index ff992d3..be7bc14 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -335,12 +335,15 @@
* but be careful to wait until the batch edit is over if one is
* in progress.</p>
*
- * @param beforeLength The number of characters to be deleted before the
- * current cursor position.
- * @param afterLength The number of characters to be deleted after the
- * current cursor position.
- * @return true on success, false if the input connection is no longer
- * valid.
+ * @param beforeLength The number of characters before the cursor to be deleted, in code unit.
+ * If this is greater than the number of existing characters between the beginning of the
+ * text and the cursor, then this method does not fail but deletes all the characters in
+ * that range.
+ * @param afterLength The number of characters after the cursor to be deleted, in code unit.
+ * If this is greater than the number of existing characters between the cursor and
+ * the end of the text, then this method does not fail but deletes all the characters in
+ * that range.
+ * @return true on success, false if the input connection is no longer valid.
*/
public boolean deleteSurroundingText(int beforeLength, int afterLength);
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 9f08b21..054eafc 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -131,6 +131,8 @@
private static String TAG_WEBVIEW_PROVIDER = "webviewprovider";
private static String TAG_PACKAGE_NAME = "packageName";
private static String TAG_DESCRIPTION = "description";
+ // Whether or not the provider must be explicitly chosen by the user to be used.
+ private static String TAG_AVAILABILITY = "availableByDefault";
private static String TAG_SIGNATURE = "signature";
/**
@@ -180,8 +182,12 @@
throw new MissingWebViewPackageException(
"WebView provider in framework resources missing description");
}
+ String availableByDefault = parser.getAttributeValue(null, TAG_AVAILABILITY);
+ if (availableByDefault == null) {
+ availableByDefault = "false";
+ }
webViewProviders.add(
- new WebViewProviderInfo(packageName, description,
+ new WebViewProviderInfo(packageName, description, availableByDefault,
readSignatures(parser)));
}
else {
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index 7bad652..3f50fe2 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -40,9 +40,11 @@
public WebViewPackageNotFoundException(Exception e) { super(e); }
}
- public WebViewProviderInfo(String packageName, String description, String[] signatures) {
+ public WebViewProviderInfo(String packageName, String description, String availableByDefault,
+ String[] signatures) {
this.packageName = packageName;
this.description = description;
+ this.availableByDefault = availableByDefault.equals("true");
this.signatures = signatures;
}
@@ -89,6 +91,39 @@
return false;
}
+ /**
+ * Returns whether this package is enabled.
+ * This state can be changed by the user from Settings->Apps
+ */
+ public boolean isEnabled() {
+ try {
+ PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+ int enabled_state = pm.getApplicationEnabledSetting(packageName);
+ switch (enabled_state) {
+ case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
+ return true;
+ case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
+ ApplicationInfo applicationInfo = getPackageInfo().applicationInfo;
+ return applicationInfo.enabled;
+ default:
+ return false;
+ }
+ } catch (WebViewPackageNotFoundException e) {
+ return false;
+ } catch (IllegalArgumentException e) {
+ // Thrown by PackageManager.getApplicationEnabledSetting if the package does not exist
+ return false;
+ }
+ }
+
+ /**
+ * Returns whether the provider is always available as long as it is valid.
+ * If this returns false, the provider will only be used if the user chose this provider.
+ */
+ public boolean isAvailableByDefault() {
+ return availableByDefault;
+ }
+
public PackageInfo getPackageInfo() {
if (packageInfo == null) {
try {
@@ -135,13 +170,13 @@
// fields read from framework resource
public String packageName;
public String description;
+ private boolean availableByDefault;
private String[] signatures;
private PackageInfo packageInfo;
- // flags declaring we want extra info from the package manager
- private final static int PACKAGE_FLAGS =
- PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNATURES;
-}
+ // flags declaring we want extra info from the package manager
+ private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
+ | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+}
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 831481dd..4ca8971 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -142,6 +142,7 @@
}
applyThumbTint();
+ applyTickMarkTint();
mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 48d1d2b..ac8d578 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -59,7 +59,6 @@
*/
public class ActionMenuPresenter extends BaseMenuPresenter
implements ActionProvider.SubUiVisibilityListener {
- private static final String TAG = "ActionMenuPresenter";
private static final int ITEM_ANIMATION_DURATION = 150;
private static final boolean ACTIONBAR_ANIMATIONS_ENABLED = false;
@@ -87,20 +86,16 @@
private OpenOverflowRunnable mPostedOpenRunnable;
private ActionMenuPopupCallback mPopupCallback;
- private final boolean mShowCascadingMenus;
-
final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
int mOpenSubMenuId;
// These collections are used to store pre- and post-layout information for menu items,
// which is used to determine appropriate animations to run for changed items.
- private SparseArray<MenuItemLayoutInfo> mPreLayoutItems =
- new SparseArray<MenuItemLayoutInfo>();
- private SparseArray<MenuItemLayoutInfo> mPostLayoutItems =
- new SparseArray<MenuItemLayoutInfo>();
+ private SparseArray<MenuItemLayoutInfo> mPreLayoutItems = new SparseArray<>();
+ private SparseArray<MenuItemLayoutInfo> mPostLayoutItems = new SparseArray<>();
// The list of currently running animations on menu items.
- private List<ItemAnimationInfo> mRunningItemAnimations = new ArrayList<ItemAnimationInfo>();
+ private List<ItemAnimationInfo> mRunningItemAnimations = new ArrayList<>();
private ViewTreeObserver.OnPreDrawListener mItemAnimationPreDrawListener =
new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -130,9 +125,6 @@
public ActionMenuPresenter(Context context) {
super(context, com.android.internal.R.layout.action_menu_layout,
com.android.internal.R.layout.action_menu_item_layout);
-
- mShowCascadingMenus = context.getResources().getBoolean(
- com.android.internal.R.bool.config_enableCascadingSubmenus);
}
@Override
@@ -845,8 +837,6 @@
}
private class OverflowMenuButton extends ImageButton implements ActionMenuView.ActionMenuChildView {
- private final float[] mTempPts = new float[2];
-
public OverflowMenuButton(Context context) {
super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 15cea77..1576877 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -82,6 +82,7 @@
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.RenderNode;
+import android.view.SubMenu;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnClickListener;
@@ -285,6 +286,9 @@
boolean mIsInsertionActionModeStartPending = false;
+ private final SuggestionHelper mSuggestionHelper = new SuggestionHelper();
+ private SuggestionInfo[] mSuggestionInfosInContextMenu;
+
Editor(TextView textView) {
mTextView = textView;
// Synchronize the filter list, which places the undo input filter at the end.
@@ -2369,6 +2373,9 @@
if (offset == -1) {
return;
}
+ mPreserveDetachedSelection = true;
+ stopTextActionMode();
+ mPreserveDetachedSelection = false;
final boolean isOnSelection = mTextView.hasSelection()
&& offset >= mTextView.getSelectionStart() && offset <= mTextView.getSelectionEnd();
if (!isOnSelection) {
@@ -2378,7 +2385,24 @@
Selection.setSelection((Spannable) mTextView.getText(), offset);
}
- // TODO: Add suggestions in the context menu.
+ if (shouldOfferToShowSuggestions()) {
+ if (mSuggestionInfosInContextMenu == null) {
+ mSuggestionInfosInContextMenu =
+ new SuggestionInfo[SuggestionSpan.SUGGESTIONS_MAX_SIZE];
+ for (int i = 0; i < mSuggestionInfosInContextMenu.length; i++) {
+ mSuggestionInfosInContextMenu[i] = new SuggestionInfo();
+ }
+ }
+ final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE, MENU_ITEM_ORDER_REPLACE,
+ com.android.internal.R.string.replace);
+ mSuggestionHelper.getSuggestionInfo(mSuggestionInfosInContextMenu);
+ int i = 0;
+ for (final SuggestionInfo info : mSuggestionInfosInContextMenu) {
+ info.mSuggestionEnd = info.mText.length();
+ subMenu.add(Menu.NONE, Menu.NONE, i++, info.mText)
+ .setOnMenuItemClickListener(mOnContextMenuReplaceItemClickListener);
+ }
+ }
menu.add(Menu.NONE, TextView.ID_UNDO, MENU_ITEM_ORDER_UNDO,
com.android.internal.R.string.undo)
@@ -2422,6 +2446,61 @@
mPreserveDetachedSelection = true;
}
+ private void replaceWithSuggestion(SuggestionInfo suggestionInfo, int spanStart, int spanEnd) {
+ final Editable editable = (Editable) mTextView.getText();
+ final String originalText = TextUtils.substring(editable, spanStart, spanEnd);
+ // SuggestionSpans are removed by replace: save them before
+ SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
+ SuggestionSpan.class);
+ final int length = suggestionSpans.length;
+ int[] suggestionSpansStarts = new int[length];
+ int[] suggestionSpansEnds = new int[length];
+ int[] suggestionSpansFlags = new int[length];
+ for (int i = 0; i < length; i++) {
+ final SuggestionSpan suggestionSpan = suggestionSpans[i];
+ suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan);
+ suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan);
+ suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan);
+
+ // Remove potential misspelled flags
+ int suggestionSpanFlags = suggestionSpan.getFlags();
+ if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) != 0) {
+ suggestionSpanFlags &= ~SuggestionSpan.FLAG_MISSPELLED;
+ suggestionSpanFlags &= ~SuggestionSpan.FLAG_EASY_CORRECT;
+ suggestionSpan.setFlags(suggestionSpanFlags);
+ }
+ }
+
+ // Notify source IME of the suggestion pick. Do this before swapping texts.
+ suggestionInfo.mSuggestionSpan.notifySelection(
+ mTextView.getContext(), originalText, suggestionInfo.mSuggestionIndex);
+
+ // Swap text content between actual text and Suggestion span
+ final int suggestionStart = suggestionInfo.mSuggestionStart;
+ final int suggestionEnd = suggestionInfo.mSuggestionEnd;
+ final String suggestion = suggestionInfo.mText.subSequence(
+ suggestionStart, suggestionEnd).toString();
+ mTextView.replaceText_internal(spanStart, spanEnd, suggestion);
+
+ String[] suggestions = suggestionInfo.mSuggestionSpan.getSuggestions();
+ suggestions[suggestionInfo.mSuggestionIndex] = originalText;
+
+ // Restore previous SuggestionSpans
+ final int lengthDelta = suggestion.length() - (spanEnd - spanStart);
+ for (int i = 0; i < length; i++) {
+ // Only spans that include the modified region make sense after replacement
+ // Spans partially included in the replaced region are removed, there is no
+ // way to assign them a valid range after replacement
+ if (suggestionSpansStarts[i] <= spanStart && suggestionSpansEnds[i] >= spanEnd) {
+ mTextView.setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i],
+ suggestionSpansEnds[i] + lengthDelta, suggestionSpansFlags[i]);
+ }
+ }
+ // Move cursor at the end of the replaced word
+ final int newCursorPosition = spanEnd + lengthDelta;
+ mTextView.setCursorPosition_internal(newCursorPosition, newCursorPosition);
+ }
+
private final MenuItem.OnMenuItemClickListener mOnContextMenuItemClickListener =
new MenuItem.OnMenuItemClickListener() {
@Override
@@ -2433,6 +2512,31 @@
}
};
+ private final MenuItem.OnMenuItemClickListener mOnContextMenuReplaceItemClickListener =
+ new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ int index = item.getOrder();
+ if (index < 0 || index >= mSuggestionInfosInContextMenu.length) {
+ clear();
+ return false;
+ }
+ final Spannable spannable = (Spannable) mTextView.getText();
+ final SuggestionSpan suggestionSpan =
+ mSuggestionInfosInContextMenu[index].mSuggestionSpan;
+ replaceWithSuggestion(mSuggestionInfosInContextMenu[index],
+ spannable.getSpanStart(suggestionSpan), spannable.getSpanEnd(suggestionSpan));
+ clear();
+ return true;
+ }
+
+ private void clear() {
+ for (final SuggestionInfo info : mSuggestionInfosInContextMenu) {
+ info.clear();
+ }
+ }
+ };
+
/**
* Controls the {@link EasyEditSpan} monitoring when it is added, and when the related
* pop-up should be displayed.
@@ -2849,6 +2953,131 @@
}
}
+ private static class SuggestionInfo {
+ // Range of actual suggestion within text
+ int mSuggestionStart, mSuggestionEnd;
+
+ // The SuggestionSpan that this TextView represents
+ @Nullable
+ SuggestionSpan mSuggestionSpan;
+
+ // The index of this suggestion inside suggestionSpan
+ int mSuggestionIndex;
+
+ final SpannableStringBuilder mText = new SpannableStringBuilder();
+
+ void clear() {
+ mSuggestionSpan = null;
+ mText.clear();
+ }
+ }
+
+ private class SuggestionHelper {
+ private final Comparator<SuggestionSpan> mSuggestionSpanComparator =
+ new SuggestionSpanComparator();
+ private final HashMap<SuggestionSpan, Integer> mSpansLengths =
+ new HashMap<SuggestionSpan, Integer>();
+
+ private class SuggestionSpanComparator implements Comparator<SuggestionSpan> {
+ public int compare(SuggestionSpan span1, SuggestionSpan span2) {
+ final int flag1 = span1.getFlags();
+ final int flag2 = span2.getFlags();
+ if (flag1 != flag2) {
+ // The order here should match what is used in updateDrawState
+ final boolean easy1 = (flag1 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
+ final boolean easy2 = (flag2 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
+ final boolean misspelled1 = (flag1 & SuggestionSpan.FLAG_MISSPELLED) != 0;
+ final boolean misspelled2 = (flag2 & SuggestionSpan.FLAG_MISSPELLED) != 0;
+ if (easy1 && !misspelled1) return -1;
+ if (easy2 && !misspelled2) return 1;
+ if (misspelled1) return -1;
+ if (misspelled2) return 1;
+ }
+
+ return mSpansLengths.get(span1).intValue() - mSpansLengths.get(span2).intValue();
+ }
+ }
+
+ /**
+ * Returns the suggestion spans that cover the current cursor position. The suggestion
+ * spans are sorted according to the length of text that they are attached to.
+ */
+ private SuggestionSpan[] getSortedSuggestionSpans() {
+ int pos = mTextView.getSelectionStart();
+ Spannable spannable = (Spannable) mTextView.getText();
+ SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class);
+
+ mSpansLengths.clear();
+ for (SuggestionSpan suggestionSpan : suggestionSpans) {
+ int start = spannable.getSpanStart(suggestionSpan);
+ int end = spannable.getSpanEnd(suggestionSpan);
+ mSpansLengths.put(suggestionSpan, Integer.valueOf(end - start));
+ }
+
+ // The suggestions are sorted according to their types (easy correction first, then
+ // misspelled) and to the length of the text that they cover (shorter first).
+ Arrays.sort(suggestionSpans, mSuggestionSpanComparator);
+ mSpansLengths.clear();
+
+ return suggestionSpans;
+ }
+
+ /**
+ * Gets the SuggestionInfo list that contains suggestion information at the current cursor
+ * position.
+ *
+ * @param suggestionInfos SuggestionInfo array the results will be set.
+ * @return the number of suggestions actually fetched.
+ */
+ public int getSuggestionInfo(SuggestionInfo[] suggestionInfos) {
+ final Spannable spannable = (Spannable) mTextView.getText();
+ final SuggestionSpan[] suggestionSpans = getSortedSuggestionSpans();
+ final int nbSpans = suggestionSpans.length;
+ if (nbSpans == 0) return 0;
+
+ int numberOfSuggestions = 0;
+ for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
+ final SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
+ final int spanStart = spannable.getSpanStart(suggestionSpan);
+ final int spanEnd = spannable.getSpanEnd(suggestionSpan);
+
+ final String[] suggestions = suggestionSpan.getSuggestions();
+ final int nbSuggestions = suggestions.length;
+ for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
+ final String suggestion = suggestions[suggestionIndex];
+ boolean suggestionIsDuplicate = false;
+ for (int i = 0; i < numberOfSuggestions; i++) {
+ if (suggestionInfos[i].mText.toString().equals(suggestion)) {
+ final SuggestionSpan otherSuggestionSpan =
+ suggestionInfos[i].mSuggestionSpan;
+ final int otherSpanStart = spannable.getSpanStart(otherSuggestionSpan);
+ final int otherSpanEnd = spannable.getSpanEnd(otherSuggestionSpan);
+ if (spanStart == otherSpanStart && spanEnd == otherSpanEnd) {
+ suggestionIsDuplicate = true;
+ break;
+ }
+ }
+ }
+
+ if (suggestionIsDuplicate) {
+ continue;
+ }
+ SuggestionInfo suggestionInfo = suggestionInfos[numberOfSuggestions];
+ suggestionInfo.mSuggestionSpan = suggestionSpan;
+ suggestionInfo.mSuggestionIndex = suggestionIndex;
+ suggestionInfo.mSuggestionStart = 0;
+ suggestionInfo.mSuggestionEnd = suggestion.length();
+ suggestionInfo.mText.replace(0, suggestionInfo.mText.length(), suggestion);
+ numberOfSuggestions++;
+ if (numberOfSuggestions >= suggestionInfos.length) {
+ return numberOfSuggestions;
+ }
+ }
+ }
+ return numberOfSuggestions;
+ }
+ }
+
@VisibleForTesting
public class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
@@ -2862,8 +3091,6 @@
private boolean mCursorWasVisibleBeforeSuggestions;
private boolean mIsShowingUp = false;
private SuggestionAdapter mSuggestionsAdapter;
- private final Comparator<SuggestionSpan> mSuggestionSpanComparator;
- private final HashMap<SuggestionSpan, Integer> mSpansLengths;
private final TextAppearanceSpan mHighlightSpan = new TextAppearanceSpan(
mTextView.getContext(), mTextView.mTextEditSuggestionHighlightStyle);
private TextView mAddToDictionaryButton;
@@ -2895,8 +3122,6 @@
public SuggestionsPopupWindow() {
mCursorWasVisibleBeforeSuggestions = mCursorVisible;
- mSuggestionSpanComparator = new SuggestionSpanComparator();
- mSpansLengths = new HashMap<SuggestionSpan, Integer>();
}
@Override
@@ -2987,24 +3212,6 @@
mIsShowingUp = false;
}
- private final class SuggestionInfo {
- int suggestionStart, suggestionEnd; // range of actual suggestion within text
-
- // the SuggestionSpan that this TextView represents
- @Nullable
- SuggestionSpan suggestionSpan;
-
- int suggestionIndex; // the index of this suggestion inside suggestionSpan
-
- @Nullable
- final SpannableStringBuilder text = new SpannableStringBuilder();
-
- void clear() {
- suggestionSpan = null;
- text.clear();
- }
- }
-
private class SuggestionAdapter extends BaseAdapter {
private LayoutInflater mInflater = (LayoutInflater) mTextView.getContext().
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -3034,55 +3241,11 @@
}
final SuggestionInfo suggestionInfo = mSuggestionInfos[position];
- textView.setText(suggestionInfo.text);
+ textView.setText(suggestionInfo.mText);
return textView;
}
}
- private class SuggestionSpanComparator implements Comparator<SuggestionSpan> {
- public int compare(SuggestionSpan span1, SuggestionSpan span2) {
- final int flag1 = span1.getFlags();
- final int flag2 = span2.getFlags();
- if (flag1 != flag2) {
- // The order here should match what is used in updateDrawState
- final boolean easy1 = (flag1 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
- final boolean easy2 = (flag2 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
- final boolean misspelled1 = (flag1 & SuggestionSpan.FLAG_MISSPELLED) != 0;
- final boolean misspelled2 = (flag2 & SuggestionSpan.FLAG_MISSPELLED) != 0;
- if (easy1 && !misspelled1) return -1;
- if (easy2 && !misspelled2) return 1;
- if (misspelled1) return -1;
- if (misspelled2) return 1;
- }
-
- return mSpansLengths.get(span1).intValue() - mSpansLengths.get(span2).intValue();
- }
- }
-
- /**
- * Returns the suggestion spans that cover the current cursor position. The suggestion
- * spans are sorted according to the length of text that they are attached to.
- */
- private SuggestionSpan[] getSuggestionSpans() {
- int pos = mTextView.getSelectionStart();
- Spannable spannable = (Spannable) mTextView.getText();
- SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class);
-
- mSpansLengths.clear();
- for (SuggestionSpan suggestionSpan : suggestionSpans) {
- int start = spannable.getSpanStart(suggestionSpan);
- int end = spannable.getSpanEnd(suggestionSpan);
- mSpansLengths.put(suggestionSpan, Integer.valueOf(end - start));
- }
-
- // The suggestions are sorted according to their types (easy correction first, then
- // misspelled) and to the length of the text that they cover (shorter first).
- Arrays.sort(suggestionSpans, mSuggestionSpanComparator);
- mSpansLengths.clear();
-
- return suggestionSpans;
- }
-
@VisibleForTesting
public ViewGroup getContentViewForTesting() {
return mContentView;
@@ -3166,66 +3329,26 @@
private boolean updateSuggestions() {
Spannable spannable = (Spannable) mTextView.getText();
- SuggestionSpan[] suggestionSpans = getSuggestionSpans();
+ mNumberOfSuggestions =
+ mSuggestionHelper.getSuggestionInfo(mSuggestionInfos);
+ if (mNumberOfSuggestions == 0) {
+ return false;
+ }
- final int nbSpans = suggestionSpans.length;
- // Suggestions are shown after a delay: the underlying spans may have been removed
- if (nbSpans == 0) return false;
-
- mNumberOfSuggestions = 0;
int spanUnionStart = mTextView.getText().length();
int spanUnionEnd = 0;
mMisspelledSpan = null;
- int underlineColor = 0;
-
- for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
- SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
- final int spanStart = spannable.getSpanStart(suggestionSpan);
- final int spanEnd = spannable.getSpanEnd(suggestionSpan);
- spanUnionStart = Math.min(spanStart, spanUnionStart);
- spanUnionEnd = Math.max(spanEnd, spanUnionEnd);
-
+ for (int i = 0; i < mNumberOfSuggestions; i++) {
+ final SuggestionInfo suggestionInfo = mSuggestionInfos[i];
+ final SuggestionSpan suggestionSpan = suggestionInfo.mSuggestionSpan;
if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
mMisspelledSpan = suggestionSpan;
}
-
- // The first span dictates the background color of the highlighted text
- if (spanIndex == 0) underlineColor = suggestionSpan.getUnderlineColor();
-
- String[] suggestions = suggestionSpan.getSuggestions();
- int nbSuggestions = suggestions.length;
- for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
- String suggestion = suggestions[suggestionIndex];
-
- boolean suggestionIsDuplicate = false;
- for (int i = 0; i < mNumberOfSuggestions; i++) {
- if (mSuggestionInfos[i].text.toString().equals(suggestion)) {
- SuggestionSpan otherSuggestionSpan = mSuggestionInfos[i].suggestionSpan;
- final int otherSpanStart = spannable.getSpanStart(otherSuggestionSpan);
- final int otherSpanEnd = spannable.getSpanEnd(otherSuggestionSpan);
- if (spanStart == otherSpanStart && spanEnd == otherSpanEnd) {
- suggestionIsDuplicate = true;
- break;
- }
- }
- }
-
- if (!suggestionIsDuplicate) {
- SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions];
- suggestionInfo.suggestionSpan = suggestionSpan;
- suggestionInfo.suggestionIndex = suggestionIndex;
- suggestionInfo.text.replace(0, suggestionInfo.text.length(), suggestion);
-
- mNumberOfSuggestions++;
-
- if (mNumberOfSuggestions == MAX_NUMBER_SUGGESTIONS) {
- // Also end outer for loop
- spanIndex = nbSpans;
- break;
- }
- }
- }
+ final int spanStart = spannable.getSpanStart(suggestionSpan);
+ final int spanEnd = spannable.getSpanEnd(suggestionSpan);
+ spanUnionStart = Math.min(spanUnionStart, spanStart);
+ spanUnionEnd = Math.max(spanUnionEnd, spanEnd);
}
for (int i = 0; i < mNumberOfSuggestions; i++) {
@@ -3244,6 +3367,7 @@
mAddToDictionaryButton.setVisibility(addToDictionaryButtonVisibility);
if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
+ final int underlineColor = mSuggestionInfos[0].mSuggestionSpan.getUnderlineColor();
if (underlineColor == 0) {
// Fallback on the default highlight color when the first span does not provide one
mSuggestionRangeSpan.setBackgroundColor(mTextView.mHighlightColor);
@@ -3263,21 +3387,21 @@
private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart,
int unionEnd) {
final Spannable text = (Spannable) mTextView.getText();
- final int spanStart = text.getSpanStart(suggestionInfo.suggestionSpan);
- final int spanEnd = text.getSpanEnd(suggestionInfo.suggestionSpan);
+ final int spanStart = text.getSpanStart(suggestionInfo.mSuggestionSpan);
+ final int spanEnd = text.getSpanEnd(suggestionInfo.mSuggestionSpan);
// Adjust the start/end of the suggestion span
- suggestionInfo.suggestionStart = spanStart - unionStart;
- suggestionInfo.suggestionEnd = suggestionInfo.suggestionStart
- + suggestionInfo.text.length();
+ suggestionInfo.mSuggestionStart = spanStart - unionStart;
+ suggestionInfo.mSuggestionEnd = suggestionInfo.mSuggestionStart
+ + suggestionInfo.mText.length();
- suggestionInfo.text.setSpan(mHighlightSpan, 0, suggestionInfo.text.length(),
+ suggestionInfo.mText.setSpan(mHighlightSpan, 0, suggestionInfo.mText.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// Add the text before and after the span.
final String textAsString = text.toString();
- suggestionInfo.text.insert(0, textAsString.substring(unionStart, spanStart));
- suggestionInfo.text.append(textAsString.substring(spanEnd, unionEnd));
+ suggestionInfo.mText.insert(0, textAsString.substring(unionStart, spanStart));
+ suggestionInfo.mText.append(textAsString.substring(spanEnd, unionEnd));
}
@Override
@@ -3285,69 +3409,14 @@
Editable editable = (Editable) mTextView.getText();
SuggestionInfo suggestionInfo = mSuggestionInfos[position];
- final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan);
- final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan);
+ final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan);
+ final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan);
if (spanStart < 0 || spanEnd <= spanStart) {
// Span has been removed
hideWithCleanUp();
return;
}
-
- final String originalText = TextUtils.substring(editable, spanStart, spanEnd);
-
- // SuggestionSpans are removed by replace: save them before
- final SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
- SuggestionSpan.class);
- final int length = suggestionSpans.length;
- final int[] suggestionSpansStarts = new int[length];
- final int[] suggestionSpansEnds = new int[length];
- final int[] suggestionSpansFlags = new int[length];
- for (int i = 0; i < length; i++) {
- final SuggestionSpan suggestionSpan = suggestionSpans[i];
- suggestionSpansStarts[i] = editable.getSpanStart(suggestionSpan);
- suggestionSpansEnds[i] = editable.getSpanEnd(suggestionSpan);
- suggestionSpansFlags[i] = editable.getSpanFlags(suggestionSpan);
-
- // Remove potential misspelled flags
- int suggestionSpanFlags = suggestionSpan.getFlags();
- if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) {
- suggestionSpanFlags &= ~SuggestionSpan.FLAG_MISSPELLED;
- suggestionSpanFlags &= ~SuggestionSpan.FLAG_EASY_CORRECT;
- suggestionSpan.setFlags(suggestionSpanFlags);
- }
- }
-
- final int suggestionStart = suggestionInfo.suggestionStart;
- final int suggestionEnd = suggestionInfo.suggestionEnd;
- final String suggestion = suggestionInfo.text.subSequence(
- suggestionStart, suggestionEnd).toString();
- mTextView.replaceText_internal(spanStart, spanEnd, suggestion);
-
- // Notify source IME of the suggestion pick. Do this before
- // swaping texts.
- suggestionInfo.suggestionSpan.notifySelection(
- mTextView.getContext(), originalText, suggestionInfo.suggestionIndex);
-
- // Swap text content between actual text and Suggestion span
- final String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions();
- suggestions[suggestionInfo.suggestionIndex] = originalText;
-
- // Restore previous SuggestionSpans
- final int lengthDifference = suggestion.length() - (spanEnd - spanStart);
- for (int i = 0; i < length; i++) {
- // Only spans that include the modified region make sense after replacement
- // Spans partially included in the replaced region are removed, there is no
- // way to assign them a valid range after replacement
- if (suggestionSpansStarts[i] <= spanStart &&
- suggestionSpansEnds[i] >= spanEnd) {
- mTextView.setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i],
- suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]);
- }
- }
-
- // Move cursor at the end of the replaced word
- final int newCursorPosition = spanEnd + lengthDifference;
- mTextView.setCursorPosition_internal(newCursorPosition, newCursorPosition);
+ replaceWithSuggestion(suggestionInfo, spanStart, spanEnd);
hideWithCleanUp();
}
}
diff --git a/core/java/android/widget/ForwardingListener.java b/core/java/android/widget/ForwardingListener.java
index 7ddeff9..b383e1c 100644
--- a/core/java/android/widget/ForwardingListener.java
+++ b/core/java/android/widget/ForwardingListener.java
@@ -53,12 +53,6 @@
/** Whether this listener is currently forwarding touch events. */
private boolean mForwarding;
- /**
- * Whether forwarding was initiated by a long-press. If so, we won't
- * force the window to dismiss when the touch stream ends.
- */
- private boolean mWasLongPress;
-
/** The id of the first pointer down in the current event stream. */
private int mActivePointerId;
@@ -172,7 +166,6 @@
switch (actionMasked) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = srcEvent.getPointerId(0);
- mWasLongPress = false;
if (mDisallowIntercept == null) {
mDisallowIntercept = new DisallowIntercept();
@@ -243,7 +236,6 @@
e.recycle();
mForwarding = true;
- mWasLongPress = true;
}
/**
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index b95bc28..595adc2 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -16,18 +16,20 @@
package android.widget;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
+import com.android.internal.R;
+import com.android.internal.view.menu.ShowableListMenu;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleRes;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.IntProperty;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
@@ -38,13 +40,7 @@
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.WindowManager;
-import android.view.animation.AccelerateDecelerateInterpolator;
-
-import com.android.internal.R;
-import com.android.internal.view.menu.ShowableListMenu;
-import com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
-
-import java.util.Locale;
+import android.widget.AdapterView.OnItemSelectedListener;
/**
* A ListPopupWindow anchors itself to a host view and displays a
@@ -109,8 +105,6 @@
private boolean mModal;
- private int mLayoutDirection;
-
PopupWindow mPopup;
/**
@@ -174,7 +168,7 @@
*
* @param context Context used for contained views.
*/
- public ListPopupWindow(Context context) {
+ public ListPopupWindow(@NonNull Context context) {
this(context, null, com.android.internal.R.attr.listPopupWindowStyle, 0);
}
@@ -185,7 +179,7 @@
* @param context Context used for contained views.
* @param attrs Attributes from inflating parent views used to style the popup.
*/
- public ListPopupWindow(Context context, AttributeSet attrs) {
+ public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.listPopupWindowStyle, 0);
}
@@ -197,7 +191,8 @@
* @param attrs Attributes from inflating parent views used to style the popup.
* @param defStyleAttr Default style attribute to use for popup content.
*/
- public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
+ public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
+ @AttrRes int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
@@ -210,7 +205,8 @@
* @param defStyleAttr Style attribute to read for default styling of popup content.
* @param defStyleRes Style resource ID to use for default styling of popup content.
*/
- public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
+ @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
mContext = context;
mHandler = new Handler(context.getMainLooper());
@@ -227,9 +223,6 @@
mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes);
mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
- // Set the default layout direction to match the default locale one
- final Locale locale = mContext.getResources().getConfiguration().locale;
- mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
}
/**
@@ -238,7 +231,7 @@
*
* @param adapter The adapter to use to create this window's content.
*/
- public void setAdapter(ListAdapter adapter) {
+ public void setAdapter(@Nullable ListAdapter adapter) {
if (mObserver == null) {
mObserver = new PopupDataSetObserver();
} else if (mAdapter != null) {
@@ -371,7 +364,7 @@
/**
* @return The background drawable for the popup window.
*/
- public Drawable getBackground() {
+ public @Nullable Drawable getBackground() {
return mPopup.getBackground();
}
@@ -380,7 +373,7 @@
*
* @param d A drawable to set as the background.
*/
- public void setBackgroundDrawable(Drawable d) {
+ public void setBackgroundDrawable(@Nullable Drawable d) {
mPopup.setBackgroundDrawable(d);
}
@@ -389,7 +382,7 @@
*
* @param animationStyle Animation style to use.
*/
- public void setAnimationStyle(int animationStyle) {
+ public void setAnimationStyle(@StyleRes int animationStyle) {
mPopup.setAnimationStyle(animationStyle);
}
@@ -399,7 +392,7 @@
*
* @return Animation style that will be used.
*/
- public int getAnimationStyle() {
+ public @StyleRes int getAnimationStyle() {
return mPopup.getAnimationStyle();
}
@@ -408,7 +401,7 @@
*
* @return The popup's anchor view
*/
- public View getAnchorView() {
+ public @Nullable View getAnchorView() {
return mDropDownAnchorView;
}
@@ -418,7 +411,7 @@
*
* @param anchor The view to use as an anchor.
*/
- public void setAnchorView(View anchor) {
+ public void setAnchorView(@Nullable View anchor) {
mDropDownAnchorView = anchor;
}
@@ -537,7 +530,7 @@
*
* @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)
*/
- public void setOnItemClickListener(AdapterView.OnItemClickListener clickListener) {
+ public void setOnItemClickListener(@Nullable AdapterView.OnItemClickListener clickListener) {
mItemClickListener = clickListener;
}
@@ -546,9 +539,9 @@
*
* @param selectedListener Listener to register.
*
- * @see ListView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
+ * @see ListView#setOnItemSelectedListener(OnItemSelectedListener)
*/
- public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener selectedListener) {
+ public void setOnItemSelectedListener(@Nullable OnItemSelectedListener selectedListener) {
mItemSelectedListener = selectedListener;
}
@@ -558,7 +551,7 @@
*
* @param prompt View to use as an informational prompt.
*/
- public void setPromptView(View prompt) {
+ public void setPromptView(@Nullable View prompt) {
boolean showing = isShowing();
if (showing) {
removePromptView();
@@ -686,7 +679,7 @@
*
* @param listener Listener that will be notified when the popup is dismissed.
*/
- public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
+ public void setOnDismissListener(@Nullable PopupWindow.OnDismissListener listener) {
mPopup.setOnDismissListener(listener);
}
@@ -795,7 +788,7 @@
/**
* @return The currently selected item or null if the popup is not showing.
*/
- public Object getSelectedItem() {
+ public @Nullable Object getSelectedItem() {
if (!isShowing()) {
return null;
}
@@ -834,7 +827,7 @@
*
* @see ListView#getSelectedView()
*/
- public View getSelectedView() {
+ public @Nullable View getSelectedView() {
if (!isShowing()) {
return null;
}
@@ -846,11 +839,11 @@
* Only valid when {@link #isShowing()} == {@code true}.
*/
@Override
- public ListView getListView() {
+ public @Nullable ListView getListView() {
return mDropDownList;
}
- DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
+ @NonNull DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
return new DropDownListView(context, hijackFocus);
}
@@ -874,7 +867,7 @@
*
* @see #setModal(boolean)
*/
- public boolean onKeyDown(int keyCode, KeyEvent event) {
+ public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
// when the drop down is shown, we drive it directly
if (isShowing()) {
// the key events are forwarded to the list in the drop down view
@@ -969,7 +962,7 @@
*
* @see #setModal(boolean)
*/
- public boolean onKeyUp(int keyCode, KeyEvent event) {
+ public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
boolean consumed = mDropDownList.onKeyUp(keyCode, event);
if (consumed && KeyEvent.isConfirmKey(keyCode)) {
@@ -993,7 +986,7 @@
*
* @see #setModal(boolean)
*/
- public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
@@ -1159,7 +1152,6 @@
mPopup.setContentView(dropDownView);
} else {
- dropDownView = (ViewGroup) mPopup.getContentView();
final View view = mPromptView;
if (view != null) {
LinearLayout.LayoutParams hintParams =
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index c79e184..09cf704 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -271,6 +271,10 @@
attrs, R.styleable.Spinner, defStyleAttr, defStyleRes);
mDropDownWidth = pa.getLayoutDimension(R.styleable.Spinner_dropDownWidth,
ViewGroup.LayoutParams.WRAP_CONTENT);
+ if (pa.hasValueOrEmpty(R.styleable.Spinner_dropDownSelector)) {
+ popup.setListSelector(pa.getDrawable(
+ R.styleable.Spinner_dropDownSelector));
+ }
popup.setBackgroundDrawable(pa.getDrawable(R.styleable.Spinner_popupBackground));
popup.setPromptText(a.getString(R.styleable.Spinner_prompt));
pa.recycle();
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 40eb375..ce4fc06 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -27,7 +27,6 @@
*/
public class MetricsLogger implements MetricsConstants {
// Temporary constants go here, to await migration to MetricsConstants.
- public static final int QS_LOCK_TILE = 257;
public static final int QS_USER_TILE = 258;
public static final int QS_BATTERY_TILE = 259;
public static final int NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 260;
@@ -62,6 +61,7 @@
* credentials UI.
*/
public static final int PROFILE_CHALLENGE = 271;
+ public static final int QS_BATTERY_DETAIL = 272;
public static void visible(Context context, int category) throws IllegalArgumentException {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index 830da79..b3222f0 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -19,6 +19,7 @@
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.Slog;
import com.android.internal.util.Preconditions;
@@ -29,6 +30,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Arrays;
/**
* Represents a connection to {@code installd}. Allows multiple connect and
@@ -61,6 +63,11 @@
}
public synchronized String transact(String cmd) {
+ if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+ Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+ }
+
if (!connect()) {
Slog.e(TAG, "connection failed");
return "-1";
@@ -96,44 +103,50 @@
}
}
- public int execute(String cmd) {
- if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
- + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
- }
-
- String res = transact(cmd);
+ public void execute(String cmd, Object... args) throws InstallerException {
+ final String resRaw = executeForResult(cmd, args);
+ int res = -1;
try {
- return Integer.parseInt(res);
- } catch (NumberFormatException ex) {
- return -1;
+ res = Integer.parseInt(resRaw);
+ } catch (NumberFormatException ignored) {
+ }
+ if (res != 0) {
+ throw new InstallerException(
+ "Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res);
}
}
- public int dexopt(String apkPath, int uid, String instructionSet,
- int dexoptNeeded, int dexFlags) {
- return dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded,
- null /*outputPath*/, dexFlags);
+ public String executeForResult(String cmd, Object... args)
+ throws InstallerException {
+ final StringBuilder builder = new StringBuilder(cmd);
+ for (Object arg : args) {
+ String escaped;
+ if (arg == null) {
+ escaped = "";
+ } else {
+ escaped = String.valueOf(arg);
+ }
+ if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
+ throw new InstallerException(
+ "Invalid argument while executing " + cmd + " " + Arrays.toString(args));
+ }
+ if (TextUtils.isEmpty(escaped)) {
+ escaped = "!";
+ }
+ builder.append(' ').append(escaped);
+ }
+ return transact(builder.toString());
}
- public int dexopt(String apkPath, int uid, String pkgName, String instructionSet,
- int dexoptNeeded, String outputPath, int dexFlags) {
- StringBuilder builder = new StringBuilder("dexopt");
- builder.append(' ');
- builder.append(apkPath);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(instructionSet);
- builder.append(' ');
- builder.append(dexoptNeeded);
- builder.append(' ');
- builder.append(outputPath != null ? outputPath : "!");
- builder.append(' ');
- builder.append(dexFlags);
- return execute(builder.toString());
+ public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
+ int dexFlags) throws InstallerException {
+ dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded, null /* outputPath */, dexFlags);
+ }
+
+ public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
+ int dexoptNeeded, String outputPath, int dexFlags) throws InstallerException {
+ execute("dexopt", apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
+ dexFlags);
}
private boolean connect() {
@@ -227,11 +240,19 @@
public void waitForConnection() {
for (;;) {
- if (execute("ping") >= 0) {
+ try {
+ execute("ping");
return;
+ } catch (InstallerException ignored) {
}
Slog.w(TAG, "installd not ready");
SystemClock.sleep(1000);
}
}
+
+ public static class InstallerException extends Exception {
+ public InstallerException(String detailMessage) {
+ super(detailMessage);
+ }
+ }
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 4a1f7f4..eecc0ee 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -37,6 +37,8 @@
import android.util.Log;
import android.webkit.WebViewFactory;
+import com.android.internal.os.InstallerConnection.InstallerException;
+
import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
import dalvik.system.VMRuntime;
@@ -502,8 +504,8 @@
dexoptNeeded, 0 /*dexFlags*/);
}
}
- } catch (IOException ioe) {
- throw new RuntimeException("Error starting system_server", ioe);
+ } catch (IOException | InstallerException e) {
+ throw new RuntimeException("Error starting system_server", e);
} finally {
installer.disconnect();
}
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 1b44ff3..de54d96 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -99,6 +99,9 @@
mResizingBackgroundDrawable = resizingBackgroundDrawable;
mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
mUserCaptionBackgroundDrawable = userCaptionBackgroundDrawable;
+ if (mCaptionBackgroundDrawable == null) {
+ mCaptionBackgroundDrawable = mResizingBackgroundDrawable;
+ }
if (statusBarColor != 0) {
mStatusBarColor = new ColorDrawable(statusBarColor);
addSystemBarNodeIfNeeded();
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index cc2f714..7ae0efb 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -17,6 +17,7 @@
package com.android.internal.policy;
import com.android.internal.R;
+import com.android.internal.policy.PhoneWindow.PanelFeatureState;
import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback;
import com.android.internal.view.FloatingActionMode;
import com.android.internal.view.RootViewSurfaceTaker;
@@ -28,6 +29,8 @@
import com.android.internal.widget.DecorCaptionView;
import com.android.internal.widget.FloatingToolbar;
+import java.util.List;
+
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.ActivityManager;
@@ -48,6 +51,7 @@
import android.view.Gravity;
import android.view.InputQueue;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -85,6 +89,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
/** @hide */
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
@@ -1616,14 +1621,8 @@
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
mStackId = getStackId();
- mResizingBackgroundDrawable = getResizingBackgroundDrawable(
- mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource);
- if (mCaptionBackgroundDrawable == null) {
- mCaptionBackgroundDrawable = getContext().getDrawable(
- R.drawable.decor_caption_title_focused);
- }
-
if (mBackdropFrameRenderer != null) {
+ loadBackgroundDrawablesIfNeeded();
mBackdropFrameRenderer.onResourcesLoaded(
this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState));
@@ -1645,6 +1644,17 @@
initializeElevation();
}
+ private void loadBackgroundDrawablesIfNeeded() {
+ if (mResizingBackgroundDrawable == null) {
+ mResizingBackgroundDrawable = getResizingBackgroundDrawable(
+ mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource);
+ }
+ if (mCaptionBackgroundDrawable == null) {
+ mCaptionBackgroundDrawable = getContext().getDrawable(
+ R.drawable.decor_caption_title_focused);
+ }
+ }
+
// Free floating overlapping windows require a caption.
private DecorCaptionView createDecorCaptionView(LayoutInflater inflater) {
DecorCaptionView decorCaptionView = null;
@@ -1815,6 +1825,7 @@
}
final ThreadedRenderer renderer = getHardwareRenderer();
if (renderer != null) {
+ loadBackgroundDrawablesIfNeeded();
mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState));
@@ -1950,6 +1961,21 @@
res.getConfiguration().screenWidthDp, res.getDisplayMetrics());
}
+ /**
+ * @hide
+ */
+ @Override
+ public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> list) {
+ final PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (!mWindow.isDestroyed() && st != null && mWindow.getCallback() != null) {
+ try {
+ mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
+ } catch (AbstractMethodError e) {
+ // We run into this if the app is using supportlib.
+ }
+ }
+ }
+
private static class ColorViewState {
View view = null;
int targetVisibility = View.INVISIBLE;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/stackdivider/DividerSnapAlgorithm.java
rename to core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index e43d531..e79f1b8 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-package com.android.systemui.stackdivider;
+package com.android.internal.policy;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Rect;
-import com.android.systemui.statusbar.FlingAnimationUtils;
-
import java.util.ArrayList;
/**
* Calculates the snap targets and the snap position given a position and a velocity. All positions
* here are to be interpreted as the left/top edge of the divider rectangle.
+ *
+ * @hide
*/
public class DividerSnapAlgorithm {
@@ -44,8 +45,7 @@
*/
private static final int SNAP_ONLY_1_1 = 2;
- private final Context mContext;
- private final FlingAnimationUtils mFlingAnimationUtils;
+ private final float mMinFlingVelocityPxPerSecond;
private final int mDisplayWidth;
private final int mDisplayHeight;
private final int mDividerSize;
@@ -63,18 +63,17 @@
private final SnapTarget mDismissStartTarget;
private final SnapTarget mDismissEndTarget;
- public DividerSnapAlgorithm(Context ctx, FlingAnimationUtils flingAnimationUtils,
+ public DividerSnapAlgorithm(Resources res, float minFlingVelocityPxPerSecond,
int displayWidth, int displayHeight, int dividerSize, boolean isHorizontalDivision,
Rect insets) {
- mContext = ctx;
- mFlingAnimationUtils = flingAnimationUtils;
+ mMinFlingVelocityPxPerSecond = minFlingVelocityPxPerSecond;
mDividerSize = dividerSize;
mDisplayWidth = displayWidth;
mDisplayHeight = displayHeight;
mInsets.set(insets);
- mSnapMode = ctx.getResources().getInteger(
+ mSnapMode = res.getInteger(
com.android.internal.R.integer.config_dockedStackDividerSnapMode);
- mFixedRatio = ctx.getResources().getFraction(
+ mFixedRatio = res.getFraction(
com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1);
calculateTargets(isHorizontalDivision);
mFirstSplitTarget = mTargets.get(1);
@@ -84,7 +83,7 @@
}
public SnapTarget calculateSnapTarget(int position, float velocity) {
- if (Math.abs(velocity) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+ if (Math.abs(velocity) < mMinFlingVelocityPxPerSecond) {
return snap(position);
}
if (position < mFirstSplitTarget.position && velocity < 0) {
@@ -100,6 +99,17 @@
}
}
+ public SnapTarget calculateNonDismissingSnapTarget(int position) {
+ SnapTarget target = snap(position);
+ if (target == mDismissStartTarget) {
+ return mFirstSplitTarget;
+ } else if (target == mDismissEndTarget) {
+ return mLastSplitTarget;
+ } else {
+ return target;
+ }
+ }
+
public float calculateDismissingFraction(int position) {
if (position < mFirstSplitTarget.position) {
return 1f - (float) position / mFirstSplitTarget.position;
diff --git a/core/java/com/android/internal/policy/DockedDividerUtils.java b/core/java/com/android/internal/policy/DockedDividerUtils.java
new file mode 100644
index 0000000..25a060e
--- /dev/null
+++ b/core/java/com/android/internal/policy/DockedDividerUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy;
+
+import android.graphics.Rect;
+import android.view.WindowManager;
+
+/**
+ * Utility functions for docked stack divider used by both window manager and System UI.
+ *
+ * @hide
+ */
+public class DockedDividerUtils {
+
+ public static void calculateBoundsForPosition(int position, int dockSide, Rect outRect,
+ int displayWidth, int displayHeight, int dividerSize) {
+ outRect.set(0, 0, displayWidth, displayHeight);
+ switch (dockSide) {
+ case WindowManager.DOCKED_LEFT:
+ outRect.right = position;
+ break;
+ case WindowManager.DOCKED_TOP:
+ outRect.bottom = position;
+ break;
+ case WindowManager.DOCKED_RIGHT:
+ outRect.left = position + dividerSize;
+ break;
+ case WindowManager.DOCKED_BOTTOM:
+ outRect.top = position + dividerSize;
+ break;
+ }
+ if (outRect.left > outRect.right) {
+ outRect.left = outRect.right;
+ }
+ if (outRect.top > outRect.bottom) {
+ outRect.top = outRect.bottom;
+ }
+ if (outRect.right < outRect.left) {
+ outRect.right = outRect.left;
+ }
+ if (outRect.bottom < outRect.top) {
+ outRect.bottom = outRect.top;
+ }
+ }
+
+ public static int calculatePositionForBounds(Rect bounds, int dockSide, int dividerSize) {
+ switch (dockSide) {
+ case WindowManager.DOCKED_LEFT:
+ return bounds.right;
+ case WindowManager.DOCKED_TOP:
+ return bounds.bottom;
+ case WindowManager.DOCKED_RIGHT:
+ return bounds.left - dividerSize;
+ case WindowManager.DOCKED_BOTTOM:
+ return bounds.top - dividerSize;
+ default:
+ return 0;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index f159a4d..b4c4ef5 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2677,20 +2677,16 @@
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else {
- mTitleView = (TextView)findViewById(R.id.title);
+ mTitleView = (TextView) findViewById(R.id.title);
if (mTitleView != null) {
- mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
- View titleContainer = findViewById(
- R.id.title_container);
+ final View titleContainer = findViewById(R.id.title_container);
if (titleContainer != null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
}
- if (mContentParent instanceof FrameLayout) {
- ((FrameLayout)mContentParent).setForeground(null);
- }
+ mContentParent.setForeground(null);
} else {
mTitleView.setText(mTitle);
}
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 16bf9dd..ca1334c 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -26,6 +26,7 @@
import java.lang.reflect.Array;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -372,6 +373,10 @@
return (array != null) ? array.clone() : null;
}
+ public static @Nullable <T> ArraySet<T> cloneOrNull(@Nullable ArraySet<T> array) {
+ return (array != null) ? new ArraySet<T>(array) : null;
+ }
+
public static @NonNull <T> ArraySet<T> add(@Nullable ArraySet<T> cur, T val) {
if (cur == null) {
cur = new ArraySet<>();
@@ -420,6 +425,16 @@
return (cur != null) ? cur.contains(val) : false;
}
+ public static @Nullable <T> T[] trimToSize(@Nullable T[] array, int size) {
+ if (array == null || size == 0) {
+ return null;
+ } else if (array.length == size) {
+ return array;
+ } else {
+ return Arrays.copyOf(array, size);
+ }
+ }
+
/**
* Returns true if the two ArrayLists are equal with respect to the objects they contain.
* The objects must be in the same order and be reference equal (== not .equals()).
diff --git a/core/java/com/android/internal/util/IndentingPrintWriter.java b/core/java/com/android/internal/util/IndentingPrintWriter.java
index f1add27..696667c 100644
--- a/core/java/com/android/internal/util/IndentingPrintWriter.java
+++ b/core/java/com/android/internal/util/IndentingPrintWriter.java
@@ -45,6 +45,8 @@
*/
private boolean mEmptyLine = true;
+ private char[] mSingleChar = new char[1];
+
public IndentingPrintWriter(Writer writer, String singleIndent) {
this(writer, singleIndent, -1);
}
@@ -78,6 +80,24 @@
}
@Override
+ public void println() {
+ write('\n');
+ }
+
+ @Override
+ public void write(int c) {
+ mSingleChar[0] = (char) c;
+ write(mSingleChar, 0, 1);
+ }
+
+ @Override
+ public void write(String s, int off, int len) {
+ final char[] buf = new char[len];
+ s.getChars(off, len - off, buf, 0);
+ write(buf, 0, len);
+ }
+
+ @Override
public void write(char[] buf, int offset, int count) {
final int indentLength = mIndentBuilder.length();
final int bufferEnd = offset + count;
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 8699843..aa4b564c 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -25,6 +25,8 @@
import android.view.IWindow;
import android.view.IWindowSession;
+import com.android.internal.os.IResultReceiver;
+
public class BaseIWindow extends IWindow.Stub {
private IWindowSession mSession;
public int mSeq;
@@ -103,4 +105,8 @@
@Override
public void dispatchWindowShown() {
}
+
+ @Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) {
+ }
}
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index c2adc42..a67e43a 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.internal.view.menu;
import android.content.Context;
@@ -7,7 +23,6 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnKeyListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -30,7 +45,7 @@
MenuPresenter, OnKeyListener {
private final Context mContext;
- private final LayoutInflater mInflater;
+
private final MenuBuilder mMenu;
private final MenuAdapter mAdapter;
private final boolean mOverflowOnly;
@@ -79,8 +94,6 @@
private Callback mPresenterCallback;
private ViewTreeObserver mTreeObserver;
- private ViewGroup mMeasureParent;
-
/** Whether the popup has been dismissed. Once dismissed, it cannot be opened again. */
private boolean mWasDismissed;
@@ -99,10 +112,10 @@
public StandardMenuPopup(Context context, MenuBuilder menu, View anchorView, int popupStyleAttr,
int popupStyleRes, boolean overflowOnly) {
mContext = Preconditions.checkNotNull(context);
- mInflater = LayoutInflater.from(context);
mMenu = menu;
mOverflowOnly = overflowOnly;
- mAdapter = new MenuAdapter(menu, mInflater, mOverflowOnly);
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ mAdapter = new MenuAdapter(menu, inflater, mOverflowOnly);
mPopupStyleAttr = popupStyleAttr;
mPopupStyleRes = popupStyleRes;
@@ -155,8 +168,7 @@
mPopup.setDropDownGravity(mDropDownGravity);
if (!mHasContentWidth) {
- mContentWidth = measureIndividualMenuWidth(
- mAdapter, mMeasureParent, mContext, mPopupMaxWidth);
+ mContentWidth = measureIndividualMenuWidth(mAdapter, null, mContext, mPopupMaxWidth);
mHasContentWidth = true;
}
@@ -177,7 +189,9 @@
false);
TextView titleView = (TextView) titleItemView.findViewById(
com.android.internal.R.id.title);
- titleView.setText(mMenu.getHeaderTitle());
+ if (titleView != null) {
+ titleView.setText(mMenu.getHeaderTitle());
+ }
titleItemView.setEnabled(false);
listView.addHeaderView(titleItemView, null, false);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index e38d82f..4e8f19c 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -24,6 +24,7 @@
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.UserInfo;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder;
@@ -34,6 +35,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.provider.Settings;
@@ -135,6 +137,8 @@
private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
+ private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
+
// Maximum allowed number of repeated or ordered characters in a sequence before we'll
// consider it a complex PIN/password.
public static final int MAX_ALLOWED_SEQUENCE = 3;
@@ -143,6 +147,7 @@
private final ContentResolver mContentResolver;
private DevicePolicyManager mDevicePolicyManager;
private ILockSettings mLockSettingsService;
+ private UserManager mUserManager;
public static final class RequestThrottledException extends Exception {
@@ -173,6 +178,13 @@
return mDevicePolicyManager;
}
+ private UserManager getUserManager() {
+ if (mUserManager == null) {
+ mUserManager = UserManager.get(mContext);
+ }
+ return mUserManager;
+ }
+
private TrustManager getTrustManager() {
TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
if (trust == null) {
@@ -866,6 +878,39 @@
}
/**
+ * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
+ * for user handles that do not belong to a managed profile.
+ */
+ public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled) {
+ UserInfo info = getUserManager().getUserInfo(userHandle);
+ if (info.isManagedProfile()) {
+ setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userHandle);
+ }
+ }
+
+ /**
+ * Retrieves whether the Separate Profile Challenge is enabled for this {@param userHandle}.
+ */
+ public boolean isSeparateProfileChallengeEnabled(int userHandle) {
+ UserInfo info = getUserManager().getUserInfo(userHandle);
+ if (info == null || !info.isManagedProfile()) {
+ return false;
+ }
+ return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userHandle);
+ }
+
+ /**
+ * Retrieves whether the current DPM allows use of the Profile Challenge.
+ */
+ public boolean isSeparateProfileChallengeAllowed(int userHandle) {
+ UserInfo info = getUserManager().getUserInfo(userHandle);
+ if (info == null || !info.isManagedProfile()) {
+ return false;
+ }
+ return getDevicePolicyManager().isSeparateProfileChallengeAllowed(userHandle);
+ }
+
+ /**
* Deserialize a pattern.
* @param string The pattern serialized with {@link #patternToString}
* @return The pattern.
@@ -1288,10 +1333,6 @@
}
}
- public static boolean isSeparateWorkChallengeEnabled() {
- return StorageManager.isFileBasedEncryptionEnabled();
- }
-
public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
try {
getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 30593f2..fc1ba44 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -7,6 +7,7 @@
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -Wno-non-virtual-dtor
LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
+LOCAL_CFLAGS += -DHWUI_NEW_OPS
LOCAL_CPPFLAGS += -Wno-conversion-null
ifeq ($(TARGET_ARCH), arm)
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 83fd073..1a86e5f 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -42,7 +42,7 @@
}
static jlong CreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) {
- return reinterpret_cast<jlong>(SkColorFilter::CreateLightingFilter(mul, add));
+ return reinterpret_cast<jlong>(SkColorMatrixFilter::CreateLightingFilter(mul, add));
}
static jlong CreateColorMatrixFilter(JNIEnv* env, jobject, jfloatArray jarray) {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 799ed83..fda0ffa 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -60,19 +60,7 @@
// as all the data needed is contained within the newly created LocalMatrixShader.
SkASSERT(shaderHandle);
SkAutoTUnref<SkShader> currentShader(reinterpret_cast<SkShader*>(shaderHandle));
-
- SkMatrix currentMatrix;
- SkAutoTUnref<SkShader> baseShader(currentShader->refAsALocalMatrixShader(¤tMatrix));
- if (baseShader.get()) {
- // if the matrices are same then there is no need to allocate a new
- // shader that is identical to the existing one.
- if (currentMatrix == *matrix) {
- return reinterpret_cast<jlong>(currentShader.detach());
- }
- return reinterpret_cast<jlong>(SkShader::CreateLocalMatrixShader(baseShader, *matrix));
- }
-
- return reinterpret_cast<jlong>(SkShader::CreateLocalMatrixShader(currentShader, *matrix));
+ return reinterpret_cast<jlong>(currentShader->newWithLocalMatrix(*matrix));
}
///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 6d3c7d7..8e8f6c37 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -152,7 +152,8 @@
static struct {
jmethodID postDynPolicyEventFromNative;
-} gDynPolicyEventHandlerMethods;
+ jmethodID postRecordConfigEventFromNative;
+} gAudioPolicyEventHandlerMethods;
static Mutex gLock;
@@ -378,12 +379,26 @@
const char* zechars = regId.string();
jstring zestring = env->NewStringUTF(zechars);
- env->CallStaticVoidMethod(clazz, gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative,
+ env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
event, zestring, val);
env->ReleaseStringUTFChars(zestring, zechars);
env->DeleteLocalRef(clazz);
+}
+static void
+android_media_AudioSystem_recording_callback(int event, int session, int source)
+{
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ return;
+ }
+
+ jclass clazz = env->FindClass(kClassPathName);
+ env->CallStaticVoidMethod(clazz,
+ gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
+ event, session, source);
+ env->DeleteLocalRef(clazz);
}
static jint
@@ -498,6 +513,22 @@
}
static jint
+android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
+{
+ return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
+}
+
+static jboolean
+android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
+{
+ bool mono;
+ if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
+ mono = false;
+ }
+ return mono;
+}
+
+static jint
android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
{
return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
@@ -1487,6 +1518,12 @@
AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
}
+static void
+android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
+{
+ AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
+}
+
static jint convertAudioMixToNative(JNIEnv *env,
AudioMix *nAudioMix,
@@ -1637,6 +1674,8 @@
{"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
{"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
{"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
+ {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
+ {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
{"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
{"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
{"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
@@ -1659,6 +1698,8 @@
(void *)android_media_AudioSystem_registerPolicyMixes},
{"native_register_dynamic_policy_callback", "()V",
(void *)android_media_AudioSystem_registerDynPolicyCallback},
+ {"native_register_recording_callback", "()V",
+ (void *)android_media_AudioSystem_registerRecordingCallback},
{"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
};
@@ -1762,9 +1803,12 @@
gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
eventHandlerClass, "mJniCallback", "J");
- gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative =
+ gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
"dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
+ gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
+ GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
+ "recordingCallbackFromNative", "(III)V");
jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 2488111..03a1e71 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -84,6 +84,7 @@
jfieldID privateClean_field;
jfieldID sharedClean_field;
jfieldID swappedOut_field;
+ jfieldID swappedOutPss_field;
};
struct stat_field_names {
@@ -94,20 +95,22 @@
const char* privateClean_name;
const char* sharedClean_name;
const char* swappedOut_name;
+ const char* swappedOutPss_name;
};
static stat_fields stat_fields[_NUM_CORE_HEAP];
static stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
{ "otherPss", "otherSwappablePss", "otherPrivateDirty", "otherSharedDirty",
- "otherPrivateClean", "otherSharedClean", "otherSwappedOut" },
+ "otherPrivateClean", "otherSharedClean", "otherSwappedOut", "otherSwappedOutPss" },
{ "dalvikPss", "dalvikSwappablePss", "dalvikPrivateDirty", "dalvikSharedDirty",
- "dalvikPrivateClean", "dalvikSharedClean", "dalvikSwappedOut" },
+ "dalvikPrivateClean", "dalvikSharedClean", "dalvikSwappedOut", "dalvikSwappedOutPss" },
{ "nativePss", "nativeSwappablePss", "nativePrivateDirty", "nativeSharedDirty",
- "nativePrivateClean", "nativeSharedClean", "nativeSwappedOut" }
+ "nativePrivateClean", "nativeSharedClean", "nativeSwappedOut", "nativeSwappedOutPss" }
};
jfieldID otherStats_field;
+jfieldID hasSwappedOutPss_field;
static bool memtrackLoaded;
@@ -119,6 +122,7 @@
int privateClean;
int sharedClean;
int swappedOut;
+ int swappedOutPss;
};
#define BINDER_STATS "/proc/binder/stats"
@@ -206,7 +210,7 @@
return err;
}
-static void read_mapinfo(FILE *fp, stats_t* stats)
+static void read_mapinfo(FILE *fp, stats_t* stats, bool* foundSwapPss)
{
char line[1024];
int len, nameLen;
@@ -216,7 +220,7 @@
float sharing_proportion = 0.0;
unsigned shared_clean = 0, shared_dirty = 0;
unsigned private_clean = 0, private_dirty = 0;
- unsigned swapped_out = 0;
+ unsigned swapped_out = 0, swapped_out_pss = 0;
bool is_swappable = false;
unsigned temp;
@@ -230,6 +234,8 @@
int subHeap = HEAP_UNKNOWN;
int prevHeap = HEAP_UNKNOWN;
+ *foundSwapPss = false;
+
if(fgets(line, sizeof(line), fp) == 0) return;
while (!done) {
@@ -340,6 +346,7 @@
private_clean = 0;
private_dirty = 0;
swapped_out = 0;
+ swapped_out_pss = 0;
while (true) {
if (fgets(line, 1024, fp) == 0) {
@@ -365,6 +372,9 @@
/* referenced = temp; */
} else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
swapped_out = temp;
+ } else if (line[0] == 'S' && sscanf(line, "SwapPss: %d kB", &temp) == 1) {
+ *foundSwapPss = true;
+ swapped_out_pss = temp;
} else if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
// looks like a new mapping
// example: "10000000-10001000 ---p 10000000 00:00 0"
@@ -390,6 +400,7 @@
stats[whichHeap].privateClean += private_clean;
stats[whichHeap].sharedClean += shared_clean;
stats[whichHeap].swappedOut += swapped_out;
+ stats[whichHeap].swappedOutPss += swapped_out_pss;
if (whichHeap == HEAP_DALVIK || whichHeap == HEAP_DALVIK_OTHER) {
stats[subHeap].pss += pss;
stats[subHeap].swappablePss += swappable_pss;
@@ -398,12 +409,13 @@
stats[subHeap].privateClean += private_clean;
stats[subHeap].sharedClean += shared_clean;
stats[subHeap].swappedOut += swapped_out;
+ stats[subHeap].swappedOutPss += swapped_out_pss;
}
}
}
}
-static void load_maps(int pid, stats_t* stats)
+static void load_maps(int pid, stats_t* stats, bool* foundSwapPss)
{
char tmp[128];
FILE *fp;
@@ -412,17 +424,18 @@
fp = fopen(tmp, "r");
if (fp == 0) return;
- read_mapinfo(fp, stats);
+ read_mapinfo(fp, stats, foundSwapPss);
fclose(fp);
}
static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
jint pid, jobject object)
{
+ bool foundSwapPss;
stats_t stats[_NUM_HEAP];
memset(&stats, 0, sizeof(stats));
- load_maps(pid, stats);
+ load_maps(pid, stats, &foundSwapPss);
struct graphics_memory_pss graphics_mem;
if (read_memtrack_memory(pid, &graphics_mem) == 0) {
@@ -442,6 +455,7 @@
stats[HEAP_UNKNOWN].privateClean += stats[i].privateClean;
stats[HEAP_UNKNOWN].sharedClean += stats[i].sharedClean;
stats[HEAP_UNKNOWN].swappedOut += stats[i].swappedOut;
+ stats[HEAP_UNKNOWN].swappedOutPss += stats[i].swappedOutPss;
}
for (int i=0; i<_NUM_CORE_HEAP; i++) {
@@ -452,9 +466,11 @@
env->SetIntField(object, stat_fields[i].privateClean_field, stats[i].privateClean);
env->SetIntField(object, stat_fields[i].sharedClean_field, stats[i].sharedClean);
env->SetIntField(object, stat_fields[i].swappedOut_field, stats[i].swappedOut);
+ env->SetIntField(object, stat_fields[i].swappedOutPss_field, stats[i].swappedOutPss);
}
+ env->SetBooleanField(object, hasSwappedOutPss_field, foundSwapPss);
jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field);
jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0);
@@ -471,6 +487,7 @@
otherArray[j++] = stats[i].privateClean;
otherArray[j++] = stats[i].sharedClean;
otherArray[j++] = stats[i].swappedOut;
+ otherArray[j++] = stats[i].swappedOutPss;
}
env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0);
@@ -481,11 +498,12 @@
android_os_Debug_getDirtyPagesPid(env, clazz, getpid(), object);
}
-static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid, jlongArray outUss,
- jlongArray outMemtrack)
+static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid,
+ jlongArray outUssSwapPss, jlongArray outMemtrack)
{
char line[1024];
jlong pss = 0;
+ jlong swapPss = 0;
jlong uss = 0;
jlong memtrack = 0;
@@ -521,19 +539,31 @@
}
uss += atoi(c);
}
+ } else if (line[0] == 'S' && strncmp(line, "SwapPss:", 8) == 0) {
+ char* c = line + 8;
+ jlong lSwapPss;
+ while (*c != 0 && (*c < '0' || *c > '9')) {
+ c++;
+ }
+ lSwapPss = atoi(c);
+ swapPss += lSwapPss;
+ pss += lSwapPss; // Also in swap, those pages would be accounted as Pss without SWAP
}
}
fclose(fp);
}
- if (outUss != NULL) {
- if (env->GetArrayLength(outUss) >= 1) {
- jlong* outUssArray = env->GetLongArrayElements(outUss, 0);
- if (outUssArray != NULL) {
- outUssArray[0] = uss;
+ if (outUssSwapPss != NULL) {
+ if (env->GetArrayLength(outUssSwapPss) >= 1) {
+ jlong* outUssSwapPssArray = env->GetLongArrayElements(outUssSwapPss, 0);
+ if (outUssSwapPssArray != NULL) {
+ outUssSwapPssArray[0] = uss;
+ if (env->GetArrayLength(outUssSwapPss) >= 2) {
+ outUssSwapPssArray[1] = swapPss;
+ }
}
- env->ReleaseLongArrayElements(outUss, outUssArray, 0);
+ env->ReleaseLongArrayElements(outUssSwapPss, outUssSwapPssArray, 0);
}
}
@@ -1056,6 +1086,7 @@
}
otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
+ hasSwappedOutPss_field = env->GetFieldID(clazz, "hasSwappedOutPss", "Z");
for (int i=0; i<_NUM_CORE_HEAP; i++) {
stat_fields[i].pss_field =
@@ -1072,6 +1103,8 @@
env->GetFieldID(clazz, stat_field_names[i].sharedClean_name, "I");
stat_fields[i].swappedOut_field =
env->GetFieldID(clazz, stat_field_names[i].swappedOut_name, "I");
+ stat_fields[i].swappedOutPss_field =
+ env->GetFieldID(clazz, stat_field_names[i].swappedOutPss_name, "I");
}
return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e8054fc..b02de0e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -103,9 +103,9 @@
<protected-broadcast android:name="android.os.action.SETTING_RESTORED" />
- <protected-broadcast android:name="android.backup.intent.RUN" />
- <protected-broadcast android:name="android.backup.intent.CLEAR" />
- <protected-broadcast android:name="android.backup.intent.INIT" />
+ <protected-broadcast android:name="android.app.backup.intent.RUN" />
+ <protected-broadcast android:name="android.app.backup.intent.CLEAR" />
+ <protected-broadcast android:name="android.app.backup.intent.INIT" />
<protected-broadcast android:name="android.bluetooth.intent.DISCOVERABLE_TIMEOUT" />
<protected-broadcast android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
@@ -205,6 +205,7 @@
<protected-broadcast android:name="android.media.VOLUME_CHANGED_ACTION" />
<protected-broadcast android:name="android.media.MASTER_VOLUME_CHANGED_ACTION" />
<protected-broadcast android:name="android.media.MASTER_MUTE_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.MASTER_MONO_CHANGED_ACTION" />
<protected-broadcast android:name="android.media.SCO_AUDIO_STATE_CHANGED" />
<protected-broadcast android:name="android.media.ACTION_SCO_AUDIO_STATE_UPDATED" />
@@ -384,6 +385,7 @@
<protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
<protected-broadcast android:name="com.android.server.Wifi.action.TOGGLE_PNO" />
<protected-broadcast android:name="intent.action.ACTION_RF_BAND_INFO" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_RESOURCE_GRANTED" />
<protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED" />
<protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL" />
@@ -1069,6 +1071,12 @@
<permission android:name="android.permission.READ_WIFI_CREDENTIAL"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi @hide Allows applications to change tether state and run
+ tether carrier provisioning.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.TETHER_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi @hide Allow system apps to receive broadcast
when a wifi network credential is changed.
<p>Not for use by third-party applications. -->
@@ -2821,6 +2829,12 @@
<permission android:name="android.permission.ACCESS_EPHEMERAL_APPS"
android:protectionLevel="signature" />
+ <!-- Allows receiving the usage of media resource e.g. video/audio codec and
+ graphic memory.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"
+ android:protectionLevel="signature|privileged" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 36c167e..c945459 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Sluit persoonlike data soos kredietkaartnommers en wagwoorde in."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Beheer vertoonskermvergroting"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Beheer die vertoonskerm se zoemvlak en posisionering."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Voer gebare uit"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan tik, swiep, knyp en ander gebare uitvoer."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"deaktiveer of verander statusbalk"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Laat die program toe om die statusbalk te deaktiveer en stelselikone by te voeg of te verwyder."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"wees die statusbalk"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ec16add..17b5a29 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"እንደ የክሬዲት ካርድ ቁጥሮች እና የይለፍ ቃላት ያሉ የግል ውሂብ ያካትታል።"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"የመቆጣጠሪያ ማሳያ እንዲጎላ አደራረግ"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"የማሳያውን የማጉያ ደረጃ እና አቀማመጥ ይቆጣጠሩ።"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"የጣት ምልክቶችን ያከናውኑ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"መታ ማድረግ፣ ማንሸራተት፣ መቆንጠጥ እና ሌሎች የጣት ምልክቶችን ማከናወን ይችላል።"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"የሁኔቴ አሞሌ አቦዝን ወይም ቀይር"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"የስርዓት አዶዎችን ወደ ሁኔታ አሞሌ ላለማስቻል ወይም ለማከል እና ለማስወገድ ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"የሁኔታ አሞሌ መሆን"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 12ef759..efde61f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -260,6 +260,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"يتضمن بيانات شخصية مثل أرقام بطاقات الائتمان وكلمات المرور."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"التحكم في تكبير الشاشة"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"يمكنك التحكم في مستوى التكبير/التصغير للشاشة وتحديد الموضع."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"تنفيذ إيماءات"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"يمكن النقر والتمرير بسرعة والتصغير وتنفيذ إيماءات أخرى."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"تعطيل شريط الحالة أو تعديله"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"للسماح للتطبيق بتعطيل شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"العمل كشريط للحالة"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 7f0e6d7..0e4771e 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Kredit kartı nömrələri və parollar kimi şəxsi məlumatlar daxildir."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ekran böyütməsinə nəzarət edin"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekran yaxınlaşdırma səviyyəsi və yerləşdirməsinə nəzarət edin."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Jestlər ilə əməliyyat aparın"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Digər jestlərə tıklaya, sürüşdürə və əməliyyat apara bilərsiniz."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"status panelini deaktivləşdir və ya dəyişdir"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Tətbiqə status panelini deaktiv etməyə və ya sistem ikonalarını əlavə etmək və ya silmək imkanı verir."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"status paneli edin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index ac5ce66..fd9ddec 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -257,6 +257,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Obuhvata lične podatke kao što su brojevi kreditnih kartica i lozinke."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Upravljaj uvećanjem prikaza"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Upravlja nivoom zumiranja prikaza i određivanjem položaja."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Obavljanje pokreta"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može da dodiruje, lista, skuplja prikaz i obavlja druge pokrete."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili izmena statusne trake"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Dozvoljava aplikaciji da onemogući statusnu traku ili da dodaje i uklanja sistemske ikone."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"funkcionisanje kao statusna traka"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 301e1e3..955727b 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Включва лични данни, като например номера на кредитни карти и пароли."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Управление на увеличението на дисплея"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управление на нивото на мащаба и позиционирането на дисплея."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Извършване на жестове"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можете да докосвате, да прекарвате пръст, да събирате пръсти и да извършвате други жестове."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"деактивиране или промяна на лентата на състоянието"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"изпълняване на ролята на лента на състоянието"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 9c88d44..6e7a77f 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ক্রেডিট কার্ডের নম্বর ও পাসওয়ার্ডগুলির মতো ব্যক্তিগত তথ্য অন্তর্ভুক্ত করে৷"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"প্রদর্শনের বৃহত্তরীকরণ ব্যবস্থা নিয়ন্ত্রণ করুন"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"প্রদর্শনের জুমের স্তর এবং অবস্থান নির্ধারন নিয়ন্ত্রণ করুন৷"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"অঙ্গভঙ্গির কাজগুলি সম্পাদন করুন"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"আলতো চাপ দেওয়া, সোয়াইপ, পিঞ্চ করা এবং অন্যান্য অঙ্গভঙ্গির কাজগুলি সম্পাদন করতে পারবেন৷"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"স্থিতি দন্ড নিষ্ক্রিয় অথবা সংশোধন করে"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"অ্যাপ্লিকেশানকে স্থিতি দন্ড অক্ষম করতে এবং সিস্টেম আইকনগুলি সরাতে দেয়৷"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"স্থিতি দন্ডে থাকুন"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 8554b84..bbe9887 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclou dades personals com ara números de targetes de crèdit i contrasenyes."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controla l\'ampliació de la pantalla"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el nivell i el posicionament del zoom de la pantalla."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Utilitza gestos"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Pot tocar, lliscar, pessigar i utilitzar altres gestos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra d\'estat"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permet que l\'aplicació desactivi la barra d\'estat o afegeixi i elimini icones del sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"aparèixer a la barra d\'estat"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 2eca49a..f5763f9 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Sledování zahrnuje osobní údaje, jako jsou například čísla kreditních karet a hesla."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Nastavení zvětšení obsahu obrazovky"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Určuje umístění a úroveň přiblížení displeje."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Provádění gest"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Může provádět gesta klepnutí, přejetí, stažení prstů a další."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"zakázání či změny stavového řádku"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikaci zakázat stavový řádek nebo přidat či odebrat systémové ikony."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vydávání se za stavový řádek"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 2a719b0..3e8a86d 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Dette omfatter personlige data såsom kreditkortnumre og adgangskoder."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kontrollér skærmforstørrelsen"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér skærmens zoomniveau og position."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Udfør bevægelser"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"deaktiver eller rediger statuslinje"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Tillader, at appen kan deaktivere statusbjælken eller tilføje og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vær statusbjælken"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index d116a24..e2fb6ff 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -56,10 +56,10 @@
<string name="badPin" msgid="9015277645546710014">"Die von Ihnen eingegebene alte PIN ist nicht korrekt."</string>
<string name="badPuk" msgid="5487257647081132201">"Der von Ihnen eingegebene PUK ist nicht korrekt."</string>
<string name="mismatchPin" msgid="609379054496863419">"Die von Ihnen eingegebenen PIN-Nummern stimmen nicht überein."</string>
- <string name="invalidPin" msgid="3850018445187475377">"Geben Sie eine PIN ein, die 4 bis 8 Zahlen enthält."</string>
- <string name="invalidPuk" msgid="8761456210898036513">"Geben Sie eine mindestens achtstellige PUK ein."</string>
- <string name="needPuk" msgid="919668385956251611">"Ihre SIM-Karte ist mit einem PUK gesperrt. Geben Sie zum Entsperren den PUK-Code ein."</string>
- <string name="needPuk2" msgid="4526033371987193070">"Geben Sie zum Entsperren der SIM-Karte den PUK2 ein."</string>
+ <string name="invalidPin" msgid="3850018445187475377">"Gib eine PIN ein, die 4 bis 8 Zahlen enthält."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Gib eine mindestens achtstellige PUK ein."</string>
+ <string name="needPuk" msgid="919668385956251611">"Deine SIM-Karte ist mit einem PUK gesperrt. Gib zum Entsperren den PUK-Code ein."</string>
+ <string name="needPuk2" msgid="4526033371987193070">"Gib zum Entsperren der SIM-Karte den PUK2 ein."</string>
<string name="enablePin" msgid="209412020907207950">"Fehler. SIM-/RUIM-Sperre aktivieren."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
<item quantity="other">Sie haben noch <xliff:g id="NUMBER_1">%d</xliff:g> Versuche, bevor Ihre SIM-Karte gesperrt wird.</item>
@@ -87,7 +87,7 @@
<string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Beschränkt"</string>
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Nicht beschränkt"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Dienst nicht eingerichtet."</string>
- <string name="CLIRPermanent" msgid="3377371145926835671">"Sie können die Einstellung für die Anrufer-ID nicht ändern."</string>
+ <string name="CLIRPermanent" msgid="3377371145926835671">"Du kannst die Einstellung für die Anrufer-ID nicht ändern."</string>
<string name="RestrictedChangedTitle" msgid="5592189398956187498">"Eingeschränkter Zugriff geändert"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Daten-Dienst ist gesperrt."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Notruf ist gesperrt."</string>
@@ -156,7 +156,7 @@
<string name="httpErrorBadUrl" msgid="3636929722728881972">"Die Seite kann nicht geöffnet werden, weil die URL ungültig ist."</string>
<string name="httpErrorFile" msgid="2170788515052558676">"Auf die Datei konnte nicht zugegriffen werden."</string>
<string name="httpErrorFileNotFound" msgid="6203856612042655084">"Die angeforderte Datei wurde nicht gefunden."</string>
- <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Es werden zurzeit zu viele Anfragen verarbeitet. Versuchen Sie es später erneut."</string>
+ <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Es werden zurzeit zu viele Anfragen verarbeitet. Versuche es später erneut."</string>
<string name="notification_title" msgid="8967710025036163822">"Fehler bei Anmeldung für <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"Synchronisierung"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisierung"</string>
@@ -198,7 +198,7 @@
<string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Ihr Fernseher wird ausgeschaltet."</string>
<string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ihre Uhr wird heruntergefahren."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon wird heruntergefahren."</string>
- <string name="shutdown_confirm_question" msgid="2906544768881136183">"Möchten Sie das Gerät herunterfahren?"</string>
+ <string name="shutdown_confirm_question" msgid="2906544768881136183">"Möchtest du das Gerät herunterfahren?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Im abgesicherten Modus starten"</string>
<string name="reboot_safemode_confirm" msgid="55293944502784668">"Möchten Sie im abgesicherten Modus neu starten? Dadurch werden alle Apps von Drittanbietern deaktiviert, die Sie installiert haben. Sie werden jedoch nach einem weiteren Neustart wiederhergestellt."</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Kürzlich geöffnet"</string>
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Einschließlich personenbezogener Daten wie Kreditkartennummern und Passwörter."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Displayvergrößerung festlegen"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Legt die Zoom-Stufe des Displays und die Zoom-Position auf dem Display fest."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Bewegungen möglich"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Tippen, Wischen, Zusammenziehen und andere Bewegungen möglich."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Statusleiste darstellen"</string>
@@ -650,11 +652,11 @@
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Passwort zum Entsperren eingeben"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"PIN zum Entsperren eingeben"</string>
<string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Falscher PIN-Code"</string>
- <string name="keyguard_label_text" msgid="861796461028298424">"Drücken Sie zum Entsperren die Menütaste und dann auf \"0\"."</string>
+ <string name="keyguard_label_text" msgid="861796461028298424">"Drücke zum Entsperren die Menütaste und dann auf \"0\"."</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Notrufnummer"</string>
<string name="lockscreen_carrier_default" msgid="6169005837238288522">"Kein Dienst"</string>
<string name="lockscreen_screen_locked" msgid="7288443074806832904">"Display gesperrt"</string>
- <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Drücken Sie die Menütaste, um das Telefon zu entsperren oder einen Notruf zu tätigen."</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Drücke die Menütaste, um das Telefon zu entsperren oder einen Notruf zu tätigen."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Zum Entsperren die Menütaste drücken"</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Muster zum Entsperren zeichnen"</string>
<string name="lockscreen_emergency_call" msgid="5298642613417801888">"Notfall"</string>
@@ -667,10 +669,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Keine SIM-Karte im Tablet"</string>
<string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"Keine SIM-Karte im Fernseher"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Keine SIM-Karte im Telefon"</string>
- <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Legen Sie eine SIM-Karte ein."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM-Karte fehlt oder ist nicht lesbar. Bitte legen Sie eine SIM-Karte ein."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Lege eine SIM-Karte ein."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM-Karte fehlt oder ist nicht lesbar. Bitte lege eine SIM-Karte ein."</string>
<string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"SIM-Karte unbrauchbar"</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"Ihre SIM-Karte wurde dauerhaft deaktiviert.\n Wenden Sie sich an Ihren Mobilfunkanbieter, um eine andere SIM-Karte zu erhalten."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"Deine SIM-Karte wurde dauerhaft deaktiviert.\n Wende dich an deinen Mobilfunkanbieter, um eine andere SIM-Karte zu erhalten."</string>
<string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"Vorheriger Titel"</string>
<string name="lockscreen_transport_next_description" msgid="573285210424377338">"Nächster Titel"</string>
<string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"Pausieren"</string>
@@ -681,22 +683,22 @@
<string name="emergency_calls_only" msgid="6733978304386365407">"Nur Notrufe"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netzwerk gesperrt"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"PUK-Sperre auf SIM"</string>
- <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Weitere Informationen erhalten Sie im Nutzerhandbuch oder beim Kundendienst."</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Weitere Informationen erhältst du im Nutzerhandbuch oder beim Kundendienst."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"PIN eingeben"</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM-Karte wird entsperrt..."</string>
- <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. \n\nBitte versuchen Sie es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
- <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Sie haben Ihr Passwort <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuchen Sie es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
- <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Sie haben Ihr Passwort <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuchen Sie es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Tablet mithilfe Ihrer Google-Anmeldeinformationen zu entsperren.\n\n Bitte versuchen Sie es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. \n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
+ <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Du hast dein Passwort <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Du hast dein Passwort <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Tablet mithilfe deiner Google-Anmeldeinformationen zu entsperren.\n\n Bitte versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Wenn Sie es noch <xliff:g id="NUMBER_1">%2$d</xliff:g>-mal falsch eingeben, werden Sie aufgefordert, Ihren Fernseher mithilfe Ihrer Google-Anmeldeinformationen zu entsperren.\n\n Versuchen Sie es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden erneut."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen werden Sie aufgefordert, Ihr Telefon mithilfe Ihrer Google-Anmeldeinformationen zu entsperren.\n\nBitte versuchen Sie es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Sie haben <xliff:g id="NUMBER_0">%1$d</xliff:g> Mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird das Tablet auf die Werkseinstellungen zurückgesetzt und alle Nutzerdaten gehen verloren."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Telefon mithilfe deiner Google-Anmeldeinformationen zu entsperren.\n\nBitte versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden noch einmal."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g> Mal erfolglos versucht, das Tablet zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird das Tablet auf die Werkseinstellungen zurückgesetzt und alle Nutzerdaten gehen verloren."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Sie haben <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal erfolglos versucht, den Fernseher zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird der Fernseher auf die Werkseinstellungen zurückgesetzt und alle Nutzerdaten gehen verloren."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Sie haben <xliff:g id="NUMBER_0">%1$d</xliff:g> Mal erfolglos versucht, das Telefon zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird das Telefon auf die Werkseinstellungen zurückgesetzt und alle Nutzerdaten gehen verloren."</string>
- <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Sie haben <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Das Tablet wird nun auf die Werkseinstellungen zurückgesetzt."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Du hast <xliff:g id="NUMBER_0">%1$d</xliff:g> Mal erfolglos versucht, das Telefon zu entsperren. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wird das Telefon auf die Werkseinstellungen zurückgesetzt und alle Nutzerdaten gehen verloren."</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Tablet zu entsperren. Das Tablet wird nun auf die Werkseinstellungen zurückgesetzt."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Sie haben <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, den Fernseher zu entsperren. Der Fernseher wird nun auf die Werkseinstellungen zurückgesetzt."</string>
- <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Sie haben <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Das Telefon wird nun auf die Werkseinstellungen zurückgesetzt."</string>
- <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Versuchen Sie es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden erneut."</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Du hast <xliff:g id="NUMBER">%d</xliff:g>-mal erfolglos versucht, das Telefon zu entsperren. Das Telefon wird nun auf die Werkseinstellungen zurückgesetzt."</string>
+ <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Versuche es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden erneut."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Muster vergessen?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Kontoentsperrung"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Zu viele Schemaversuche"</string>
@@ -786,11 +788,11 @@
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ermöglicht der App, Nachrichten zu Ihrem Mailbox-Posteingang hinzuzufügen"</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Geolokalisierungsberechtigungen des Browsers ändern"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ermöglicht der App, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Apps können so Standortinformationen an beliebige Websites senden."</string>
- <string name="save_password_message" msgid="767344687139195790">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
+ <string name="save_password_message" msgid="767344687139195790">"Möchtest du, dass der Browser dieses Passwort speichert?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nicht jetzt"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Speichern"</string>
<string name="save_password_never" msgid="8274330296785855105">"Nie"</string>
- <string name="open_permission_deny" msgid="7374036708316629800">"Sie sind nicht zum Öffnen dieser Seite berechtigt."</string>
+ <string name="open_permission_deny" msgid="7374036708316629800">"Du bist nicht zum Öffnen dieser Seite berechtigt."</string>
<string name="text_copied" msgid="4985729524670131385">"Text in Zwischenablage kopiert."</string>
<string name="more_item_label" msgid="4650918923083320495">"Mehr"</string>
<string name="prepend_shortcut_label" msgid="2572214461676015642">"Menü+"</string>
@@ -903,10 +905,10 @@
<string name="aerr_process" msgid="4507058997035697579">"Der Prozess \"<xliff:g id="PROCESS">%1$s</xliff:g>\" wurde beendet."</string>
<string name="aerr_process_silence" msgid="4226685530196000222">"Silence stürzt bei <xliff:g id="PROCESS">%1$s</xliff:g> bis zum Neustart ab."</string>
<string name="anr_title" msgid="4351948481459135709"></string>
- <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> reagiert nicht.\n\nMöchten Sie die App schließen?"</string>
- <string name="anr_activity_process" msgid="5776209883299089767">"Aktivität \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" reagiert nicht.\n\nMöchten Sie sie beenden?"</string>
- <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> reagiert nicht. Möchten Sie die App schließen?"</string>
- <string name="anr_process" msgid="6513209874880517125">"Prozess \"<xliff:g id="PROCESS">%1$s</xliff:g>\" reagiert nicht.\n\nMöchten Sie ihn beenden?"</string>
+ <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> reagiert nicht.\n\nMöchtest du die App schließen?"</string>
+ <string name="anr_activity_process" msgid="5776209883299089767">"Aktivität \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\" reagiert nicht.\n\nMöchtest du sie beenden?"</string>
+ <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> reagiert nicht. Möchtest du die App schließen?"</string>
+ <string name="anr_process" msgid="6513209874880517125">"Prozess \"<xliff:g id="PROCESS">%1$s</xliff:g>\" reagiert nicht.\n\nMöchtest du ihn beenden?"</string>
<string name="force_close" msgid="8346072094521265605">"OK"</string>
<string name="report" msgid="4060218260984795706">"Bericht"</string>
<string name="wait" msgid="7147118217226317732">"Warten"</string>
@@ -1094,7 +1096,7 @@
<string name="dial_number_using" msgid="5789176425167573586">"Nummer\nmit <xliff:g id="NUMBER">%s</xliff:g> wählen"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Neuer Kontakt\nmit <xliff:g id="NUMBER">%s</xliff:g> erstellen"</string>
<string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Die folgenden Apps benötigen die Berechtigung zum aktuellen und zukünftigen Zugriff auf Ihr Konto."</string>
- <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Möchten Sie diese Anfrage zulassen?"</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Möchtest du diese Anfrage zulassen?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"Zugriffsanforderung"</string>
<string name="allow" msgid="7225948811296386551">"Zulassen"</string>
<string name="deny" msgid="2081879885755434506">"Ablehnen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8116b16..3e277c3 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Περιλαμβάνει προσωπικά δεδομένα, όπως είναι οι αριθμοί πιστωτικών καρτών και οι κωδικοί πρόσβασης."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ελέγξτε τη μεγέθυνση της οθόνης"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ελέγξτε το επίπεδο ζουμ και τη θέση της οθόνης."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Εκτέλεση κινήσεων"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Επιτρέπει το πάτημα, την ολίσθηση, το πλησίασμα και άλλες κινήσεις."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"απενεργοποίηση ή τροποποίηση γραμμής κατάστασης"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Επιτρέπει στην εφαρμογή να απενεργοποιεί τη γραμμή κατάστασης ή να προσθέτει και να αφαιρεί εικονίδια συστήματος."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ορισμός ως γραμμής κατάστασης"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 930c310..0edc438 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Includes personal data such as credit card numbers and passwords."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Control display magnification"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 930c310..0edc438 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Includes personal data such as credit card numbers and passwords."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Control display magnification"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 930c310..0edc438 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Includes personal data such as credit card numbers and passwords."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Control display magnification"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Control the display\'s zoom level and positioning."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Perform gestures"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Can tap, swipe, pinch and perform other gestures."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Allows the app to disable the status bar or add and remove system icons."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"be the status bar"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 258ef33..bd2f91b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Incluye datos personales, como números de tarjeta de crédito y contraseñas."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlar la ampliación de pantalla"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Usar gestos"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permite presionar, deslizar, pellizcar y usar otros gestos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"aparecer en la barra de estado"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 9848bb6..e73b425 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Incluye datos personales como números de tarjetas de crédito y contraseñas."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controla la ampliación de la pantalla"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controla el posicionamiento y el nivel de zoom de la pantalla."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar gestos"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Puedes tocar y pellizcar la pantalla, deslizar el dedo y hacer otros gestos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"inhabilitar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que la aplicación inhabilite la barra de estado o añada y elimine iconos del sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"aparecer en la barra de estado"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 466bd5d..e6a122c 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Sisaldab isiklikke andmeid, nt krediitkaardi numbreid ja paroole."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ekraani suurenduse juhtimine"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Saate juhtida ekraani suumitaset ja asendit."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Liigutuste tegemine"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Saate puudutada, pühkida, sõrmi kokku-lahku liigutada ja teisi liigutusi teha."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"keela või muuda olekuriba"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Võimaldab rakendusel keelata olekuriba või lisada ja eemaldada süsteemiikoone."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"olekuribana kuvamine"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index cdb8622..31a073b 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Ez da salbuespenik egiten datu pertsonalekin, hala nola, kreditu-txartelen zenbakiekin eta pasahitzekin."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kontrolatu pantailaren zoom-maila"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolatu pantailaren zoom-maila eta kokapena."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Keinuak egin"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Sakatu, lerratu, atximurkatu eta beste hainbat keinu egin ditzake."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Desgaitu edo aldatu egoera-barra"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Bihurtu egoera-barra"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b0da5fe..f0271d6 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"اطلاعات شخصی مانند شماره کارت اعتباری و گذرواژهها را لحاظ میکند."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"کنترل درشتنمایی نمایشگر"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"سطح و موقعیت بزرگنمایی نمایشگر را کنترل کنید."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"اجرای اشارهها"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"میتوانید ضربه بزنید، انگشتتان را تند بکشید، انگشتانتان را به هم نزدیک یا از هم دور کنید و اشارههای دیگری اجرا کنید."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"به برنامه اجازه میدهد تا نوار وضعیت را غیرفعال کند یا نمادهای سیستم را اضافه یا حذف کند."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"نوار وضعیت باشد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index f7db678..3e0c172 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Sisältää henkilökohtaisia tietoja, kuten luottokortin numeroita ja salasanoja."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Näytön suurentamisen hallinnointi"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Hallinnoi näytön zoomaustasoa ja asettelua."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Eleiden käyttäminen"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Lupa napauttaa, pyyhkäistä, nipistää ja käyttää muita eleitä."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Antaa sovelluksen poistaa tilapalkin käytöstä ja lisätä tai poistaa järjestelmäkuvakkeita."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"sijaita tilapalkissa"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 50aed95..8450e5c 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclut des données personnelles telles que les numéros de cartes de paiement et les mots de passe."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Contrôler l\'agrandissement de l\'écran"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Contrôler le niveau de zoom et le positionnement de l\'écran."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Effectuer des gestes"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Peut toucher, balayer, pincer et effectuer d\'autres gestes."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"désactiver ou modifier la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"servir de barre d\'état"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 33d2016..84c43fac 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclut des données personnelles telles que les numéros de cartes de paiement et les mots de passe."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Contrôler l\'agrandissement de l\'écran"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Contrôler le niveau de zoom et le positionnement de l\'écran"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Effectuer des gestes"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Permet d\'appuyer sur l\'écran, de le balayer, de le pincer et d\'effectuer d\'autres gestes."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Désactivation ou modification de la barre d\'état"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permet à l\'application de désactiver la barre d\'état, ou d\'ajouter et de supprimer des icônes système."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"remplacer la barre d\'état"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 7947825..36594e0 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclúe datos persoais como números e contrasinais de tarxetas de crédito."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlar ampliación da pantalla"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o nivel do zoom e o posicionamento da pantalla"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar xestos"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Podes tocar, pasar o dedo, beliscar e realizar outros xestos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desactivar ou modificar a barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite á aplicación desactivar a barra de estado ou engadir e eliminar as iconas do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"actuar como a barra de estado"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index aa9478b..9d098fc 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ક્રેડિટ કાર્ડ નંબર્સ અને પાસવર્ડ્સ જેવો વ્યક્તિગત ડેટા શામેલ છે."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"પ્રદર્શન વિસ્તૃતિકરણ નિયંત્રિત કરો"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"પ્રદર્શનનું ઝૂમ સ્તર અને સ્થિતિનિર્ધારણ નિયંત્રિત કરો."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"હાવભાવ કરો"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ટૅપ, સ્વાઇપ, પિંચ કરી અને અન્ય હાવભાવ કરી શકે છે."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"સ્થિતિ બાર અક્ષમ કરો અથવા સંશોધિત કરો"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"એપ્લિકેશનને સ્થિતિ બાર અક્ષમ કરવાની અથવા સિસ્ટમ આયકન્સ ઉમેરવા અને દૂર કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"સ્થિતિ બાર થાઓ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index d3d1e2c..5741d5c 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"क्रेडिट कार्ड नंबर और पासवर्ड जैसा व्यक्तिगत डेटा शामिल होता है."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"प्रदर्शन आवर्धन नियंत्रित करें"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शन का ज़ूम स्तर और स्थिति निर्धारण नियंत्रित करें."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"हावभाव निष्पादित करें"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"इस सेवा के द्वारा टैप किया जा सकता है, स्वाइप किया जा सकता है, पिंच किया जा सकता है और अन्य हावभाव निष्पादित किए जा सकते हैं."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"स्थिति बार अक्षम या बदलें"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ऐप्स को स्थिति बार अक्षम करने या सिस्टम आइकन को जोड़ने या निकालने देता है."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"स्थिति बार होने दें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index dc55c57..f635b15 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -257,6 +257,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Uključuje osobne podatke kao što su brojevi kreditnih kartica i zaporke."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kontrola uvećanja zaslona"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolira razinu zumiranja i položaj zaslona."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Izvođenje pokreta"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Može dodirnuti, prijeći prstom, spojiti prste i izvoditi druge pokrete."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili izmjena trake statusa"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Aplikaciji omogućuje onemogućavanje trake statusa ili dodavanje i uklanjanje sistemskih ikona."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"biti traka statusa"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 3176c65..64a674c 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Beleértve a személyes adatokat, például a hitelkártyaszámokat és jelszavakat."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"A kijelző nagyításának vezérlése"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"A kijelző nagyítási/kicsinyítési szintjének és pozíciójának vezérlése"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Kézmozdulatok végrehajtása"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Koppintás, ujjak gyors csúsztatása és összehúzása, illetve egyéb kézmozdulatok végrehajtása."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"állapotsor kikapcsolása vagy módosítása"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását, illetve rendszerikonok hozzáadását és eltávolítását."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"az állapotsor szerepének átvétele"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index d72ee8d..8d6272a 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Ներառում է անձնական տվյալներ, ինչպիսիք են վարկային քարտերի համարները և գաղտնաբառերը:"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ցուցասարքի խոշորացման կառավարում"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ցուցասարքի մասշտաբավորման և դիրքավորման կառավարում:"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Կատարել ժեստեր"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Կարող է հպել, թերթել, պտղունցել և կատարել այլ ժեստեր:"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"անջատել կամ փոփոխել կարգավիճակի գոտին"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Թույլ է տալիս հավելվածին անջատել կարգավիճակի գոտին կամ ավելացնել ու հեռացնել համակարգի պատկերակները:"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"լինել կարգավիճակի գոտի"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 024eea4..898f6d1 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Meliputi data pribadi seperti nomor kartu kredit dan sandi."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Mengontrol perbesaran layar"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Mengontrol tingkat zoom dan pemosisian layar."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Melakukan isyarat"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Dapat mengetuk, menggesek, mencubit, dan melakukan isyarat lainnya."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"nonaktifkan atau ubah bilah status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Mengizinkan apl menonaktifkan bilah status atau menambah dan menghapus ikon sistem."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"jadikan bilah status"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 240c715..ebcde5d 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Felur í sér persónuleg gögn á borð við kreditkortanúmer og aðgangsorð."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Stilla skjástærð"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Stjórnaðu aðdrætti og afstöðu skjásins."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Nota bendingar"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Getur ýtt, strokið, fært fingur saman og gert ýmsar aðrar bendingar."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"slökkva á eða breyta stöðustiku"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Leyfir forriti að slökkva á stöðustikunni eða bæta við og fjarlægja kerfistákn."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vera stöðustikan"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ece503d..d064684 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Sono inclusi dati personali come numeri di carte di credito e password."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlla l\'ingrandimento del display"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlla il livello di zoom e la posizione del display."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Esegui gesti"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Consente di toccare, far scorrere, pizzicare ed eseguire altri gesti."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"disattivare o modificare la barra di stato"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ruolo di barra di stato"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 144afc0..375bdf0 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"כולל נתונים אישיים כמו מספרי כרטיס אשראי וסיסמאות."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"שליטה בהגדלת התצוגה"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"קבע את המרחק מהתצוגה ואת מיקום התצוגה."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ביצוע תנועות"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"יכול להקיש, להחליק, לעשות תנועת צביטה ולבצע תנועות אחרות."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"השבת או שנה את שורת המצב"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"מאפשר לאפליקציה להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"להיות שורת הסטטוס"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index edfab22..a32a8ed 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"クレジットカードの番号やパスワードなどの個人データが含まれます。"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"画面の拡大の制御"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"画面のズームレベルと位置を制御します。"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"操作の実行"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"タップ、スワイプ、ピンチ、その他の操作を行えます。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ステータスバーの無効化や変更"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ステータスバーの無効化、システムアイコンの追加や削除をアプリに許可します。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ステータスバーへの表示"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index ffdd31c..f2fc953 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"შეიცავს ისეთ პირად მონაცემებს, როგორიცაა საკრედიტო ბარათის ნომრები და პაროლები."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ერანის გადიდების მართვა"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ეკრანის მასშტაბირების დონისა და პოზიციის მართვა."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ჟესტების შესრულება"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"შეუძლია შეხება, გადაფურცვლა, მასშტაბირება და სხვა ჟესტების შესრულება."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"სტატუსის ზოლის გათიშვა ან ცვლილება"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"აპს შეეძლება სტატუსების ზოლის გათიშვა და სისტემის ხატულების დამატება/წაშლა."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"სტატუსის ზოლის ჩანაცვლება"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index ff58eaa..ab82fd4 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Кредит карта нөмірі және кілтсөздер сияқты жеке деректерді қоса."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Дисплей ұлғайтуды басқару"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Дисплейдің масштабтау деңгейін және орналастыруды басқару."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Қимылдарды орындау"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Түртуге, жанауға, қысуға және басқа қимылдарды орындауға болады."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"күйін көрсету тақтасын өшіру немесе өзгерту"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Қолданбаға күй жолағын өшіруге немесе жүйелік белгішелерді қосуға және жоюға рұқсат береді."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"күй жолағы болу"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 261212f..ffb3599 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"រួមបញ្ចូលទិន្នន័យផ្ទាល់ខ្លួន ដូចជាលេខកាតឥណទាន និងពាក្យសម្ងាត់។"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"គ្រប់គ្រងការពង្រីកអេក្រង់"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"គ្រប់គ្រងការកំណត់ទីតាំង និងកម្រិតពង្រីករបស់អេក្រង់"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ធ្វើកាយវិការ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"អាចប៉ះ អូស ច្បិច និងធ្វើកាយវិការផ្សេងទៀត"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"បិទ ឬកែរបារស្ថានភាព"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ឲ្យកម្មវិធីបិទរបារស្ថានភាព ឬបន្ថែម និងលុបរូបតំណាងប្រព័ន្ធ។"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ធ្វើជារបារស្ថានភាព"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index f083702..ab7ad82 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್ ಸಂಖ್ಯೆಗಳು ಮತ್ತು ಪಾಸ್ವರ್ಡ್ಗಳಂತಹ ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ಪ್ರದರ್ಶನದ ವರ್ಧಕವನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ಪ್ರದರ್ಶನದ ಝೂಮ್ ಮಟ್ಟ ಮತ್ತು ಸ್ಥಾನ ನಿರ್ಧಾರವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ಗೆಸ್ಚರ್ಗಳನ್ನು ಮಾಡಿ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ಟ್ಯಾಪ್ ಮಾಡಬಹುದು, ಸ್ವೈಪ್ ಮಾಡಬಹುದು, ಪಿಂಚ್ ಮಾಡಬಹುದು ಮತ್ತು ಇತರ ಗೆಸ್ಚರ್ಗಳನ್ನು ಮಾಡಬಹುದು."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇಲ್ಲವೇ ಮಾರ್ಪಡಿಸಿ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಮತ್ತು ಸಿಸ್ಟಂ ಐಕಾನ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಾಗಿರಲು"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index c8f08c7..4c478aa 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"신용카드 번호와 비밀번호 등의 개인 데이터를 포함합니다."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"디스플레이 배율 제어"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"디스플레이의 확대/축소 수준 및 위치를 제어합니다."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"동작 실행"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"탭, 스와이프, 확대/축소 및 기타 동작을 실행할 수 있습니다."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"상태 표시줄 사용 중지 또는 수정"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"앱이 상태 표시줄을 사용중지하거나 시스템 아이콘을 추가 및 제거할 수 있도록 허용합니다."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"상태 표시줄에 위치"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 4d84933..e9b01d1 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Кредиттик карта номурлары жана сырсөздөр сыяктуу өздүк берилиштерди камтыйт."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Дисплейди чоңойтууну башкаруу"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Экрандагы сүрөттүн өлчөмүн өзгөртүү жана жайгаштыруу."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Жаңсоолорду аткаруу"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Таптап, серпип, чымчып жана башка жаңсоолорду аткара алат."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"абал тилкесин өчүрүү же өзгөртүү"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Колдонмого абал тилкесин өчүрүү же тутум сүрөтчөлөрүн кошуу же алып салуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"абал тилкесинин милдетин аткаруу"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 12d67bb..cf21944 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ຮວມທັງຂໍ້ມູນສ່ວນໂຕເຊັ່ນ: ເລກບັດເຄຣດິດ ແລະລະຫັດຜ່ານ."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ຄວບຄຸມການຂະຫຍາຍຈໍສະແດງຜົນ"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ຄວບຄຸມລະດັບການຊູມ ແລະການວາງຕຳແໜ່ງຂອງຈໍສະແດງຜົນ."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ດຳເນີນທ່າທາງຕ່າງໆ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ສາມາດແຕະ, ປັດນີ້ວມື, ຢິບນິ້ວມື ແລະ ດຳເນີນທ່າທາງອື່ນ."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ປິດການນນຳໃຊ້ ຫຼື ແກ້ໄຂແຖບສະຖານະ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງແຖບສະຖານະ ຫຼືເພີ່ມ ແລະລຶບໄອຄອນລະບົບອອກໄດ້."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ເປັນແຖບສະຖານະ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index e35edd6..f1143fe 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Įtraukiami asmeniniai duomenys, pavyzdžiui, kredito kortelių numeriai ir slaptažodžiai."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ekrano didinimo valdymas"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Valdykite ekrano mastelio keitimo lygį ir pozicijos nustatymą."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Veiksmai gestais"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Galima paliesti, perbraukti, suimti ir atlikti kitus veiksmus gestais."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"išjungti ar keisti būsenos juostą"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Leidžiama programai neleisti būsenos juostos arba pridėti ir pašalinti sistemos piktogramas."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"būti būsenos juosta"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index de02a4f..f8644004 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -257,6 +257,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Ietver personas datus, piemēram, kredītkartes numurus un paroles."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Displeja palielinājuma kontrole"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolējiet displeja tālummaiņas līmeni un pozicionēšanu."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Žestu izpilde"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Atbalsta pieskaršanos, vilkšanu, savilkšanu un citus žestus."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"atspējot vai pārveidot statusa joslu"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ļauj lietotnei atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Būt par statusa joslu"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 96a29a5..484e5a6 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Опфаќа лични податоци како што се броеви на кредитни картички и лозинки."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Контролирајте го зголемувањето на екранот"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Контролирајте го нивото на зумирање и позиционирање на екранот."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Користете движења"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Може да допрете, повлечете, штипнете и да користите други движења."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"оневозможи или измени статусна лента"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дозволува апликацијата да ја оневозможи статусната лента или да додава или отстранува системски икони."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"да стане статусна лента"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index f6869e3..42a9a82 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ക്രെഡിറ്റ് കാർഡ് നമ്പറുകളും പാസ്വേഡുകളും പോലുള്ള വ്യക്തിഗത ഡാറ്റ ഉൾപ്പെടുന്നു."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ഡിസ്പ്ലേ മാഗ്നിഫിക്കേഷൻ നിയന്ത്രിക്കുക"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ഡിസ്പ്ലേയുടെ സൂം നിലയും പൊസിഷനിംഗും നിയന്ത്രിക്കുക."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ജെസ്റ്ററുകൾ നിർവഹിക്കുക"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ടാപ്പുചെയ്യാനോ സ്വൈപ്പുചെയ്യാനോ പിഞ്ചുചെയ്യാനോ മറ്റ് ജെസ്റ്ററുകൾ നിർവഹിക്കാനോ കഴിയും."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"സ്റ്റാറ്റസ് ബാർ പ്രവർത്തനരഹിതമാക്കുക അല്ലെങ്കിൽ പരിഷ്ക്കരിക്കുക"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"നില ബാർ പ്രവർത്തരഹിതമാക്കുന്നതിന് അല്ലെങ്കിൽ സിസ്റ്റം ഐക്കണുകൾ ചേർക്കുന്നതിനും നീക്കംചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"സ്റ്റാറ്റസ് ബാർ ആയിരിക്കുക"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index d982ece..91b9ea7e 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Кредит картын дугаар болон нууц үг зэрэг хувийн датаг агуулж байна."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Дэлгэцийн өсгөлтийг хянах"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Дэлгэцийн томруулах түвшин болон байршлыг хянах."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Зангах"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Товших, шудрах, жижигрүүлэх болон бусад зангааг хийх боломжтой."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"статус самбарыг идэвхгүй болгох болон өөрчлөх"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Апп нь статус самбарыг идэвхгүй болгох эсвэл систем дүрсийг нэмэх, хасах боломжтой."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"статусын хэсэг болох"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 4087199..0cb37da 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"क्रेडिट कार्ड नंबर आणि संकेतशब्द यासारखा वैयक्तिक डेटा समाविष्ट करते."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"प्रदर्शन विस्तृतीकरण नियंत्रित करा"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शनाचा झूम स्तर आणि स्थिती निर्धारण नियंत्रित करा."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"जेश्चर करा"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"टॅप, स्वाइप, पिंच आणि इतर जेश्चर करू शकते."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टीम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"स्टेटस बार होऊ द्या"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 0923e91..d40c7d1 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Termasuk data peribadi seperti nombor kad kredit dan kata laluan."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kawal pembesaran paparan"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kawal tahap zum dan kedudukan paparan."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Lakukan gerak isyarat"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Boleh ketik, leret, cubit dan laksanakan gerak isyarat lain."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"lumpuhkan atau ubah suai bar status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Membenarkan apl melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"jadi bar status"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 3ef7e6c..28a4d0f 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"အရေးကြီးသော ကိုယ်ရေးအချက်အလက်များဖြစ်တဲ့ ခရက်ဒစ်ကဒ်နံပါတ်များနှင့် စကားဝှက်များ ပါဝင်ပါတယ်."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"မျက်နှာပြင် ချဲ့ခြင်းကို ထိန်းချုပ်ပါ"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"မျက်နှာပြင် ချဲ့ခြင်းနှင့် နေရာချထားခြင်းကို ထိန်းချုပ်ပါ"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"လက်ဟန်များ အသုံးပြုပါ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"တို့ခြင်း၊ ပွတ်ဆွဲခြင်း၊ နှင့် အခြား လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်။"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"အခြေအနေပြဘားအား အလုပ်မလုပ်ခိုင်းရန်သို့မဟုတ် မွမ်းမံရန်"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"appအား အခြေအနေပြ ဘားကို ပိတ်ခွင့် သို့မဟတ် စနစ် အိုင်ကွန်များကို ထည့်ခြင်း ဖယ်ရှားခြင်း ပြုလုပ်ခွင့် ပြုသည်။"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"အခြေအနေပြ ဘားဖြစ်ပါစေ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index cd65d85..7e909e4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Dette omfatter personlige data, som kredittkortnumre og passord."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kontrollér forstørrelse for skjermen"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér zoomenivået og plasseringen for skjermen."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gjøre bevegelser"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, sveipe, klype og gjøre andre bevegelser."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"deaktivere eller endre statusfeltet"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Lar appen deaktivere statusfeltet eller legge til og fjerne systemikoner."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vise appen i statusfeltet"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 301094b..15277a2 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"व्यक्तिगत डेटा जस्तै क्रेडिट कार्ड नम्बरहरू र पासवर्डहरू समावेश गर्दछ।"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"प्रदर्शन आवर्धन नियन्त्रण गर्नुहोस्"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"प्रदर्शनको जुम स्तर र स्थिति नियन्त्रण गर्नुहोस्।"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"इसाराहरू सम्बन्धी कार्य गर्नुहोस्"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ट्याप, स्वाइप गर्न, थिच्न र अन्य इसाराहरू सम्बन्धी कार्य गर्न सकिन्छ"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"स्थिति पट्टिलाई अक्षम वा संशोधित गर्नुहोस्"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"स्थिति पट्टि असक्षम पार्न वा प्रणाली आइकनहरू थप्न र हटाउन अनुप्रयोगलाई अनुमति दिन्छ।"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"वस्तुस्थिति पट्टी हुन दिनुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1407991..b81b46e 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Omvat persoonlijke gegevens zoals creditcardnummers en wachtwoorden."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Schermvergroting bedienen"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Bedien het zoomniveau en de positionering van het scherm."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gebaren uitvoeren"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan tikken, vegen, samenknijpen en andere gebaren uitvoeren."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"statusbalk uitschakelen of wijzigen"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Hiermee kan de app de statusbalk uitschakelen of systeempictogrammen toevoegen en verwijderen."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"de statusbalk zijn"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 39f20f5..192c181 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ਇਸ ਵਿੱਚ ਨਿੱਜੀ ਡਾਟਾ ਸ਼ਾਮਲ ਹੈ ਜਿਵੇਂ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ ਅਤੇ ਪਾਸਵਰਡ।"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ਡਿਸਪਲੇ ਵੱਡਦਰਸ਼ੀ ਨੂੰ ਨਿਯੰਤ੍ਰਿਤ ਕਰੋ"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ਡਿਸਪਲੇ ਦੇ ਜ਼ੂਮ ਪੱਧਰ ਅਤੇ ਸਥਿਤੀ ਨੂੰ ਨਿਯੰਤ੍ਰਿਤ ਕਰੋ।"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ਸੰਕੇਤ ਕਰਦੀ ਹੈ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ਟੈਪ ਕਰ ਸਕਦੀ ਹੈ, ਸਵਾਈਪ ਕਰ ਸਕਦੀ ਹੈ, ਪਿੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਹੋਰ ਸੰਕੇਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ਸਥਿਤੀ ਬਾਰ ਅਸਮਰੱਥ ਬਣਾਓ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਜਾਂ ਸਿਸਟਮ ਆਈਕਨਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f3e50b5..38437fa 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Obejmuje informacje osobiste, takie jak numery kart kredytowych i hasła."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Regulowanie powiększenia ekranu"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Regulowanie poziomu i obszaru powiększenia ekranu."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Obsługa gestów"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Obsługuje kliknięcia, przesunięcia, ściągnięcia palców i inne gesty."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"wyłączanie lub zmienianie paska stanu"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Pozwala aplikacji na wyłączanie paska stanu oraz dodawanie i usuwanie ikon systemowych."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"działanie jako pasek stanu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 89bbbe8..91821a4 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclui dados pessoais, como números de cartão de crédito e senhas."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlar ampliação da tela"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o posicionamento e nível de zoom da tela."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fazer gestos"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ser a barra de status"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index f559dbb..f37d3a6 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclui dados pessoais, como números de cartões de crédito e palavras-passe."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlar a ampliação do ecrã"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o nível de zoom e o posicionamento do ecrã."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Realizar gestos"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"É possível tocar, deslizar rapidamente, juntar os dedos e realizar outros gestos"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar barra de estado"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite à aplicação desativar a barra de estado ou adicionar e remover ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ser apresentada na barra de estado"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 89bbbe8..91821a4 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inclui dados pessoais, como números de cartão de crédito e senhas."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlar ampliação da tela"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlar o posicionamento e nível de zoom da tela."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Fazer gestos"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Toque, deslize, faça gestos de pinça e faça outros gestos."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"desativar ou modificar a barra de status"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite que o app desative a barra de status ou adicione e remova ícones do sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"ser a barra de status"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 4086e69..b235b7a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -257,6 +257,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Include date personale, cum ar fi numere ale cardurilor de credit sau parole."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Controlați mărirea pe afișaj"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Controlați nivelul de zoom și poziționarea afișajului."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Folosiți gesturi"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Se poate atinge, glisa, ciupi și se pot folosi alte gesturi."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"dezactivare sau modificare bare de stare"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Permite aplicației să dezactiveze bara de stare sau să adauge și să elimine pictograme de sistem."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"să fie bara de stare"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ee39b83..0c5fb09b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"В том числе личные данные, например номера кредитных карт и пароли."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Управлять масштабом изображения"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управлять позиционированием и размером изображения на экране."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Жесты"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Может выполнять жесты нажатия, пролистывания, масштабирования и т. д."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Отключение/изменение строки состояния"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"Замена строки состояния"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 5364c98..17f0f97 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ණයවරපත් අංක සහ මුරපද වැනි පුද්ගලික දත්ත ඇතුළත් වේ."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"සංදර්ශන විශාලන මට්ටම පාලනය කිරීම"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"සංදර්ශනයේ විශාලන මට්ටම සහ පිහිටීම පාලනය කිරීම."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"අභින සිදු කරන්න"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"තට්ටු කිරීමට, ස්වයිප් කිරීමට, පින්ච් කිරීමට, සහ වෙනත් අභින සිදු කිරීමට හැකිය."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"තත්ව තීරුව අබල කරන්න හෝ වෙනස් කරන්න"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"තත්ව තීරුව අක්රිය කිරීමට හෝ පද්ධති නිරූපක එකතු හෝ ඉවත් කිරීමට යෙදුමට අවසර දේ."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"තත්ත්ව තීරුව බවට පත්වීම"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 90ccd54..d9c79f2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Sledovanie zahŕňa osobné údaje ako sú čísla kreditných kariet a heslá."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ovládanie priblíženia obrazovky"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ovládajte úroveň priblíženia/oddialenia obrazovky a umiestnenie"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gestá"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Je možné použiť klepnutie, prejdenie, stiahnutie prstami a ďalšie gestá."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"zakázanie alebo zmeny stavového riadka"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Umožňuje aplikácii vypnúť stavový riadok alebo pridať a odstrániť systémové ikony."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"vydávanie sa za stavový riadok"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 4e9b1c5..8e293e1 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Vključuje osebne podatke, kot so številke kreditnih kartic in gesla."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Nadziranje povečave prikaza"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Nadziranje stopnje povečave in položaja prikaza."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Izvajanje potez"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Mogoče je izvajanje dotikov, vlečenja, vlečenja prstov skupaj in drugih potez."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"onemogočanje ali spreminjanje vrstice stanja"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Aplikacijam omogoča onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikon sistema."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"postane vrstica stanja"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index be9c709..a24e82f 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Përfshi të dhënat personale si numrat e kartave të kreditit si dhe fjalëkalimet."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kontrollo zmadhimin e ekranit"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollo nivelin dhe pozicionimin e zmadhimit të ekranit."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Kryen gjeste"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Mund të trokasë, rrëshqasë, bashkojë gishtat dhe kryejë gjeste të tjera."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"çaktivizo ose modifiko shiritin e statusit"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Lejon aplikacionin të çaktivizojë shiritin e statusit dhe të heqë ikonat e sistemit."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"të bëhet shiriti i statusit"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index a3618ab..c706264 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -257,6 +257,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Обухвата личне податке као што су бројеви кредитних картица и лозинке."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Управљај увећањем приказа"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Управља нивоом зумирања приказа и одређивањем положаја."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Обављање покрета"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Може да додирује, листа, скупља приказ и обавља друге покрете."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"онемогућавање или измена статусне траке"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дозвољава апликацији да онемогући статусну траку или да додаје и уклања системске иконе."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"функционисање као статусна трака"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index b07dc28..ecc6d4e 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Omfattar personuppgifter som kreditkortsnummer och lösenord."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Styr skärmförstoringen"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Styr skärmens zoomnivå och positionering."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Göra rörelser"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trycka, svepa, nypa och göra andra rörelser."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"inaktivera eller ändra statusfält"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Tillåter att appen inaktiverar statusfältet eller lägger till och tar bort systemikoner."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"visas i statusfältet"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index cf0063c..d1e6d97 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Inajumuisha data binafsi kama vile nambari za kadi ya mkopo na manenosiri."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Dhibiti ukuzaji wa onyesho"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Dhibiti kiwango cha kukuza na nafasi cha onyesho."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Tekeleza ishara"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Unaweza kugonga, kutelezesha kidole, kubana na kutekeleza ishara zingine."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"zima au rekebisha mwambaa hali"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa ikoni za mfumo."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"kuwa sehemu ya arifa"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index ecefb77..eacc9a9 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"கிரெடிட் கார்டு எண்கள் மற்றும் கடவுச்சொற்கள் போன்ற தனிப்பட்ட தகவலும் உள்ளடங்கும்."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"திரையின் உருப்பெருக்கத்தைக் கட்டுப்படுத்துதல்"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"திரையின் ஜூம் அளவையும் நிலையையும் கட்டுப்படுத்தலாம்."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"சைகைகளைச் செயல்படுத்துதல்"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"தட்டலாம், ஸ்வைப் செய்யலாம், பின்ச் செய்யலாம் மற்றும் பிற சைகைகளைச் செயல்படுத்தலாம்."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"நிலைப் பட்டியை முடக்குதல் அல்லது மாற்றுதல்"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"நிலைப் பட்டியை முடக்க அல்லது முறைமையில் ஐகான்களைச் சேர்க்க மற்றும் அகற்ற பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"நிலைப் பட்டியில் இருக்கும்"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index b1bccd2..0440134 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"క్రెడిట్ కార్డు నంబర్లు మరియు పాస్వర్డ్ల వంటి వ్యక్తిగత డేటాను కలిగి ఉంటుంది."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"డిస్ప్లే మాగ్నిఫికేషన్ను నియంత్రించండి"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"డిస్ప్లే జూమ్ స్థాయి మరియు స్థానాన్ని నియంత్రిస్తుంది."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"సంజ్ఞలను చేయడం"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"నొక్కగలరు, స్వైప్ చేయగలరు, స్క్రీన్పై రెండు వేళ్లను ఉంచి ఆ వేళ్లను దగ్గరకు లేదా దూరానికి లాగగలరు మరియు ఇతర సంజ్ఞలను చేయగలరు."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"స్థితి బార్ను నిలిపివేయడం లేదా సవరించడం"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"స్థితి బార్ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"స్థితి పట్టీగా ఉండటం"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 0b8e60d..5d27943 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"รวมถึงข้อมูลส่วนบุคคล เช่น หมายเลขบัตรเครดิตและรหัสผ่าน"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ควบคุมการขยายการแสดงผล"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ควบคุมระดับการซูมและการวางตำแหน่งของการแสดงผล"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ทำท่าทางสัมผัส"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"สามารถแตะ เลื่อน บีบ และทำท่าทางสัมผัสอื่นๆ"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"อนุญาตให้แอปพลิเคชันปิดใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"เป็นแถบสถานะ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 02a3587..479efdf 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"May kasamang personal na data tulad ng mga numero ng credit card at password."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kontrolin ang pag-magnify ng display"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrolin ang antas ng pag-zoom at pagpoposisyon ng display."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Magsagawa ng mga galaw"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"May kakayahang mag-tap, mag-swipe, mag-pinch at magsagawa ng iba pang mga galaw."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"huwag paganahin o baguhin ang status bar"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Pinapayagan ang app na huwag paganahin ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"maging status bar"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 283bcebb..b0c6d5a 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Kredi kartı ve şifre gibi kişisel bilgiler içerir."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ekran büyütecini kontrol et"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekranın yakınlaştırma seviyesini ve konumunu kontrol edin."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Haraketleri yapma"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Hafifçe dokunabilir, hızlıca kaydırabilir, sıkıştırabilir ve diğer hareketleri yapabilirsiniz."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"durum çubuğunu devre dışı bırak veya değiştir"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Uygulamaya, durum çubuğunu devre dışı bırakma ve sistem simgelerini ekleyip kaldırma izni verir."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"durum çubuğunda olma"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index fce4cc3..af1354a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -258,6 +258,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Включає особисті дані, як-от номери кредитних карток і паролі."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Контролювати збільшення екрана"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Контролювати масштаб і розташування екрана."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Виконання жестів"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Можна торкатися, проводити пальцем, стискати пальці та виконувати інші жести."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"вимикати чи змін. рядок стану"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Дозволяє програмі вимикати рядок стану чи додавати та видаляти піктограми системи."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"відображатися як рядок стану"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 519f42b..82bf7ab 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"اس میں ذاتی ڈیٹا جیسے کریڈٹ کارڈ نمبرز اور پاس ورڈز شامل ہیں۔"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ڈسپلے بڑا کرنے کے عمل کو کنٹرول کریں"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ڈسپلے کے زوم کی سطح اور پوزیشن کو کنٹرول کریں۔"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"اشارے انجام دیں"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"تھپتھپانا، سوائپ کرنا، چٹکی بھرنا اور دیگر اشارے انجام دے سکتی ہے"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"اسٹیٹس بار کو غیر فعال یا اس میں ترمیم کریں"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"ایپ کو اسٹیٹس بار غیر فعال کرنے یا سسٹم آئیکنز شامل کرنے اور ہٹانے کی اجازت دیتا ہے۔"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"بطور اسٹیٹس بار کام لیں"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index e90d921..c4be0b9 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Bunga kredit karta raqamlari va parollar kabi shaxsiy ma’lumotlar kiradi."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Ekranni kattalashtirishni boshqarish"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Ekranni kattalashtirish darajasi va joylashuvini boshqaradi."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Imo-ishoralar bilan boshqarish"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Bosish, surish; jipslashtirish va boshqa imo-ishoralarni amalga oshirish mumkin."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"holat panelini o‘zgartirish yoki o‘chirish"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ilova holat panelini o‘chirib qo‘yishi hamda tizim ikonkalarini qo‘shishi yoki olib tashlashi mumkin."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"holat qatorida ko‘rinishi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 31e090b..69b0b99 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Bao gồm dữ liệu cá nhân chẳng hạn như số thẻ tín dụng và mật khẩu."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Kiểm soát thu phóng màn hình"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kiểm soát vị trí và mức thu phóng của màn hình."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Thực hiện cử chỉ"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Có thể nhấn, vuốt, chụm và thực hiện các cử chỉ khác."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hóa hoặc sửa đổi thanh trạng thái"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Cho phép ứng dụng vô hiệu hóa thanh trạng thái hoặc thêm và xóa biểu tượng hệ thống."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"trở thành thanh trạng thái"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c5cd59a..4c7bfd3 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"包含个人数据,例如信用卡号和密码。"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"控制显示内容放大功能"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控制显示内容的缩放级别和位置。"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"执行手势"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可执行点按、滑动、双指张合等手势。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改状态栏"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"允许应用停用状态栏或者增删系统图标。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"用作状态栏"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 36ba2ad6..d6cacb7 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"包括個人資料,如信用卡號碼和密碼。"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"控制顯示屏的放大功能"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控制顯示屏的縮放程度和位置。"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"執行手勢"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可以輕按、快速滑動和兩指縮放,並執行其他手勢。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"停用或修改狀態列"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"成為狀態列"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 72ea523..a47f73d 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"包括個人資料,如信用卡號碼和密碼。"</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"控管顯示畫面放大功能"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"控管顯示畫面的縮放等級和位置。"</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"使用手勢"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"可使用輕按、滑動和雙指撥動等手勢。"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"停用或變更狀態列"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"允許應用程式停用狀態列,並可新增或移除系統圖示。"</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"以狀態列顯示"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index bee7eea..b34594f 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -256,6 +256,8 @@
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Kufaka phakathi idatha yomuntu siqu efana nezinombolo zekhadi lesikweletu namaphasiwedi."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Lawula ukulungiswa kwesibonisi"</string>
<string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Lawula ileveli yokusondeza yesibonisi nendawo."</string>
+ <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Yenza ukuthinta"</string>
+ <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Ingathepha, iswayiphe, incinze, futhi yenze okunye ukuthintwa."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"khubaza noma guqula ibha yomumo"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ivumela uhlelo lokusebenza ukuthi yenze umudwa ochaza ngesimo ukuthi ungasebenzi noma ukufaka noma ukukhipha izithonjana zohlelo."</string>
<string name="permlab_statusBarService" msgid="4826835508226139688">"yiba yibha yesimo"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6d505a5..e0f9eca 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3316,7 +3316,14 @@
</p>
-->
<attr name="canControlMagnification" format="boolean" />
- <!-- Short description of the accessibility serivce purpose or behavior.-->
+ <!-- Attribute whether the accessibility service wants to be able to perform gestures.
+ <p>
+ Required to allow setting the {@link android.accessibilityservice
+ #AccessibilityServiceInfo#FLAG_CAN_PERFORM_GESTURES} flag.
+ </p>
+ -->
+ <attr name="canPerformGestures" format="boolean" />
+ <!-- Short description of the accessibility service purpose or behavior.-->
<attr name="description" />
</declare-styleable>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 58a77e8..21e92ba 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1748,6 +1748,10 @@
<attr name="isolatedProcess" format="boolean" />
<attr name="singleUser" />
<attr name="encryptionAware" />
+ <!-- @hide If the service is an {@link #isolatedProcess} service, this permits a client to
+ bind to the service as if it were running it its own package. The service must also be
+ {@link #exported} if this flag is set. -->
+ <attr name="externalService" format="boolean" />
</declare-styleable>
<!-- The <code>receiver</code> tag declares an
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ebb1b37..c883b1f8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2688,6 +2688,8 @@
<public type="attr" name="tickMark" />
<public type="attr" name="tickMarkTint" />
<public type="attr" name="tickMarkTintMode" />
+ <public type="attr" name="canPerformGestures" />
+ <public type="attr" name="externalService" />
<public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
<public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index be9ba62..997371e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -652,6 +652,12 @@
<string name="capability_desc_canControlMagnification">Control the display\'s zoom level and
positioning.</string>
+ <!-- Title for the capability of an accessibility service to perform gestures. -->
+ <string name="capability_title_canPerformGestures">Perform gestures</string>
+ <!-- Description for the capability of an accessibility service to perform gestures. -->
+ <string name="capability_desc_canPerformGestures">Can tap, swipe, pinch, and perform other
+ gestures.</string>
+
<!-- Permissions -->
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a4654e8..706dd20 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -561,6 +561,8 @@
<java-symbol type="string" name="capability_title_canRetrieveWindowContent" />
<java-symbol type="string" name="capability_desc_canControlMagnification" />
<java-symbol type="string" name="capability_title_canControlMagnification" />
+ <java-symbol type="string" name="capability_desc_canPerformGestures" />
+ <java-symbol type="string" name="capability_title_canPerformGestures" />
<java-symbol type="string" name="cfTemplateForwarded" />
<java-symbol type="string" name="cfTemplateForwardedTime" />
<java-symbol type="string" name="cfTemplateNotForwarded" />
diff --git a/core/res/res/xml/config_webview_packages.xml b/core/res/res/xml/config_webview_packages.xml
index fd443c1..f062b59 100644
--- a/core/res/res/xml/config_webview_packages.xml
+++ b/core/res/res/xml/config_webview_packages.xml
@@ -16,6 +16,6 @@
<webviewproviders>
<!-- The default WebView implementation -->
- <webviewprovider description="Android WebView" packageName="com.android.webview">
+ <webviewprovider description="Android WebView" packageName="com.android.webview" availableByDefault="true">
</webviewprovider>
</webviewproviders>
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index 6bd8f6e..a391e1f 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -75,6 +75,7 @@
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<!-- This permission is added for API call setAirplaneMode() in ConnectivityManager -->
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/core/tests/coretests/src/android/util/LocaleListTest.java b/core/tests/coretests/src/android/util/LocaleListTest.java
new file mode 100644
index 0000000..de1382d
--- /dev/null
+++ b/core/tests/coretests/src/android/util/LocaleListTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.util;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.LocaleList;
+
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+public class LocaleListTest extends TestCase {
+ @SmallTest
+ public void testConstructor() throws Exception {
+ LocaleList ll;
+ ll = new LocaleList(Locale.forLanguageTag("fr"), null);
+ assertEquals("fr", ll.toLanguageTags());
+
+ ll = new LocaleList(Locale.forLanguageTag("fr"), LocaleList.getEmptyLocaleList());
+ assertEquals("fr", ll.toLanguageTags());
+
+ ll = new LocaleList(Locale.forLanguageTag("fr"), LocaleList.forLanguageTags("fr"));
+ assertEquals("fr", ll.toLanguageTags());
+
+ ll = new LocaleList(Locale.forLanguageTag("fr"), LocaleList.forLanguageTags("de"));
+ assertEquals("fr,de", ll.toLanguageTags());
+
+ ll = new LocaleList(Locale.forLanguageTag("fr"), LocaleList.forLanguageTags("de,ja"));
+ assertEquals("fr,de,ja", ll.toLanguageTags());
+
+ ll = new LocaleList(Locale.forLanguageTag("fr"), LocaleList.forLanguageTags("de,fr,ja"));
+ assertEquals("fr,de,ja", ll.toLanguageTags());
+
+ ll = new LocaleList(Locale.forLanguageTag("fr"), LocaleList.forLanguageTags("de,fr"));
+ assertEquals("fr,de", ll.toLanguageTags());
+
+ ll = new LocaleList(Locale.forLanguageTag("fr"), LocaleList.forLanguageTags("fr,de"));
+ assertEquals("fr,de", ll.toLanguageTags());
+ }
+
+ @SmallTest
+ public void testConstructor_nullThrows() throws Exception {
+ try {
+ final LocaleList ll = new LocaleList(null, LocaleList.getEmptyLocaleList());
+ fail("Constructing with locale and locale list should throw with a null locale.");
+ } catch (Throwable e) {
+ assertEquals(NullPointerException.class, e.getClass());
+ }
+ }
+
+ @SmallTest
+ public void testGetDefault_localeSetDefaultCalledButNoChangeNecessary() throws Exception {
+ final Locale originalLocale = Locale.getDefault();
+ final LocaleList originalLocaleList = LocaleList.getDefault();
+ final int originalLocaleIndex = originalLocaleList.indexOf(originalLocale);
+
+ // This simulates a situation potentially set by the system processes
+ LocaleList.setDefault(LocaleList.forLanguageTags("ae,en,ja"), 1 /* en */);
+
+ // check our assumptions about input
+ assertEquals("en", Locale.getDefault().toLanguageTag());
+ final LocaleList firstResult = LocaleList.getDefault();
+ assertEquals("ae,en,ja", LocaleList.getDefault().toLanguageTags());
+
+ Locale.setDefault(Locale.forLanguageTag("ae"));
+ assertSame(firstResult, LocaleList.getDefault());
+
+ // restore the original values
+ LocaleList.setDefault(originalLocaleList, originalLocaleIndex);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
index 48590c1..1966313 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
@@ -22,6 +22,7 @@
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -32,6 +33,8 @@
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
+import java.util.List;
+
/**
* Tests {@link PhoneWindow}'s {@link ActionMode} related methods.
*/
@@ -288,6 +291,9 @@
@Override
public void onActionModeFinished(ActionMode mode) {}
+
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {}
}
private static final class MockActionModeCallback implements ActionMode.Callback {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 651b453..e2150c0 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -82,8 +82,13 @@
*/
public static final int PADDING_MODE_STACK = 1;
- /** Value used for undefined start and end insets. */
- private static final int UNDEFINED_INSET = Integer.MIN_VALUE;
+ /**
+ * Value used for undefined start and end insets.
+ *
+ * @see #getLayerInsetStart(int)
+ * @see #getLayerInsetEnd(int)
+ */
+ public static final int UNDEFINED_INSET = Integer.MIN_VALUE;
LayerState mLayerState;
@@ -867,7 +872,8 @@
/**
* @param index the index of the layer
- * @return number of pixels to inset from the start bound
+ * @return the number of pixels to inset from the start bound, or
+ * {@link #UNDEFINED_INSET} if not specified
* @attr ref android.R.styleable#LayerDrawableItem_start
*/
public int getLayerInsetStart(int index) {
@@ -877,7 +883,8 @@
/**
* @param index the index of the layer to adjust
- * @param e number of pixels to inset from the end bound
+ * @param e number of pixels to inset from the end bound, or
+ * {@link #UNDEFINED_INSET} if not specified
* @attr ref android.R.styleable#LayerDrawableItem_end
*/
public void setLayerInsetEnd(int index, int e) {
@@ -977,34 +984,33 @@
computeStackedPadding(padding);
}
+ final int paddingT = layerState.mPaddingTop;
+ final int paddingB = layerState.mPaddingBottom;
+
+ // Resolve padding for RTL. Relative padding overrides absolute
+ // padding.
+ final boolean isLayoutRtl = getLayoutDirection() == LayoutDirection.RTL;
+ final int paddingRtlL = isLayoutRtl ? layerState.mPaddingEnd : layerState.mPaddingStart;
+ final int paddingRtlR = isLayoutRtl ? layerState.mPaddingStart : layerState.mPaddingEnd;
+ final int paddingL = paddingRtlL >= 0 ? paddingRtlL : layerState.mPaddingLeft;
+ final int paddingR = paddingRtlR >= 0 ? paddingRtlR : layerState.mPaddingRight;
+
// If padding was explicitly specified (e.g. not -1) then override the
// computed padding in that dimension.
- if (layerState.mPaddingTop >= 0) {
- padding.top = layerState.mPaddingTop;
+ if (paddingL >= 0) {
+ padding.left = paddingL;
}
- if (layerState.mPaddingBottom >= 0) {
- padding.bottom = layerState.mPaddingBottom;
+ if (paddingT >= 0) {
+ padding.top = paddingT;
}
- final int paddingRtlLeft;
- final int paddingRtlRight;
- if (getLayoutDirection() == LayoutDirection.RTL) {
- paddingRtlLeft = layerState.mPaddingEnd;
- paddingRtlRight = layerState.mPaddingStart;
- } else {
- paddingRtlLeft = layerState.mPaddingStart;
- paddingRtlRight = layerState.mPaddingEnd;
+ if (paddingR >= 0) {
+ padding.right = paddingR;
}
- final int paddingLeft = paddingRtlLeft >= 0 ? paddingRtlLeft : layerState.mPaddingLeft;
- if (paddingLeft >= 0) {
- padding.left = paddingLeft;
- }
-
- final int paddingRight = paddingRtlRight >= 0 ? paddingRtlRight : layerState.mPaddingRight;
- if (paddingRight >= 0) {
- padding.right = paddingRight;
+ if (paddingB >= 0) {
+ padding.bottom = paddingB;
}
return padding.left != 0 || padding.top != 0 || padding.right != 0 || padding.bottom != 0;
@@ -1471,58 +1477,59 @@
}
private void updateLayerBounds(Rect bounds) {
- int padL = 0;
- int padT = 0;
- int padR = 0;
- int padB = 0;
+ int paddingL = 0;
+ int paddingT = 0;
+ int paddingR = 0;
+ int paddingB = 0;
final Rect outRect = mTmpOutRect;
final int layoutDirection = getLayoutDirection();
- final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST;
+ final boolean isLayoutRtl = layoutDirection == LayoutDirection.RTL;
+ final boolean isPaddingNested = mLayerState.mPaddingMode == PADDING_MODE_NEST;
final ChildDrawable[] array = mLayerState.mChildren;
- final int N = mLayerState.mNum;
- for (int i = 0; i < N; i++) {
+
+ for (int i = 0, count = mLayerState.mNum; i < count; i++) {
final ChildDrawable r = array[i];
final Drawable d = r.mDrawable;
if (d == null) {
continue;
}
- final Rect container = mTmpContainer;
- container.set(d.getBounds());
+ final int insetT = r.mInsetT;
+ final int insetB = r.mInsetB;
- // Take the resolved layout direction into account. If start / end
- // padding are defined, they will be resolved (hence overriding) to
- // left / right or right / left depending on the resolved layout
- // direction. If start / end padding are not defined, use the
- // left / right ones.
- final int insetL, insetR;
- if (layoutDirection == LayoutDirection.RTL) {
- insetL = r.mInsetE == UNDEFINED_INSET ? r.mInsetL : r.mInsetE;
- insetR = r.mInsetS == UNDEFINED_INSET ? r.mInsetR : r.mInsetS;
- } else {
- insetL = r.mInsetS == UNDEFINED_INSET ? r.mInsetL : r.mInsetS;
- insetR = r.mInsetE == UNDEFINED_INSET ? r.mInsetR : r.mInsetE;
- }
+ // Resolve insets for RTL. Relative insets override absolute
+ // insets.
+ final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS;
+ final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE;
+ final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL;
+ final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR;
// Establish containing region based on aggregate padding and
// requested insets for the current layer.
- container.set(bounds.left + insetL + padL, bounds.top + r.mInsetT + padT,
- bounds.right - insetR - padR, bounds.bottom - r.mInsetB - padB);
+ final Rect container = mTmpContainer;
+ container.set(bounds.left + insetL + paddingL, bounds.top + insetT + paddingT,
+ bounds.right - insetR - paddingR, bounds.bottom - insetB - paddingB);
- // Apply resolved gravity to drawable based on resolved size.
- final int gravity = resolveGravity(r.mGravity, r.mWidth, r.mHeight,
- d.getIntrinsicWidth(), d.getIntrinsicHeight());
- final int w = r.mWidth < 0 ? d.getIntrinsicWidth() : r.mWidth;
- final int h = r.mHeight < 0 ? d.getIntrinsicHeight() : r.mHeight;
- Gravity.apply(gravity, w, h, container, outRect, layoutDirection);
+ // Compute a reasonable default gravity based on the intrinsic and
+ // explicit dimensions, if specified.
+ final int intrinsicW = d.getIntrinsicWidth();
+ final int intrinsicH = d.getIntrinsicHeight();
+ final int layerW = r.mWidth;
+ final int layerH = r.mHeight;
+ final int gravity = resolveGravity(r.mGravity, layerW, layerH, intrinsicW, intrinsicH);
+
+ // Explicit dimensions override intrinsic dimensions.
+ final int resolvedW = layerW < 0 ? intrinsicW : layerW;
+ final int resolvedH = layerH < 0 ? intrinsicH : layerH;
+ Gravity.apply(gravity, resolvedW, resolvedH, container, outRect, layoutDirection);
d.setBounds(outRect);
- if (nest) {
- padL += mPaddingL[i];
- padR += mPaddingR[i];
- padT += mPaddingT[i];
- padB += mPaddingB[i];
+ if (isPaddingNested) {
+ paddingL += mPaddingL[i];
+ paddingR += mPaddingR[i];
+ paddingT += mPaddingT[i];
+ paddingB += mPaddingB[i];
}
}
}
@@ -1578,6 +1585,7 @@
int padR = 0;
final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST;
+ final boolean isLayoutRtl = getLayoutDirection() == LayoutDirection.RTL;
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
@@ -1591,15 +1599,10 @@
// left / right or right / left depending on the resolved layout
// direction. If start / end padding are not defined, use the
// left / right ones.
- final int insetL, insetR;
- final int layoutDirection = getLayoutDirection();
- if (layoutDirection == LayoutDirection.RTL) {
- insetL = r.mInsetE == UNDEFINED_INSET ? r.mInsetL : r.mInsetE;
- insetR = r.mInsetS == UNDEFINED_INSET ? r.mInsetR : r.mInsetS;
- } else {
- insetL = r.mInsetS == UNDEFINED_INSET ? r.mInsetL : r.mInsetS;
- insetR = r.mInsetE == UNDEFINED_INSET ? r.mInsetR : r.mInsetE;
- }
+ final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS;
+ final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE;
+ final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL;
+ final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR;
// Don't apply padding and insets for children that don't have
// an intrinsic dimension.
@@ -1659,8 +1662,8 @@
if (r.mDrawable != null) {
final Rect rect = mTmpRect;
r.mDrawable.getPadding(rect);
- if (rect.left != mPaddingL[i] || rect.top != mPaddingT[i] ||
- rect.right != mPaddingR[i] || rect.bottom != mPaddingB[i]) {
+ if (rect.left != mPaddingL[i] || rect.top != mPaddingT[i]
+ || rect.right != mPaddingR[i] || rect.bottom != mPaddingB[i]) {
mPaddingL[i] = rect.left;
mPaddingT[i] = rect.top;
mPaddingR[i] = rect.right;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 11056d4..bbfc022 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,7 +2,7 @@
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-HWUI_NEW_OPS := false
+HWUI_NEW_OPS := true
hwui_src_files := \
font/CacheTexture.cpp \
@@ -109,7 +109,8 @@
BakedOpDispatcher.cpp \
BakedOpRenderer.cpp \
BakedOpState.cpp \
- OpReorderer.cpp \
+ FrameBuilder.cpp \
+ LayerBuilder.cpp \
RecordingCanvas.cpp
hwui_cflags += -DHWUI_NEW_OPS
@@ -236,8 +237,8 @@
ifeq (true, $(HWUI_NEW_OPS))
LOCAL_SRC_FILES += \
tests/unit/BakedOpStateTests.cpp \
- tests/unit/RecordingCanvasTests.cpp \
- tests/unit/OpReordererTests.cpp
+ tests/unit/FrameBuilderTests.cpp \
+ tests/unit/RecordingCanvasTests.cpp
endif
include $(BUILD_NATIVE_TEST)
@@ -296,9 +297,9 @@
tests/microbench/PathParserBench.cpp \
tests/microbench/ShadowBench.cpp
-ifeq (true, $(HWUI_NEW_OPS))
- LOCAL_SRC_FILES += \
- tests/microbench/OpReordererBench.cpp
-endif
+# ifeq (true, $(HWUI_NEW_OPS))
+# LOCAL_SRC_FILES += \
+# tests/microbench/FrameBuilderBench.cpp
+# endif
include $(BUILD_EXECUTABLE)
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index f58ca31..5b34f6b 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -338,8 +338,8 @@
static void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state,
PathTexture& texture, const RecordedOp& op) {
Rect dest(texture.width, texture.height);
- dest.translate(texture.left + op.unmappedBounds.left - texture.offset,
- texture.top + op.unmappedBounds.top - texture.offset);
+ dest.translate(texture.left - texture.offset,
+ texture.top - texture.offset);
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
@@ -545,19 +545,19 @@
op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.patch);
Texture* texture = entry ? entry->texture : renderer.caches().textureCache.get(op.bitmap);
- if (!texture) return;
- const AutoTexture autoCleanup(texture);
- Glop glop;
- GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
- .setRoundRectClipState(state.roundRectClipState)
- .setMeshPatchQuads(*mesh)
- .setMeshTexturedUnitQuad(texture->uvMapper)
- .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
- .setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
- Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
- .build();
- renderer.renderGlop(state, glop);
+ if (CC_LIKELY(texture)) {
+ const AutoTexture autoCleanup(texture);
+ Glop glop;
+ GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
+ .setRoundRectClipState(state.roundRectClipState)
+ .setMeshPatchQuads(*mesh)
+ .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
+ .setTransform(state.computedState.transform, TransformFlags::None)
+ .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
+ Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
+ .build();
+ renderer.renderGlop(state, glop);
+ }
}
void BakedOpDispatcher::onPathOp(BakedOpRenderer& renderer, const PathOp& op, const BakedOpState& state) {
@@ -736,6 +736,7 @@
void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
OffscreenBuffer* buffer = *op.layerHandle;
+ // Note that we don't use op->paint here - it's never set on a LayerOp
float layerAlpha = op.alpha * state.alpha;
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
@@ -754,11 +755,35 @@
}
void BakedOpDispatcher::onCopyToLayerOp(BakedOpRenderer& renderer, const CopyToLayerOp& op, const BakedOpState& state) {
- LOG_ALWAYS_FATAL("TODO!");
+ LOG_ALWAYS_FATAL_IF(*(op.layerHandle) != nullptr, "layer already exists!");
+ *(op.layerHandle) = renderer.copyToLayer(state.computedState.clippedBounds);
+ LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "layer copy failed");
}
void BakedOpDispatcher::onCopyFromLayerOp(BakedOpRenderer& renderer, const CopyFromLayerOp& op, const BakedOpState& state) {
- LOG_ALWAYS_FATAL("TODO!");
+ LOG_ALWAYS_FATAL_IF(*op.layerHandle == nullptr, "no layer to draw underneath!");
+ if (!state.computedState.clippedBounds.isEmpty()) {
+ if (op.paint && op.paint->getAlpha() < 255) {
+ SkPaint layerPaint;
+ layerPaint.setAlpha(op.paint->getAlpha());
+ layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+ layerPaint.setColorFilter(op.paint->getColorFilter());
+ RectOp rectOp(state.computedState.clippedBounds, Matrix4::identity(), nullptr, &layerPaint);
+ BakedOpDispatcher::onRectOp(renderer, rectOp, state);
+ }
+
+ OffscreenBuffer& layer = **(op.layerHandle);
+ auto mode = PaintUtils::getXfermodeDirect(op.paint);
+ Glop glop;
+ GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
+ .setRoundRectClipState(state.roundRectClipState)
+ .setMeshTexturedUvQuad(nullptr, layer.getTextureCoordinates())
+ .setFillLayer(layer.texture, nullptr, 1.0f, mode, Blend::ModeOrderSwap::Swap)
+ .setTransform(state.computedState.transform, TransformFlags::None)
+ .setModelViewMapUnitToRect(state.computedState.clippedBounds)
+ .build();
+ renderer.renderGlop(state, glop);
+ }
}
} // namespace uirenderer
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 4aebe3c..42fb66f 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -79,6 +79,20 @@
mRenderTarget.frameBufferId = 0;
}
+OffscreenBuffer* BakedOpRenderer::copyToLayer(const Rect& area) {
+ OffscreenBuffer* buffer = mRenderState.layerPool().get(mRenderState,
+ area.getWidth(), area.getHeight());
+ if (!area.isEmpty()) {
+ mCaches.textureState().activateTexture(0);
+ mCaches.textureState().bindTexture(buffer->texture.id);
+
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+ area.left, mRenderTarget.viewportHeight - area.bottom,
+ area.getWidth(), area.getHeight());
+ }
+ return buffer;
+}
+
void BakedOpRenderer::startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {
LOG_ALWAYS_FATAL_IF(mRenderTarget.frameBufferId != 0, "primary framebufferId must be 0");
mRenderState.bindFramebuffer(0);
@@ -147,7 +161,7 @@
}
void BakedOpRenderer::clearColorBuffer(const Rect& rect) {
- if (Rect(mRenderTarget.viewportWidth, mRenderTarget.viewportHeight).contains(rect)) {
+ if (rect.contains(Rect(mRenderTarget.viewportWidth, mRenderTarget.viewportHeight))) {
// Full viewport is being cleared - disable scissor
mRenderState.scissor().setEnabled(false);
} else {
@@ -187,6 +201,7 @@
}
void BakedOpRenderer::setupStencilRectList(const ClipBase* clip) {
+ LOG_ALWAYS_FATAL_IF(clip->mode != ClipMode::RectangleList, "can't rectlist clip without rectlist");
auto&& rectList = reinterpret_cast<const ClipRectList*>(clip)->rectList;
int quadCount = rectList.getTransformedRectanglesCount();
std::vector<Vertex> rectangleVertices;
@@ -220,6 +235,7 @@
}
void BakedOpRenderer::setupStencilRegion(const ClipBase* clip) {
+ LOG_ALWAYS_FATAL_IF(clip->mode != ClipMode::Region, "can't region clip without region");
auto&& region = reinterpret_cast<const ClipRegion*>(clip)->region;
std::vector<Vertex> regionVertices;
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 65e8b29..e857f6b 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -19,6 +19,7 @@
#include "BakedOpState.h"
#include "Matrix.h"
+#include "utils/Macros.h"
namespace android {
namespace uirenderer {
@@ -61,9 +62,10 @@
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect);
void endFrame(const Rect& repaintRect);
- OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height);
+ WARN_UNUSED_RESULT OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height);
void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect);
void endLayer();
+ WARN_UNUSED_RESULT OffscreenBuffer* copyToLayer(const Rect& area);
Texture* getTexture(const SkBitmap* bitmap);
const LightInfo& getLightInfo() const { return mLightInfo; }
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index b7c9281..87844f9 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -48,10 +48,10 @@
const Rect& clipRect = clipState->rect;
if (CC_UNLIKELY(clipRect.isEmpty() || !clippedBounds.intersects(clipRect))) {
// Rejected based on either empty clip, or bounds not intersecting with clip
- if (clipState) {
- allocator.rewindIfLastAlloc(clipState);
- clipState = nullptr;
- }
+
+ // Note: we could rewind the clipState object in situations where the clipRect is empty,
+ // but *only* if the caching logic within ClipArea was aware of the rewind.
+ clipState = nullptr;
clippedBounds.setEmpty();
} else {
// Not rejected! compute true clippedBounds and clipSideFlags
@@ -71,13 +71,12 @@
clipState = snapshot.mutateClipArea().serializeClip(allocator);
LOG_ALWAYS_FATAL_IF(!clipState, "clipState required");
clippedBounds = clipState->rect;
- transform.mapRect(clippedBounds);
clipSideFlags = OpClipSideFlags::Full;
}
-ResolvedRenderState::ResolvedRenderState(const Rect& dstRect)
+ResolvedRenderState::ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect)
: transform(Matrix4::identity())
- , clipState(nullptr)
+ , clipState(viewportRect)
, clippedBounds(dstRect)
, clipSideFlags(OpClipSideFlags::None) {}
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index 70b0484..3db28c9 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -58,9 +58,8 @@
// Constructor for unbounded ops without transform/clip (namely shadows)
ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot);
- // Constructor for primitive ops without clip or transform
- // NOTE: these ops can't be queried for RT clip / local clip
- ResolvedRenderState(const Rect& dstRect);
+ // Constructor for primitive ops provided clip, and no transform
+ ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect);
Rect computeLocalSpaceClip() const {
Matrix4 inverse;
@@ -71,15 +70,13 @@
return outClip;
}
- // NOTE: Can only be used on clipped/snapshot based ops
const Rect& clipRect() const {
return clipState->rect;
}
- // NOTE: Can only be used on clipped/snapshot based ops
bool requiresClip() const {
return clipSideFlags != OpClipSideFlags::None
- || CC_UNLIKELY(clipState->mode != ClipMode::Rectangle);
+ || CC_UNLIKELY(clipState->mode != ClipMode::Rectangle);
}
// returns the clip if it's needed to draw the operation, otherwise nullptr
@@ -102,6 +99,7 @@
public:
static BakedOpState* tryConstruct(LinearAllocator& allocator,
Snapshot& snapshot, const RecordedOp& recordedOp) {
+ if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
BakedOpState* bakedState = new (allocator) BakedOpState(
allocator, snapshot, recordedOp, false);
if (bakedState->computedState.clippedBounds.isEmpty()) {
@@ -121,6 +119,7 @@
static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator,
Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
+ if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
: true;
@@ -129,6 +128,7 @@
allocator, snapshot, recordedOp, expandForStroke);
if (bakedState->computedState.clippedBounds.isEmpty()) {
// bounds are empty, so op is rejected
+ // NOTE: this won't succeed if a clip was allocated
allocator.rewindIfLastAlloc(bakedState);
return nullptr;
}
@@ -137,15 +137,15 @@
static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator,
Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
- if (snapshot.getRenderTargetClip().isEmpty()) return nullptr;
+ if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
// clip isn't empty, so construct the op
return new (allocator) BakedOpState(allocator, snapshot, shadowOpPtr);
}
static BakedOpState* directConstruct(LinearAllocator& allocator,
- const Rect& dstRect, const RecordedOp& recordedOp) {
- return new (allocator) BakedOpState(dstRect, recordedOp);
+ const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
+ return new (allocator) BakedOpState(clip, dstRect, recordedOp);
}
static void* operator new(size_t size, LinearAllocator& allocator) {
@@ -177,8 +177,8 @@
, projectionPathMask(snapshot.projectionPathMask)
, op(shadowOpPtr) {}
- BakedOpState(const Rect& dstRect, const RecordedOp& recordedOp)
- : computedState(dstRect)
+ BakedOpState(const ClipRect* viewportRect, const Rect& dstRect, const RecordedOp& recordedOp)
+ : computedState(viewportRect, dstRect)
, alpha(1.0f)
, roundRectClipState(nullptr)
, projectionPathMask(nullptr)
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/FrameBuilder.cpp
similarity index 61%
rename from libs/hwui/OpReorderer.cpp
rename to libs/hwui/FrameBuilder.cpp
index 34c3d60..c4c655b 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "OpReorderer.h"
+#include "FrameBuilder.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
@@ -30,375 +30,46 @@
namespace android {
namespace uirenderer {
-class BatchBase {
-
-public:
- BatchBase(batchid_t batchId, BakedOpState* op, bool merging)
- : mBatchId(batchId)
- , mMerging(merging) {
- mBounds = op->computedState.clippedBounds;
- mOps.push_back(op);
- }
-
- bool intersects(const Rect& rect) const {
- if (!rect.intersects(mBounds)) return false;
-
- for (const BakedOpState* op : mOps) {
- if (rect.intersects(op->computedState.clippedBounds)) {
- return true;
- }
- }
- return false;
- }
-
- batchid_t getBatchId() const { return mBatchId; }
- bool isMerging() const { return mMerging; }
-
- const std::vector<BakedOpState*>& getOps() const { return mOps; }
-
- void dump() const {
- ALOGD(" Batch %p, id %d, merging %d, count %d, bounds " RECT_STRING,
- this, mBatchId, mMerging, mOps.size(), RECT_ARGS(mBounds));
- }
-protected:
- batchid_t mBatchId;
- Rect mBounds;
- std::vector<BakedOpState*> mOps;
- bool mMerging;
-};
-
-class OpBatch : public BatchBase {
-public:
- static void* operator new(size_t size, LinearAllocator& allocator) {
- return allocator.alloc(size);
- }
-
- OpBatch(batchid_t batchId, BakedOpState* op)
- : BatchBase(batchId, op, false) {
- }
-
- void batchOp(BakedOpState* op) {
- mBounds.unionWith(op->computedState.clippedBounds);
- mOps.push_back(op);
- }
-};
-
-class MergingOpBatch : public BatchBase {
-public:
- static void* operator new(size_t size, LinearAllocator& allocator) {
- return allocator.alloc(size);
- }
-
- MergingOpBatch(batchid_t batchId, BakedOpState* op)
- : BatchBase(batchId, op, true)
- , mClipSideFlags(op->computedState.clipSideFlags) {
- }
-
- /*
- * Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds
- * and clip side flags. Positive bounds delta means new bounds fit in old.
- */
- static inline bool checkSide(const int currentFlags, const int newFlags, const int side,
- float boundsDelta) {
- bool currentClipExists = currentFlags & side;
- bool newClipExists = newFlags & side;
-
- // if current is clipped, we must be able to fit new bounds in current
- if (boundsDelta > 0 && currentClipExists) return false;
-
- // if new is clipped, we must be able to fit current bounds in new
- if (boundsDelta < 0 && newClipExists) return false;
-
- return true;
- }
-
- static bool paintIsDefault(const SkPaint& paint) {
- return paint.getAlpha() == 255
- && paint.getColorFilter() == nullptr
- && paint.getShader() == nullptr;
- }
-
- static bool paintsAreEquivalent(const SkPaint& a, const SkPaint& b) {
- return a.getAlpha() == b.getAlpha()
- && a.getColorFilter() == b.getColorFilter()
- && a.getShader() == b.getShader();
- }
-
- /*
- * Checks if a (mergeable) op can be merged into this batch
- *
- * If true, the op's multiDraw must be guaranteed to handle both ops simultaneously, so it is
- * important to consider all paint attributes used in the draw calls in deciding both a) if an
- * op tries to merge at all, and b) if the op can merge with another set of ops
- *
- * False positives can lead to information from the paints of subsequent merged operations being
- * dropped, so we make simplifying qualifications on the ops that can merge, per op type.
- */
- bool canMergeWith(BakedOpState* op) const {
- bool isTextBatch = getBatchId() == OpBatchType::Text
- || getBatchId() == OpBatchType::ColorText;
-
- // Overlapping other operations is only allowed for text without shadow. For other ops,
- // multiDraw isn't guaranteed to overdraw correctly
- if (!isTextBatch || PaintUtils::hasTextShadow(op->op->paint)) {
- if (intersects(op->computedState.clippedBounds)) return false;
- }
-
- const BakedOpState* lhs = op;
- const BakedOpState* rhs = mOps[0];
-
- if (!MathUtils::areEqual(lhs->alpha, rhs->alpha)) return false;
-
- // Identical round rect clip state means both ops will clip in the same way, or not at all.
- // As the state objects are const, we can compare their pointers to determine mergeability
- if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
- if (lhs->projectionPathMask != rhs->projectionPathMask) return false;
-
- /* Clipping compatibility check
- *
- * Exploits the fact that if a op or batch is clipped on a side, its bounds will equal its
- * clip for that side.
- */
- const int currentFlags = mClipSideFlags;
- const int newFlags = op->computedState.clipSideFlags;
- if (currentFlags != OpClipSideFlags::None || newFlags != OpClipSideFlags::None) {
- const Rect& opBounds = op->computedState.clippedBounds;
- float boundsDelta = mBounds.left - opBounds.left;
- if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Left, boundsDelta)) return false;
- boundsDelta = mBounds.top - opBounds.top;
- if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Top, boundsDelta)) return false;
-
- // right and bottom delta calculation reversed to account for direction
- boundsDelta = opBounds.right - mBounds.right;
- if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Right, boundsDelta)) return false;
- boundsDelta = opBounds.bottom - mBounds.bottom;
- if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Bottom, boundsDelta)) return false;
- }
-
- const SkPaint* newPaint = op->op->paint;
- const SkPaint* oldPaint = mOps[0]->op->paint;
-
- if (newPaint == oldPaint) {
- // if paints are equal, then modifiers + paint attribs don't need to be compared
- return true;
- } else if (newPaint && !oldPaint) {
- return paintIsDefault(*newPaint);
- } else if (!newPaint && oldPaint) {
- return paintIsDefault(*oldPaint);
- }
- return paintsAreEquivalent(*newPaint, *oldPaint);
- }
-
- void mergeOp(BakedOpState* op) {
- mBounds.unionWith(op->computedState.clippedBounds);
- mOps.push_back(op);
-
- // Because a new op must have passed canMergeWith(), we know it's passed the clipping compat
- // check, and doesn't extend past a side of the clip that's in use by the merged batch.
- // Therefore it's safe to simply always merge flags, and use the bounds as the clip rect.
- mClipSideFlags |= op->computedState.clipSideFlags;
- }
-
- int getClipSideFlags() const { return mClipSideFlags; }
- const Rect& getClipRect() const { return mBounds; }
-
-private:
- int mClipSideFlags;
-};
-
-OpReorderer::LayerReorderer::LayerReorderer(uint32_t width, uint32_t height,
- const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode)
- : width(width)
- , height(height)
- , repaintRect(repaintRect)
- , offscreenBuffer(renderNode ? renderNode->getLayer() : nullptr)
- , beginLayerOp(beginLayerOp)
- , renderNode(renderNode) {}
-
-// iterate back toward target to see if anything drawn since should overlap the new op
-// if no target, merging ops still iterate to find similar batch to insert after
-void OpReorderer::LayerReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds,
- BatchBase** targetBatch, size_t* insertBatchIndex) const {
- for (int i = mBatches.size() - 1; i >= 0; i--) {
- BatchBase* overBatch = mBatches[i];
-
- if (overBatch == *targetBatch) break;
-
- // TODO: also consider shader shared between batch types
- if (batchId == overBatch->getBatchId()) {
- *insertBatchIndex = i + 1;
- if (!*targetBatch) break; // found insert position, quit
- }
-
- if (overBatch->intersects(clippedBounds)) {
- // NOTE: it may be possible to optimize for special cases where two operations
- // of the same batch/paint could swap order, such as with a non-mergeable
- // (clipped) and a mergeable text operation
- *targetBatch = nullptr;
- break;
- }
- }
-}
-
-void OpReorderer::LayerReorderer::deferLayerClear(const Rect& rect) {
- mClearRects.push_back(rect);
-}
-
-void OpReorderer::LayerReorderer::flushLayerClears(LinearAllocator& allocator) {
- if (CC_UNLIKELY(!mClearRects.empty())) {
- const int vertCount = mClearRects.size() * 4;
- // put the verts in the frame allocator, since
- // 1) SimpleRectsOps needs verts, not rects
- // 2) even if mClearRects stored verts, std::vectors will move their contents
- Vertex* const verts = (Vertex*) allocator.alloc(vertCount * sizeof(Vertex));
-
- Vertex* currentVert = verts;
- Rect bounds = mClearRects[0];
- for (auto&& rect : mClearRects) {
- bounds.unionWith(rect);
- Vertex::set(currentVert++, rect.left, rect.top);
- Vertex::set(currentVert++, rect.right, rect.top);
- Vertex::set(currentVert++, rect.left, rect.bottom);
- Vertex::set(currentVert++, rect.right, rect.bottom);
- }
- mClearRects.clear(); // discard rects before drawing so this method isn't reentrant
-
- // One or more unclipped saveLayers have been enqueued, with deferred clears.
- // Flush all of these clears with a single draw
- SkPaint* paint = allocator.create<SkPaint>();
- paint->setXfermodeMode(SkXfermode::kClear_Mode);
- SimpleRectsOp* op = new (allocator) SimpleRectsOp(bounds,
- Matrix4::identity(), nullptr, paint,
- verts, vertCount);
- BakedOpState* bakedState = BakedOpState::directConstruct(allocator, bounds, *op);
-
-
- deferUnmergeableOp(allocator, bakedState, OpBatchType::Vertices);
- }
-}
-
-void OpReorderer::LayerReorderer::deferUnmergeableOp(LinearAllocator& allocator,
- BakedOpState* op, batchid_t batchId) {
- if (batchId != OpBatchType::CopyToLayer) {
- // if first op after one or more unclipped saveLayers, flush the layer clears
- flushLayerClears(allocator);
- }
-
- OpBatch* targetBatch = mBatchLookup[batchId];
-
- size_t insertBatchIndex = mBatches.size();
- if (targetBatch) {
- locateInsertIndex(batchId, op->computedState.clippedBounds,
- (BatchBase**)(&targetBatch), &insertBatchIndex);
- }
-
- if (targetBatch) {
- targetBatch->batchOp(op);
- } else {
- // new non-merging batch
- targetBatch = new (allocator) OpBatch(batchId, op);
- mBatchLookup[batchId] = targetBatch;
- mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
- }
-}
-
-void OpReorderer::LayerReorderer::deferMergeableOp(LinearAllocator& allocator,
- BakedOpState* op, batchid_t batchId, mergeid_t mergeId) {
- if (batchId != OpBatchType::CopyToLayer) {
- // if first op after one or more unclipped saveLayers, flush the layer clears
- flushLayerClears(allocator);
- }
- MergingOpBatch* targetBatch = nullptr;
-
- // Try to merge with any existing batch with same mergeId
- auto getResult = mMergingBatchLookup[batchId].find(mergeId);
- if (getResult != mMergingBatchLookup[batchId].end()) {
- targetBatch = getResult->second;
- if (!targetBatch->canMergeWith(op)) {
- targetBatch = nullptr;
- }
- }
-
- size_t insertBatchIndex = mBatches.size();
- locateInsertIndex(batchId, op->computedState.clippedBounds,
- (BatchBase**)(&targetBatch), &insertBatchIndex);
-
- if (targetBatch) {
- targetBatch->mergeOp(op);
- } else {
- // new merging batch
- targetBatch = new (allocator) MergingOpBatch(batchId, op);
- mMergingBatchLookup[batchId].insert(std::make_pair(mergeId, targetBatch));
-
- mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
- }
-}
-
-void OpReorderer::LayerReorderer::replayBakedOpsImpl(void* arg,
- BakedOpReceiver* unmergedReceivers, MergedOpReceiver* mergedReceivers) const {
- ATRACE_NAME("flush drawing commands");
- for (const BatchBase* batch : mBatches) {
- size_t size = batch->getOps().size();
- if (size > 1 && batch->isMerging()) {
- int opId = batch->getOps()[0]->op->opId;
- const MergingOpBatch* mergingBatch = static_cast<const MergingOpBatch*>(batch);
- MergedBakedOpList data = {
- batch->getOps().data(),
- size,
- mergingBatch->getClipSideFlags(),
- mergingBatch->getClipRect()
- };
- mergedReceivers[opId](arg, data);
- } else {
- for (const BakedOpState* op : batch->getOps()) {
- unmergedReceivers[op->op->opId](arg, *op);
- }
- }
- }
-}
-
-void OpReorderer::LayerReorderer::dump() const {
- ALOGD("LayerReorderer %p, %ux%u buffer %p, blo %p, rn %p",
- this, width, height, offscreenBuffer, beginLayerOp, renderNode);
- for (const BatchBase* batch : mBatches) {
- batch->dump();
- }
-}
-
-OpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
+FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
uint32_t viewportWidth, uint32_t viewportHeight,
const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter)
: mCanvasState(*this) {
ATRACE_NAME("prepare drawing commands");
- mLayerReorderers.reserve(layers.entries().size());
+ mLayerBuilders.reserve(layers.entries().size());
mLayerStack.reserve(layers.entries().size());
// Prepare to defer Fbo0
- mLayerReorderers.emplace_back(viewportWidth, viewportHeight, Rect(clip));
+ auto fbo0 = mAllocator.create<LayerBuilder>(viewportWidth, viewportHeight, Rect(clip));
+ mLayerBuilders.push_back(fbo0);
mLayerStack.push_back(0);
mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
lightCenter);
// Render all layers to be updated, in order. Defer in reverse order, so that they'll be
- // updated in the order they're passed in (mLayerReorderers are issued to Renderer in reverse)
+ // updated in the order they're passed in (mLayerBuilders are issued to Renderer in reverse)
for (int i = layers.entries().size() - 1; i >= 0; i--) {
RenderNode* layerNode = layers.entries()[i].renderNode;
- const Rect& layerDamage = layers.entries()[i].damage;
- layerNode->computeOrdering();
+ // only schedule repaint if node still on layer - possible it may have been
+ // removed during a dropped frame, but layers may still remain scheduled so
+ // as not to lose info on what portion is damaged
+ if (CC_LIKELY(layerNode->getLayer() != nullptr)) {
+ const Rect& layerDamage = layers.entries()[i].damage;
+ layerNode->computeOrdering();
- // map current light center into RenderNode's coordinate space
- Vector3 lightCenter = mCanvasState.currentSnapshot()->getRelativeLightCenter();
- layerNode->getLayer()->inverseTransformInWindow.mapPoint3d(lightCenter);
+ // map current light center into RenderNode's coordinate space
+ Vector3 lightCenter = mCanvasState.currentSnapshot()->getRelativeLightCenter();
+ layerNode->getLayer()->inverseTransformInWindow.mapPoint3d(lightCenter);
- saveForLayer(layerNode->getWidth(), layerNode->getHeight(), 0, 0,
- layerDamage, lightCenter, nullptr, layerNode);
+ saveForLayer(layerNode->getWidth(), layerNode->getHeight(), 0, 0,
+ layerDamage, lightCenter, nullptr, layerNode);
- if (layerNode->getDisplayList()) {
- deferNodeOps(*layerNode);
+ if (layerNode->getDisplayList()) {
+ deferNodeOps(*layerNode);
+ }
+ restoreForLayer();
}
- restoreForLayer();
}
// Defer Fbo0
@@ -412,11 +83,11 @@
}
}
-void OpReorderer::onViewportInitialized() {}
+void FrameBuilder::onViewportInitialized() {}
-void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
+void FrameBuilder::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
-void OpReorderer::deferNodePropsAndOps(RenderNode& node) {
+void FrameBuilder::deferNodePropsAndOps(RenderNode& node) {
const RenderProperties& properties = node.properties();
const Outline& outline = properties.getOutline();
if (properties.getAlpha() <= 0
@@ -548,7 +219,7 @@
}
template <typename V>
-void OpReorderer::defer3dChildren(ChildrenSelectMode mode, const V& zTranslatedNodes) {
+void FrameBuilder::defer3dChildren(ChildrenSelectMode mode, const V& zTranslatedNodes) {
const int size = zTranslatedNodes.size();
if (size == 0
|| (mode == ChildrenSelectMode::Negative&& zTranslatedNodes[0].key > 0.0f)
@@ -598,7 +269,7 @@
}
}
-void OpReorderer::deferShadow(const RenderNodeOp& casterNodeOp) {
+void FrameBuilder::deferShadow(const RenderNodeOp& casterNodeOp) {
auto& node = *casterNodeOp.renderNode;
auto& properties = node.properties();
@@ -654,7 +325,7 @@
}
}
-void OpReorderer::deferProjectedChildren(const RenderNode& renderNode) {
+void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
int count = mCanvasState.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
@@ -687,15 +358,15 @@
}
/**
- * Used to define a list of lambdas referencing private OpReorderer::onXX::defer() methods.
+ * Used to define a list of lambdas referencing private FrameBuilder::onXX::defer() methods.
*
* This allows opIds embedded in the RecordedOps to be used for dispatching to these lambdas.
- * E.g. a BitmapOp op then would be dispatched to OpReorderer::onBitmapOp(const BitmapOp&)
+ * E.g. a BitmapOp op then would be dispatched to FrameBuilder::onBitmapOp(const BitmapOp&)
*/
#define OP_RECEIVER(Type) \
- [](OpReorderer& reorderer, const RecordedOp& op) { reorderer.defer##Type(static_cast<const Type&>(op)); },
-void OpReorderer::deferNodeOps(const RenderNode& renderNode) {
- typedef void (*OpDispatcher) (OpReorderer& reorderer, const RecordedOp& op);
+ [](FrameBuilder& frameBuilder, const RecordedOp& op) { frameBuilder.defer##Type(static_cast<const Type&>(op)); },
+void FrameBuilder::deferNodeOps(const RenderNode& renderNode) {
+ typedef void (*OpDispatcher) (FrameBuilder& frameBuilder, const RecordedOp& op);
static OpDispatcher receivers[] = BUILD_DEFERRABLE_OP_LUT(OP_RECEIVER);
// can't be null, since DL=null node rejection happens before deferNodePropsAndOps
@@ -719,7 +390,7 @@
}
}
-void OpReorderer::deferRenderNodeOpImpl(const RenderNodeOp& op) {
+void FrameBuilder::deferRenderNodeOpImpl(const RenderNodeOp& op) {
if (op.renderNode->nothingToDraw()) return;
int count = mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
@@ -734,7 +405,7 @@
mCanvasState.restoreToCount(count);
}
-void OpReorderer::deferRenderNodeOp(const RenderNodeOp& op) {
+void FrameBuilder::deferRenderNodeOp(const RenderNodeOp& op) {
if (!op.skipInOrderDraw) {
deferRenderNodeOpImpl(op);
}
@@ -744,7 +415,7 @@
* Defers an unmergeable, strokeable op, accounting correctly
* for paint's style on the bounds being computed.
*/
-void OpReorderer::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
+void FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
BakedOpState::StrokeBehavior strokeBehavior) {
// Note: here we account for stroke when baking the op
BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
@@ -766,7 +437,7 @@
: (paint.isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices);
}
-void OpReorderer::deferArcOp(const ArcOp& op) {
+void FrameBuilder::deferArcOp(const ArcOp& op) {
deferStrokeableOp(op, tessBatchId(op));
}
@@ -775,7 +446,7 @@
|| state.computedState.clipState->mode == ClipMode::Rectangle;
}
-void OpReorderer::deferBitmapOp(const BitmapOp& op) {
+void FrameBuilder::deferBitmapOp(const BitmapOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
@@ -787,7 +458,7 @@
&& PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode
&& op.bitmap->colorType() != kAlpha_8_SkColorType
&& hasMergeableClip(*bakedState)) {
- mergeid_t mergeId = (mergeid_t) op.bitmap->getGenerationID();
+ mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.bitmap->getGenerationID());
// TODO: AssetAtlas in mergeId
currentLayer().deferMergeableOp(mAllocator, bakedState, OpBatchType::Bitmap, mergeId);
} else {
@@ -795,19 +466,19 @@
}
}
-void OpReorderer::deferBitmapMeshOp(const BitmapMeshOp& op) {
+void FrameBuilder::deferBitmapMeshOp(const BitmapMeshOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
}
-void OpReorderer::deferBitmapRectOp(const BitmapRectOp& op) {
+void FrameBuilder::deferBitmapRectOp(const BitmapRectOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
}
-void OpReorderer::deferCirclePropsOp(const CirclePropsOp& op) {
+void FrameBuilder::deferCirclePropsOp(const CirclePropsOp& op) {
// allocate a temporary oval op (with mAllocator, so it persists until render), so the
// renderer doesn't have to handle the RoundRectPropsOp type, and so state baking is simple.
float x = *(op.x);
@@ -822,29 +493,29 @@
deferOvalOp(*resolvedOp);
}
-void OpReorderer::deferFunctorOp(const FunctorOp& op) {
+void FrameBuilder::deferFunctorOp(const FunctorOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Functor);
}
-void OpReorderer::deferLinesOp(const LinesOp& op) {
+void FrameBuilder::deferLinesOp(const LinesOp& op) {
batchid_t batch = op.paint->isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices;
deferStrokeableOp(op, batch, BakedOpState::StrokeBehavior::Forced);
}
-void OpReorderer::deferOvalOp(const OvalOp& op) {
+void FrameBuilder::deferOvalOp(const OvalOp& op) {
deferStrokeableOp(op, tessBatchId(op));
}
-void OpReorderer::deferPatchOp(const PatchOp& op) {
+void FrameBuilder::deferPatchOp(const PatchOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
if (bakedState->computedState.transform.isPureTranslate()
&& PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode
&& hasMergeableClip(*bakedState)) {
- mergeid_t mergeId = (mergeid_t) op.bitmap->getGenerationID();
+ mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.bitmap->getGenerationID());
// TODO: AssetAtlas in mergeId
// Only use the MergedPatch batchId when merged, so Bitmap+Patch don't try to merge together
@@ -855,24 +526,24 @@
}
}
-void OpReorderer::deferPathOp(const PathOp& op) {
+void FrameBuilder::deferPathOp(const PathOp& op) {
deferStrokeableOp(op, OpBatchType::Bitmap);
}
-void OpReorderer::deferPointsOp(const PointsOp& op) {
+void FrameBuilder::deferPointsOp(const PointsOp& op) {
batchid_t batch = op.paint->isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices;
deferStrokeableOp(op, batch, BakedOpState::StrokeBehavior::Forced);
}
-void OpReorderer::deferRectOp(const RectOp& op) {
+void FrameBuilder::deferRectOp(const RectOp& op) {
deferStrokeableOp(op, tessBatchId(op));
}
-void OpReorderer::deferRoundRectOp(const RoundRectOp& op) {
+void FrameBuilder::deferRoundRectOp(const RoundRectOp& op) {
deferStrokeableOp(op, tessBatchId(op));
}
-void OpReorderer::deferRoundRectPropsOp(const RoundRectPropsOp& op) {
+void FrameBuilder::deferRoundRectPropsOp(const RoundRectPropsOp& op) {
// allocate a temporary round rect op (with mAllocator, so it persists until render), so the
// renderer doesn't have to handle the RoundRectPropsOp type, and so state baking is simple.
const RoundRectOp* resolvedOp = new (mAllocator) RoundRectOp(
@@ -883,7 +554,7 @@
deferRoundRectOp(*resolvedOp);
}
-void OpReorderer::deferSimpleRectsOp(const SimpleRectsOp& op) {
+void FrameBuilder::deferSimpleRectsOp(const SimpleRectsOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Vertices);
@@ -894,7 +565,7 @@
return paint.getColor() == SK_ColorBLACK ? OpBatchType::Text : OpBatchType::ColorText;
}
-void OpReorderer::deferTextOp(const TextOp& op) {
+void FrameBuilder::deferTextOp(const TextOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
@@ -909,19 +580,19 @@
}
}
-void OpReorderer::deferTextOnPathOp(const TextOnPathOp& op) {
+void FrameBuilder::deferTextOnPathOp(const TextOnPathOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint)));
}
-void OpReorderer::deferTextureLayerOp(const TextureLayerOp& op) {
+void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) {
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::TextureLayer);
}
-void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
+void FrameBuilder::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
float contentTranslateX, float contentTranslateY,
const Rect& repaintRect,
const Vector3& lightCenter,
@@ -936,11 +607,13 @@
repaintRect.left, repaintRect.top, repaintRect.right, repaintRect.bottom);
// create a new layer repaint, and push its index on the stack
- mLayerStack.push_back(mLayerReorderers.size());
- mLayerReorderers.emplace_back(layerWidth, layerHeight, repaintRect, beginLayerOp, renderNode);
+ mLayerStack.push_back(mLayerBuilders.size());
+ auto newFbo = mAllocator.create<LayerBuilder>(layerWidth, layerHeight,
+ repaintRect, beginLayerOp, renderNode);
+ mLayerBuilders.push_back(newFbo);
}
-void OpReorderer::restoreForLayer() {
+void FrameBuilder::restoreForLayer() {
// restore canvas, and pop finished layer off of the stack
mCanvasState.restore();
mLayerStack.pop_back();
@@ -948,7 +621,7 @@
// TODO: defer time rejection (when bounds become empty) + tests
// Option - just skip layers with no bounds at playback + defer?
-void OpReorderer::deferBeginLayerOp(const BeginLayerOp& op) {
+void FrameBuilder::deferBeginLayerOp(const BeginLayerOp& op) {
uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth();
uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight();
@@ -993,7 +666,7 @@
&op, nullptr);
}
-void OpReorderer::deferEndLayerOp(const EndLayerOp& /* ignored */) {
+void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {
const BeginLayerOp& beginLayerOp = *currentLayer().beginLayerOp;
int finishedLayerIndex = mLayerStack.back();
@@ -1006,7 +679,7 @@
beginLayerOp.localMatrix,
beginLayerOp.localClip,
beginLayerOp.paint,
- &mLayerReorderers[finishedLayerIndex].offscreenBuffer);
+ &(mLayerBuilders[finishedLayerIndex]->offscreenBuffer));
BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp);
if (bakedOpState) {
@@ -1016,12 +689,12 @@
// Layer won't be drawn - delete its drawing batches to prevent it from doing any work
// TODO: need to prevent any render work from being done
// - create layerop earlier for reject purposes?
- mLayerReorderers[finishedLayerIndex].clear();
+ mLayerBuilders[finishedLayerIndex]->clear();
return;
}
}
-void OpReorderer::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) {
+void FrameBuilder::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) {
Matrix4 boundsTransform(*(mCanvasState.currentSnapshot()->transform));
boundsTransform.multiply(op.localMatrix);
@@ -1030,13 +703,14 @@
dstRect.doIntersect(mCanvasState.currentSnapshot()->getRenderTargetClip());
// Allocate a holding position for the layer object (copyTo will produce, copyFrom will consume)
- OffscreenBuffer** layerHandle = mAllocator.create<OffscreenBuffer*>();
+ OffscreenBuffer** layerHandle = mAllocator.create<OffscreenBuffer*>(nullptr);
/**
* First, defer an operation to copy out the content from the rendertarget into a layer.
*/
auto copyToOp = new (mAllocator) CopyToLayerOp(op, layerHandle);
- BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator, dstRect, *copyToOp);
+ BakedOpState* bakedState = BakedOpState::directConstruct(mAllocator,
+ &(currentLayer().viewportClip), dstRect, *copyToOp);
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::CopyToLayer);
/**
@@ -1050,11 +724,12 @@
* a balanced EndUnclippedLayerOp is seen
*/
auto copyFromOp = new (mAllocator) CopyFromLayerOp(op, layerHandle);
- bakedState = BakedOpState::directConstruct(mAllocator, dstRect, *copyFromOp);
+ bakedState = BakedOpState::directConstruct(mAllocator,
+ &(currentLayer().viewportClip), dstRect, *copyFromOp);
currentLayer().activeUnclippedSaveLayers.push_back(bakedState);
}
-void OpReorderer::deferEndUnclippedLayerOp(const EndUnclippedLayerOp& op) {
+void FrameBuilder::deferEndUnclippedLayerOp(const EndUnclippedLayerOp& /* ignored */) {
LOG_ALWAYS_FATAL_IF(currentLayer().activeUnclippedSaveLayers.empty(), "no layer to end!");
BakedOpState* copyFromLayerOp = currentLayer().activeUnclippedSaveLayers.back();
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/FrameBuilder.h
similarity index 60%
rename from libs/hwui/OpReorderer.h
rename to libs/hwui/FrameBuilder.h
index b824d02..3ba73f0 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/FrameBuilder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#ifndef ANDROID_HWUI_OP_REORDERER_H
-#define ANDROID_HWUI_OP_REORDERER_H
+#pragma once
#include "BakedOpState.h"
#include "CanvasState.h"
#include "DisplayList.h"
+#include "LayerBuilder.h"
#include "RecordedOp.h"
#include <vector>
@@ -31,113 +31,34 @@
namespace uirenderer {
class BakedOpState;
-class BatchBase;
class LayerUpdateQueue;
-class MergingOpBatch;
class OffscreenBuffer;
-class OpBatch;
class Rect;
-typedef int batchid_t;
-typedef const void* mergeid_t;
-
-namespace OpBatchType {
- enum {
- Bitmap,
- MergedPatch,
- AlphaVertices,
- Vertices,
- AlphaMaskTexture,
- Text,
- ColorText,
- Shadow,
- TextureLayer,
- Functor,
- CopyToLayer,
- CopyFromLayer,
-
- Count // must be last
- };
-}
-
-class OpReorderer : public CanvasStateClient {
- typedef void (*BakedOpReceiver)(void*, const BakedOpState&);
- typedef void (*MergedOpReceiver)(void*, const MergedBakedOpList& opList);
-
- /**
- * Stores the deferred render operations and state used to compute ordering
- * for a single FBO/layer.
- */
- class LayerReorderer {
- public:
- // Create LayerReorderer for Fbo0
- LayerReorderer(uint32_t width, uint32_t height, const Rect& repaintRect)
- : LayerReorderer(width, height, repaintRect, nullptr, nullptr) {};
-
- // Create LayerReorderer for an offscreen layer, where beginLayerOp is present for a
- // saveLayer, renderNode is present for a HW layer.
- LayerReorderer(uint32_t width, uint32_t height,
- const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
-
- // iterate back toward target to see if anything drawn since should overlap the new op
- // if no target, merging ops still iterate to find similar batch to insert after
- void locateInsertIndex(int batchId, const Rect& clippedBounds,
- BatchBase** targetBatch, size_t* insertBatchIndex) const;
-
- void deferUnmergeableOp(LinearAllocator& allocator, BakedOpState* op, batchid_t batchId);
-
- // insertion point of a new batch, will hopefully be immediately after similar batch
- // (generally, should be similar shader)
- void deferMergeableOp(LinearAllocator& allocator,
- BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
-
- void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers, MergedOpReceiver*) const;
-
- void deferLayerClear(const Rect& dstRect);
-
- bool empty() const {
- return mBatches.empty();
- }
-
- void clear() {
- mBatches.clear();
- }
-
- void dump() const;
-
- const uint32_t width;
- const uint32_t height;
- const Rect repaintRect;
- OffscreenBuffer* offscreenBuffer;
- const BeginLayerOp* beginLayerOp;
- const RenderNode* renderNode;
-
- // list of deferred CopyFromLayer ops, to be deferred upon encountering EndUnclippedLayerOps
- std::vector<BakedOpState*> activeUnclippedSaveLayers;
- private:
- void flushLayerClears(LinearAllocator& allocator);
-
- std::vector<BatchBase*> mBatches;
-
- /**
- * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
- * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
- * collide, which avoids the need to resolve mergeid collisions.
- */
- std::unordered_map<mergeid_t, MergingOpBatch*> mMergingBatchLookup[OpBatchType::Count];
-
- // Maps batch ids to the most recent *non-merging* batch of that id
- OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };
-
- std::vector<Rect> mClearRects;
- };
-
+/**
+ * Traverses all of the drawing commands from the layers and RenderNodes passed into it, preparing
+ * them to be rendered.
+ *
+ * Resolves final drawing state for each operation (including clip, alpha and matrix), and then
+ * reorder and merge each op as it is resolved for drawing efficiency. Each layer of content (either
+ * from the LayerUpdateQueue, or temporary layers created by saveLayer operations in the
+ * draw stream) will create different reorder contexts, each in its own LayerBuilder.
+ *
+ * Then the prepared or 'baked' drawing commands can be issued by calling the templated
+ * replayBakedOps() function, which will dispatch them (including any created merged op collections)
+ * to a Dispatcher and Renderer. See BakedOpDispatcher for how these baked drawing operations are
+ * resolved into Glops and rendered via BakedOpRenderer.
+ *
+ * This class is also the authoritative source for traversing RenderNodes, both for standard op
+ * traversal within a DisplayList, and for out of order RenderNode traversal for Z and projection.
+ */
+class FrameBuilder : public CanvasStateClient {
public:
- OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
+ FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
uint32_t viewportWidth, uint32_t viewportHeight,
const std::vector< sp<RenderNode> >& nodes, const Vector3& lightCenter);
- virtual ~OpReorderer() {}
+ virtual ~FrameBuilder() {}
/**
* replayBakedOps() is templated based on what class will receive ops being replayed.
@@ -177,8 +98,8 @@
// Relay through layers in reverse order, since layers
// later in the list will be drawn by earlier ones
- for (int i = mLayerReorderers.size() - 1; i >= 1; i--) {
- LayerReorderer& layer = mLayerReorderers[i];
+ for (int i = mLayerBuilders.size() - 1; i >= 1; i--) {
+ LayerBuilder& layer = *(mLayerBuilders[i]);
if (layer.renderNode) {
// cached HW layer - can't skip layer if empty
renderer.startRepaintLayer(layer.offscreenBuffer, layer.repaintRect);
@@ -191,15 +112,15 @@
}
}
- const LayerReorderer& fbo0 = mLayerReorderers[0];
+ const LayerBuilder& fbo0 = *(mLayerBuilders[0]);
renderer.startFrame(fbo0.width, fbo0.height, fbo0.repaintRect);
fbo0.replayBakedOpsImpl((void*)&renderer, unmergedReceivers, mergedReceivers);
renderer.endFrame(fbo0.repaintRect);
}
void dump() const {
- for (auto&& layer : mLayerReorderers) {
- layer.dump();
+ for (auto&& layer : mLayerBuilders) {
+ layer->dump();
}
}
@@ -222,7 +143,7 @@
const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
void restoreForLayer();
- LayerReorderer& currentLayer() { return mLayerReorderers[mLayerStack.back()]; }
+ LayerBuilder& currentLayer() { return *(mLayerBuilders[mLayerStack.back()]); }
BakedOpState* tryBakeOpState(const RecordedOp& recordedOp) {
return BakedOpState::tryConstruct(mAllocator, *mCanvasState.writableSnapshot(), recordedOp);
@@ -252,7 +173,7 @@
BakedOpState::StrokeBehavior strokeBehavior = BakedOpState::StrokeBehavior::StyleDefined);
/**
- * Declares all OpReorderer::deferXXXXOp() methods for every RecordedOp type.
+ * Declares all FrameBuilder::deferXXXXOp() methods for every RecordedOp type.
*
* These private methods are called from within deferImpl to defer each individual op
* type differently.
@@ -262,17 +183,17 @@
#undef X
// List of every deferred layer's render state. Replayed in reverse order to render a frame.
- std::vector<LayerReorderer> mLayerReorderers;
+ std::vector<LayerBuilder*> mLayerBuilders;
/*
- * Stack of indices within mLayerReorderers representing currently active layers. If drawing
+ * Stack of indices within mLayerBuilders representing currently active layers. If drawing
* layerA within a layerB, will contain, in order:
* - 0 (representing FBO 0, always present)
* - layerB's index
* - layerA's index
*
- * Note that this doesn't vector doesn't always map onto all values of mLayerReorderers. When a
- * layer is finished deferring, it will still be represented in mLayerReorderers, but it's index
+ * Note that this doesn't vector doesn't always map onto all values of mLayerBuilders. When a
+ * layer is finished deferring, it will still be represented in mLayerBuilders, but it's index
* won't be in mLayerStack. This is because it can be replayed, but can't have any more drawing
* ops added to it.
*/
@@ -286,5 +207,3 @@
}; // namespace uirenderer
}; // namespace android
-
-#endif // ANDROID_HWUI_OP_REORDERER_H
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
new file mode 100644
index 0000000..7170d4f
--- /dev/null
+++ b/libs/hwui/LayerBuilder.cpp
@@ -0,0 +1,365 @@
+/*
+ * 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 "LayerBuilder.h"
+
+#include "BakedOpState.h"
+#include "RenderNode.h"
+#include "utils/PaintUtils.h"
+#include "utils/TraceUtils.h"
+
+#include <utils/TypeHelpers.h>
+
+namespace android {
+namespace uirenderer {
+
+class BatchBase {
+public:
+ BatchBase(batchid_t batchId, BakedOpState* op, bool merging)
+ : mBatchId(batchId)
+ , mMerging(merging) {
+ mBounds = op->computedState.clippedBounds;
+ mOps.push_back(op);
+ }
+
+ bool intersects(const Rect& rect) const {
+ if (!rect.intersects(mBounds)) return false;
+
+ for (const BakedOpState* op : mOps) {
+ if (rect.intersects(op->computedState.clippedBounds)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ batchid_t getBatchId() const { return mBatchId; }
+ bool isMerging() const { return mMerging; }
+
+ const std::vector<BakedOpState*>& getOps() const { return mOps; }
+
+ void dump() const {
+ ALOGD(" Batch %p, id %d, merging %d, count %d, bounds " RECT_STRING,
+ this, mBatchId, mMerging, (int) mOps.size(), RECT_ARGS(mBounds));
+ }
+protected:
+ batchid_t mBatchId;
+ Rect mBounds;
+ std::vector<BakedOpState*> mOps;
+ bool mMerging;
+};
+
+class OpBatch : public BatchBase {
+public:
+ static void* operator new(size_t size, LinearAllocator& allocator) {
+ return allocator.alloc(size);
+ }
+
+ OpBatch(batchid_t batchId, BakedOpState* op)
+ : BatchBase(batchId, op, false) {
+ }
+
+ void batchOp(BakedOpState* op) {
+ mBounds.unionWith(op->computedState.clippedBounds);
+ mOps.push_back(op);
+ }
+};
+
+class MergingOpBatch : public BatchBase {
+public:
+ static void* operator new(size_t size, LinearAllocator& allocator) {
+ return allocator.alloc(size);
+ }
+
+ MergingOpBatch(batchid_t batchId, BakedOpState* op)
+ : BatchBase(batchId, op, true)
+ , mClipSideFlags(op->computedState.clipSideFlags) {
+ }
+
+ /*
+ * Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds
+ * and clip side flags. Positive bounds delta means new bounds fit in old.
+ */
+ static inline bool checkSide(const int currentFlags, const int newFlags, const int side,
+ float boundsDelta) {
+ bool currentClipExists = currentFlags & side;
+ bool newClipExists = newFlags & side;
+
+ // if current is clipped, we must be able to fit new bounds in current
+ if (boundsDelta > 0 && currentClipExists) return false;
+
+ // if new is clipped, we must be able to fit current bounds in new
+ if (boundsDelta < 0 && newClipExists) return false;
+
+ return true;
+ }
+
+ static bool paintIsDefault(const SkPaint& paint) {
+ return paint.getAlpha() == 255
+ && paint.getColorFilter() == nullptr
+ && paint.getShader() == nullptr;
+ }
+
+ static bool paintsAreEquivalent(const SkPaint& a, const SkPaint& b) {
+ // Note: don't check color, since all currently mergeable ops can merge across colors
+ return a.getAlpha() == b.getAlpha()
+ && a.getColorFilter() == b.getColorFilter()
+ && a.getShader() == b.getShader();
+ }
+
+ /*
+ * Checks if a (mergeable) op can be merged into this batch
+ *
+ * If true, the op's multiDraw must be guaranteed to handle both ops simultaneously, so it is
+ * important to consider all paint attributes used in the draw calls in deciding both a) if an
+ * op tries to merge at all, and b) if the op can merge with another set of ops
+ *
+ * False positives can lead to information from the paints of subsequent merged operations being
+ * dropped, so we make simplifying qualifications on the ops that can merge, per op type.
+ */
+ bool canMergeWith(BakedOpState* op) const {
+ bool isTextBatch = getBatchId() == OpBatchType::Text
+ || getBatchId() == OpBatchType::ColorText;
+
+ // Overlapping other operations is only allowed for text without shadow. For other ops,
+ // multiDraw isn't guaranteed to overdraw correctly
+ if (!isTextBatch || PaintUtils::hasTextShadow(op->op->paint)) {
+ if (intersects(op->computedState.clippedBounds)) return false;
+ }
+
+ const BakedOpState* lhs = op;
+ const BakedOpState* rhs = mOps[0];
+
+ if (!MathUtils::areEqual(lhs->alpha, rhs->alpha)) return false;
+
+ // Identical round rect clip state means both ops will clip in the same way, or not at all.
+ // As the state objects are const, we can compare their pointers to determine mergeability
+ if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
+ if (lhs->projectionPathMask != rhs->projectionPathMask) return false;
+
+ /* Clipping compatibility check
+ *
+ * Exploits the fact that if a op or batch is clipped on a side, its bounds will equal its
+ * clip for that side.
+ */
+ const int currentFlags = mClipSideFlags;
+ const int newFlags = op->computedState.clipSideFlags;
+ if (currentFlags != OpClipSideFlags::None || newFlags != OpClipSideFlags::None) {
+ const Rect& opBounds = op->computedState.clippedBounds;
+ float boundsDelta = mBounds.left - opBounds.left;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Left, boundsDelta)) return false;
+ boundsDelta = mBounds.top - opBounds.top;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Top, boundsDelta)) return false;
+
+ // right and bottom delta calculation reversed to account for direction
+ boundsDelta = opBounds.right - mBounds.right;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Right, boundsDelta)) return false;
+ boundsDelta = opBounds.bottom - mBounds.bottom;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Bottom, boundsDelta)) return false;
+ }
+
+ const SkPaint* newPaint = op->op->paint;
+ const SkPaint* oldPaint = mOps[0]->op->paint;
+
+ if (newPaint == oldPaint) {
+ // if paints are equal, then modifiers + paint attribs don't need to be compared
+ return true;
+ } else if (newPaint && !oldPaint) {
+ return paintIsDefault(*newPaint);
+ } else if (!newPaint && oldPaint) {
+ return paintIsDefault(*oldPaint);
+ }
+ return paintsAreEquivalent(*newPaint, *oldPaint);
+ }
+
+ void mergeOp(BakedOpState* op) {
+ mBounds.unionWith(op->computedState.clippedBounds);
+ mOps.push_back(op);
+
+ // Because a new op must have passed canMergeWith(), we know it's passed the clipping compat
+ // check, and doesn't extend past a side of the clip that's in use by the merged batch.
+ // Therefore it's safe to simply always merge flags, and use the bounds as the clip rect.
+ mClipSideFlags |= op->computedState.clipSideFlags;
+ }
+
+ int getClipSideFlags() const { return mClipSideFlags; }
+ const Rect& getClipRect() const { return mBounds; }
+
+private:
+ int mClipSideFlags;
+};
+
+LayerBuilder::LayerBuilder(uint32_t width, uint32_t height,
+ const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode)
+ : width(width)
+ , height(height)
+ , repaintRect(repaintRect)
+ , offscreenBuffer(renderNode ? renderNode->getLayer() : nullptr)
+ , beginLayerOp(beginLayerOp)
+ , renderNode(renderNode)
+ , viewportClip(Rect(width, height)) {}
+
+// iterate back toward target to see if anything drawn since should overlap the new op
+// if no target, merging ops still iterate to find similar batch to insert after
+void LayerBuilder::locateInsertIndex(int batchId, const Rect& clippedBounds,
+ BatchBase** targetBatch, size_t* insertBatchIndex) const {
+ for (int i = mBatches.size() - 1; i >= 0; i--) {
+ BatchBase* overBatch = mBatches[i];
+
+ if (overBatch == *targetBatch) break;
+
+ // TODO: also consider shader shared between batch types
+ if (batchId == overBatch->getBatchId()) {
+ *insertBatchIndex = i + 1;
+ if (!*targetBatch) break; // found insert position, quit
+ }
+
+ if (overBatch->intersects(clippedBounds)) {
+ // NOTE: it may be possible to optimize for special cases where two operations
+ // of the same batch/paint could swap order, such as with a non-mergeable
+ // (clipped) and a mergeable text operation
+ *targetBatch = nullptr;
+ break;
+ }
+ }
+}
+
+void LayerBuilder::deferLayerClear(const Rect& rect) {
+ mClearRects.push_back(rect);
+}
+
+void LayerBuilder::flushLayerClears(LinearAllocator& allocator) {
+ if (CC_UNLIKELY(!mClearRects.empty())) {
+ const int vertCount = mClearRects.size() * 4;
+ // put the verts in the frame allocator, since
+ // 1) SimpleRectsOps needs verts, not rects
+ // 2) even if mClearRects stored verts, std::vectors will move their contents
+ Vertex* const verts = (Vertex*) allocator.alloc(vertCount * sizeof(Vertex));
+
+ Vertex* currentVert = verts;
+ Rect bounds = mClearRects[0];
+ for (auto&& rect : mClearRects) {
+ bounds.unionWith(rect);
+ Vertex::set(currentVert++, rect.left, rect.top);
+ Vertex::set(currentVert++, rect.right, rect.top);
+ Vertex::set(currentVert++, rect.left, rect.bottom);
+ Vertex::set(currentVert++, rect.right, rect.bottom);
+ }
+ mClearRects.clear(); // discard rects before drawing so this method isn't reentrant
+
+ // One or more unclipped saveLayers have been enqueued, with deferred clears.
+ // Flush all of these clears with a single draw
+ SkPaint* paint = allocator.create<SkPaint>();
+ paint->setXfermodeMode(SkXfermode::kClear_Mode);
+ SimpleRectsOp* op = new (allocator) SimpleRectsOp(bounds,
+ Matrix4::identity(), nullptr, paint,
+ verts, vertCount);
+ BakedOpState* bakedState = BakedOpState::directConstruct(allocator,
+ &viewportClip, bounds, *op);
+ deferUnmergeableOp(allocator, bakedState, OpBatchType::Vertices);
+ }
+}
+
+void LayerBuilder::deferUnmergeableOp(LinearAllocator& allocator,
+ BakedOpState* op, batchid_t batchId) {
+ if (batchId != OpBatchType::CopyToLayer) {
+ // if first op after one or more unclipped saveLayers, flush the layer clears
+ flushLayerClears(allocator);
+ }
+
+ OpBatch* targetBatch = mBatchLookup[batchId];
+
+ size_t insertBatchIndex = mBatches.size();
+ if (targetBatch) {
+ locateInsertIndex(batchId, op->computedState.clippedBounds,
+ (BatchBase**)(&targetBatch), &insertBatchIndex);
+ }
+
+ if (targetBatch) {
+ targetBatch->batchOp(op);
+ } else {
+ // new non-merging batch
+ targetBatch = new (allocator) OpBatch(batchId, op);
+ mBatchLookup[batchId] = targetBatch;
+ mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
+ }
+}
+
+void LayerBuilder::deferMergeableOp(LinearAllocator& allocator,
+ BakedOpState* op, batchid_t batchId, mergeid_t mergeId) {
+ if (batchId != OpBatchType::CopyToLayer) {
+ // if first op after one or more unclipped saveLayers, flush the layer clears
+ flushLayerClears(allocator);
+ }
+ MergingOpBatch* targetBatch = nullptr;
+
+ // Try to merge with any existing batch with same mergeId
+ auto getResult = mMergingBatchLookup[batchId].find(mergeId);
+ if (getResult != mMergingBatchLookup[batchId].end()) {
+ targetBatch = getResult->second;
+ if (!targetBatch->canMergeWith(op)) {
+ targetBatch = nullptr;
+ }
+ }
+
+ size_t insertBatchIndex = mBatches.size();
+ locateInsertIndex(batchId, op->computedState.clippedBounds,
+ (BatchBase**)(&targetBatch), &insertBatchIndex);
+
+ if (targetBatch) {
+ targetBatch->mergeOp(op);
+ } else {
+ // new merging batch
+ targetBatch = new (allocator) MergingOpBatch(batchId, op);
+ mMergingBatchLookup[batchId].insert(std::make_pair(mergeId, targetBatch));
+
+ mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
+ }
+}
+
+void LayerBuilder::replayBakedOpsImpl(void* arg,
+ BakedOpReceiver* unmergedReceivers, MergedOpReceiver* mergedReceivers) const {
+ ATRACE_NAME("flush drawing commands");
+ for (const BatchBase* batch : mBatches) {
+ size_t size = batch->getOps().size();
+ if (size > 1 && batch->isMerging()) {
+ int opId = batch->getOps()[0]->op->opId;
+ const MergingOpBatch* mergingBatch = static_cast<const MergingOpBatch*>(batch);
+ MergedBakedOpList data = {
+ batch->getOps().data(),
+ size,
+ mergingBatch->getClipSideFlags(),
+ mergingBatch->getClipRect()
+ };
+ mergedReceivers[opId](arg, data);
+ } else {
+ for (const BakedOpState* op : batch->getOps()) {
+ unmergedReceivers[op->op->opId](arg, *op);
+ }
+ }
+ }
+}
+
+void LayerBuilder::dump() const {
+ ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p",
+ this, width, height, offscreenBuffer, beginLayerOp, renderNode);
+ for (const BatchBase* batch : mBatches) {
+ batch->dump();
+ }
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/LayerBuilder.h b/libs/hwui/LayerBuilder.h
new file mode 100644
index 0000000..99968e1
--- /dev/null
+++ b/libs/hwui/LayerBuilder.h
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "ClipArea.h"
+#include "Rect.h"
+#include "utils/Macros.h"
+
+#include <vector>
+#include <unordered_map>
+
+struct SkRect;
+
+namespace android {
+namespace uirenderer {
+
+class BakedOpState;
+struct BeginLayerOp;
+class BatchBase;
+class LinearAllocator;
+struct MergedBakedOpList;
+class MergingOpBatch;
+class OffscreenBuffer;
+class OpBatch;
+class RenderNode;
+
+typedef int batchid_t;
+typedef const void* mergeid_t;
+
+namespace OpBatchType {
+ enum {
+ Bitmap,
+ MergedPatch,
+ AlphaVertices,
+ Vertices,
+ AlphaMaskTexture,
+ Text,
+ ColorText,
+ Shadow,
+ TextureLayer,
+ Functor,
+ CopyToLayer,
+ CopyFromLayer,
+
+ Count // must be last
+ };
+}
+
+typedef void (*BakedOpReceiver)(void*, const BakedOpState&);
+typedef void (*MergedOpReceiver)(void*, const MergedBakedOpList& opList);
+
+/**
+ * Stores the deferred render operations and state used to compute ordering
+ * for a single FBO/layer.
+ */
+class LayerBuilder {
+// Prevent copy/assign because users may stash pointer to offscreenBuffer and viewportClip
+PREVENT_COPY_AND_ASSIGN(LayerBuilder);
+public:
+ // Create LayerBuilder for Fbo0
+ LayerBuilder(uint32_t width, uint32_t height, const Rect& repaintRect)
+ : LayerBuilder(width, height, repaintRect, nullptr, nullptr) {};
+
+ // Create LayerBuilder for an offscreen layer, where beginLayerOp is present for a
+ // saveLayer, renderNode is present for a HW layer.
+ LayerBuilder(uint32_t width, uint32_t height,
+ const Rect& repaintRect, const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
+
+ // iterate back toward target to see if anything drawn since should overlap the new op
+ // if no target, merging ops still iterate to find similar batch to insert after
+ void locateInsertIndex(int batchId, const Rect& clippedBounds,
+ BatchBase** targetBatch, size_t* insertBatchIndex) const;
+
+ void deferUnmergeableOp(LinearAllocator& allocator, BakedOpState* op, batchid_t batchId);
+
+ // insertion point of a new batch, will hopefully be immediately after similar batch
+ // (generally, should be similar shader)
+ void deferMergeableOp(LinearAllocator& allocator,
+ BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
+
+ void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers, MergedOpReceiver*) const;
+
+ void deferLayerClear(const Rect& dstRect);
+
+ bool empty() const {
+ return mBatches.empty();
+ }
+
+ void clear() {
+ mBatches.clear();
+ }
+
+ void dump() const;
+
+ const uint32_t width;
+ const uint32_t height;
+ const Rect repaintRect;
+ OffscreenBuffer* offscreenBuffer;
+ const BeginLayerOp* beginLayerOp;
+ const RenderNode* renderNode;
+ const ClipRect viewportClip;
+
+ // list of deferred CopyFromLayer ops, to be deferred upon encountering EndUnclippedLayerOps
+ std::vector<BakedOpState*> activeUnclippedSaveLayers;
+private:
+ void flushLayerClears(LinearAllocator& allocator);
+
+ std::vector<BatchBase*> mBatches;
+
+ /**
+ * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
+ * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
+ * collide, which avoids the need to resolve mergeid collisions.
+ */
+ std::unordered_map<mergeid_t, MergingOpBatch*> mMergingBatchLookup[OpBatchType::Count];
+
+ // Maps batch ids to the most recent *non-merging* batch of that id
+ OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };
+
+ std::vector<Rect> mClearRects;
+};
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/LayerUpdateQueue.h b/libs/hwui/LayerUpdateQueue.h
index be612d2..5b1a854 100644
--- a/libs/hwui/LayerUpdateQueue.h
+++ b/libs/hwui/LayerUpdateQueue.h
@@ -42,7 +42,7 @@
LayerUpdateQueue() {}
void enqueueLayerWithDamage(RenderNode* renderNode, Rect dirty);
void clear();
- const std::vector<Entry> entries() const { return mEntries; }
+ const std::vector<Entry>& entries() const { return mEntries; }
private:
std::vector<Entry> mEntries;
};
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index b6f50b1..8e4a3df 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -47,11 +47,11 @@
class DisplayListCanvas;
class DisplayListOp;
class OpenGLRenderer;
-class OpReorderer;
class Rect;
class SkiaShader;
#if HWUI_NEW_OPS
+class FrameBuilder;
class OffscreenBuffer;
struct RenderNodeOp;
typedef OffscreenBuffer layer_t;
@@ -87,7 +87,7 @@
*/
class RenderNode : public VirtualLightRefBase {
friend class TestUtils; // allow TestUtils to access syncDisplayList / syncProperties
-friend class OpReorderer;
+friend class FrameBuilder;
public:
enum DirtyPropertyMask {
GENERIC = 1 << 1,
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 130cc80..976f775 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -162,15 +162,15 @@
mCanvas->save(SkCanvas::kMatrixClip_SaveFlag);
}
-SkCanvas::SaveLayerStrategy SkiaCanvasProxy::willSaveLayer(const SkRect* rectPtr,
- const SkPaint* paint, SaveFlags flags) {
+SkCanvas::SaveLayerStrategy SkiaCanvasProxy::getSaveLayerStrategy(const SaveLayerRec& saveLayerRec) {
SkRect rect;
- if (rectPtr) {
- rect = *rectPtr;
- } else if(!mCanvas->getClipBounds(&rect)) {
+ if (saveLayerRec.fBounds) {
+ rect = *saveLayerRec.fBounds;
+ } else if (!mCanvas->getClipBounds(&rect)) {
rect = SkRect::MakeEmpty();
}
- mCanvas->saveLayer(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, paint, flags);
+ mCanvas->saveLayer(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, saveLayerRec.fPaint,
+ (SkCanvas::SaveFlags) SaveLayerFlagsToSaveFlags(saveLayerRec.fSaveLayerFlags));
return SkCanvas::kNoLayer_SaveLayerStrategy;
}
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 0089fb5..e342d19 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -47,7 +47,7 @@
virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
virtual void willSave() override;
- virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) override;
+ virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
virtual void willRestore() override;
virtual void didConcat(const SkMatrix&) override;
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 6b44557..227b640 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -54,6 +54,12 @@
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
+Rect OffscreenBuffer::getTextureCoordinates() {
+ const float texX = 1.0f / float(texture.width);
+ const float texY = 1.0f / float(texture.height);
+ return Rect(0, viewportHeight * texY, viewportWidth * texX, 0);
+}
+
void OffscreenBuffer::updateMeshFromRegion() {
// avoid T-junctions as they cause artifacts in between the resultant
// geometry when complex transforms occur.
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h
index fac6c35..2d8d529 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.h
+++ b/libs/hwui/renderstate/OffscreenBufferPool.h
@@ -46,6 +46,8 @@
uint32_t viewportWidth, uint32_t viewportHeight);
~OffscreenBuffer();
+ Rect getTextureCoordinates();
+
// must be called prior to rendering, to construct/update vertex buffer
void updateMeshFromRegion();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1af8f80..24d43df 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -31,7 +31,7 @@
#include "utils/TimeUtils.h"
#if HWUI_NEW_OPS
-#include "OpReorderer.h"
+#include "FrameBuilder.h"
#endif
#include <cutils/properties.h>
@@ -338,14 +338,13 @@
mEglManager.damageFrame(frame, dirty);
#if HWUI_NEW_OPS
- OpReorderer reorderer(mLayerUpdateQueue, dirty, frame.width(), frame.height(),
+ FrameBuilder frameBuilder(mLayerUpdateQueue, dirty, frame.width(), frame.height(),
mRenderNodes, mLightCenter);
mLayerUpdateQueue.clear();
BakedOpRenderer renderer(Caches::getInstance(), mRenderThread.renderState(),
mOpaque, mLightInfo);
// TODO: profiler().draw(mCanvas);
- reorderer.replayBakedOps<BakedOpDispatcher>(renderer);
-
+ frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
bool drew = renderer.didDraw();
#else
@@ -513,11 +512,11 @@
void CanvasContext::prepareAndDraw(RenderNode* node) {
ATRACE_CALL();
+ nsecs_t vsync = mRenderThread.timeLord().computeFrameTimeNanos();
int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
UiFrameInfoBuilder(frameInfo)
.addFlag(FrameInfoFlags::RTAnimation)
- .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(),
- mRenderThread.timeLord().latestVsync());
+ .setVsync(vsync, vsync);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC), node);
@@ -579,7 +578,7 @@
node->setPropertyFieldsDirty(RenderNode::GENERIC);
#if HWUI_NEW_OPS
- LOG_ALWAYS_FATAL("unsupported");
+ // TODO: support buildLayer
#else
mCanvas->markLayersAsBuildLayers();
mCanvas->flushLayerUpdates();
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index ac14fc8..edde31e 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -53,6 +53,13 @@
&& MathUtils::areEqual(a.right, b.right) \
&& MathUtils::areEqual(a.bottom, b.bottom));
+#define EXPECT_CLIP_RECT(expRect, clipStatePtr) \
+ EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped"; \
+ if ((clipStatePtr)->mode == ClipMode::Rectangle) { \
+ EXPECT_EQ((expRect), reinterpret_cast<const ClipRect*>(clipStatePtr)->rect); \
+ } else { \
+ ADD_FAILURE() << "ClipState not a rect"; \
+ }
/**
* Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope
* (for e.g. accessing its RenderState)
diff --git a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
index 78fcd8b..c899850 100644
--- a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
@@ -29,14 +29,27 @@
public:
sp<RenderNode> card;
void createContent(int width, int height, TestCanvas& canvas) override {
- canvas.drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); // background
+ canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode); // background
- card = TestUtils::createNode(0, 0, 200, 200,
+ card = TestUtils::createNode(0, 0, 400, 800,
[](RenderProperties& props, TestCanvas& canvas) {
- canvas.saveLayerAlpha(0, 0, 200, 200, 128, SkCanvas::kClipToLayer_SaveFlag);
- canvas.drawColor(0xFF00FF00, SkXfermode::kSrcOver_Mode); // outer, unclipped
- canvas.saveLayerAlpha(50, 50, 150, 150, 128, SkCanvas::kClipToLayer_SaveFlag);
- canvas.drawColor(0xFF0000FF, SkXfermode::kSrcOver_Mode); // inner, clipped
+ // nested clipped saveLayers
+ canvas.saveLayerAlpha(0, 0, 400, 400, 200, SkCanvas::kClipToLayer_SaveFlag);
+ canvas.drawColor(Color::Green_700, SkXfermode::kSrcOver_Mode);
+ canvas.clipRect(50, 50, 350, 350, SkRegion::kIntersect_Op);
+ canvas.saveLayerAlpha(100, 100, 300, 300, 128, SkCanvas::kClipToLayer_SaveFlag);
+ canvas.drawColor(Color::Blue_500, SkXfermode::kSrcOver_Mode);
+ canvas.restore();
+ canvas.restore();
+
+ // single unclipped saveLayer
+ canvas.save(SkCanvas::kMatrixClip_SaveFlag);
+ canvas.translate(0, 400);
+ canvas.saveLayerAlpha(100, 100, 300, 300, 128, SkCanvas::SaveFlags(0)); // unclipped
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(Color::Green_700);
+ canvas.drawCircle(200, 200, 200, paint);
canvas.restore();
canvas.restore();
});
diff --git a/libs/hwui/tests/microbench/OpReordererBench.cpp b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
similarity index 82%
rename from libs/hwui/tests/microbench/OpReordererBench.cpp
rename to libs/hwui/tests/microbench/FrameBuilderBench.cpp
index 6bfe5a9..67c95e2 100644
--- a/libs/hwui/tests/microbench/OpReordererBench.cpp
+++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -19,8 +19,8 @@
#include "BakedOpState.h"
#include "BakedOpDispatcher.h"
#include "BakedOpRenderer.h"
+#include "FrameBuilder.h"
#include "LayerUpdateQueue.h"
-#include "OpReorderer.h"
#include "RecordedOp.h"
#include "RecordingCanvas.h"
#include "tests/common/TestContext.h"
@@ -61,20 +61,20 @@
return vec;
}
-BENCHMARK_NO_ARG(BM_OpReorderer_defer);
-void BM_OpReorderer_defer::Run(int iters) {
+BENCHMARK_NO_ARG(BM_FrameBuilder_defer);
+void BM_FrameBuilder_defer::Run(int iters) {
auto nodes = createTestNodeList();
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
nodes, sLightCenter);
- MicroBench::DoNotOptimize(&reorderer);
+ MicroBench::DoNotOptimize(&frameBuilder);
}
StopBenchmarkTiming();
}
-BENCHMARK_NO_ARG(BM_OpReorderer_deferAndRender);
-void BM_OpReorderer_deferAndRender::Run(int iters) {
+BENCHMARK_NO_ARG(BM_FrameBuilder_deferAndRender);
+void BM_FrameBuilder_deferAndRender::Run(int iters) {
TestUtils::runOnRenderThread([this, iters](RenderThread& thread) {
auto nodes = createTestNodeList();
BakedOpRenderer::LightInfo lightInfo = {50.0f, 128, 128 };
@@ -84,11 +84,11 @@
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
nodes, sLightCenter);
BakedOpRenderer renderer(caches, renderState, true, lightInfo);
- reorderer.replayBakedOps<BakedOpDispatcher>(renderer);
+ frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
MicroBench::DoNotOptimize(&renderer);
}
StopBenchmarkTiming();
@@ -117,10 +117,10 @@
auto nodes = getSyncedSceneNodes(sceneName);
benchmark.StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
- OpReorderer reorderer(sEmptyLayerUpdateQueue,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
nodes, sLightCenter);
- MicroBench::DoNotOptimize(&reorderer);
+ MicroBench::DoNotOptimize(&frameBuilder);
}
benchmark.StopBenchmarkTiming();
}
@@ -136,25 +136,25 @@
benchmark.StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
- OpReorderer reorderer(sEmptyLayerUpdateQueue,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
nodes, sLightCenter);
BakedOpRenderer renderer(caches, renderState, true, lightInfo);
- reorderer.replayBakedOps<BakedOpDispatcher>(renderer);
+ frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
MicroBench::DoNotOptimize(&renderer);
}
benchmark.StopBenchmarkTiming();
});
}
-BENCHMARK_NO_ARG(BM_OpReorderer_listview_defer);
-void BM_OpReorderer_listview_defer::Run(int iters) {
+BENCHMARK_NO_ARG(BM_FrameBuilder_listview_defer);
+void BM_FrameBuilder_listview_defer::Run(int iters) {
benchDeferScene(*this, iters, "listview");
}
-BENCHMARK_NO_ARG(BM_OpReorderer_listview_deferAndRender);
-void BM_OpReorderer_listview_deferAndRender::Run(int iters) {
+BENCHMARK_NO_ARG(BM_FrameBuilder_listview_deferAndRender);
+void BM_FrameBuilder_listview_deferAndRender::Run(int iters) {
benchDeferAndRenderScene(*this, iters, "listview");
}
diff --git a/libs/hwui/tests/unit/BakedOpStateTests.cpp b/libs/hwui/tests/unit/BakedOpStateTests.cpp
index 3fd822d..0f8e047 100644
--- a/libs/hwui/tests/unit/BakedOpStateTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpStateTests.cpp
@@ -176,46 +176,50 @@
}
TEST(BakedOpState, tryConstruct) {
- LinearAllocator allocator;
-
Matrix4 translate100x0;
translate100x0.loadTranslate(100, 0, 0);
SkPaint paint;
ClipRect clip(Rect(100, 200));
- {
- RectOp rejectOp(Rect(30, 40, 100, 200), translate100x0, &clip, &paint);
- auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 200));
- BakedOpState* bakedState = BakedOpState::tryConstruct(allocator, *snapshot, rejectOp);
- EXPECT_EQ(nullptr, bakedState); // rejected by clip, so not constructed
- EXPECT_GT(8u, allocator.usedSize()); // no significant allocation space used for rejected op
- }
- {
- RectOp successOp(Rect(30, 40, 100, 200), Matrix4::identity(), &clip, &paint);
- auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 200));
- BakedOpState* bakedState = BakedOpState::tryConstruct(allocator, *snapshot, successOp);
+ LinearAllocator allocator;
+ RectOp successOp(Rect(30, 40, 100, 200), Matrix4::identity(), &clip, &paint);
+ auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 200));
+ EXPECT_NE(nullptr, BakedOpState::tryConstruct(allocator, *snapshot, successOp))
+ << "successOp NOT rejected by clip, so should be constructed";
+ size_t successAllocSize = allocator.usedSize();
+ EXPECT_LE(64u, successAllocSize) << "relatively large alloc for non-rejected op";
- EXPECT_NE(nullptr, bakedState); // NOT rejected by clip, so will be constructed
- EXPECT_LE(64u, allocator.usedSize()); // relatively large alloc for non-rejected op
- }
+ RectOp rejectOp(Rect(30, 40, 100, 200), translate100x0, &clip, &paint);
+ EXPECT_EQ(nullptr, BakedOpState::tryConstruct(allocator, *snapshot, rejectOp))
+ << "rejectOp rejected by clip, so should not be constructed";
+
+ // NOTE: this relies on the clip having already been serialized by the op above
+ EXPECT_EQ(successAllocSize, allocator.usedSize()) << "no extra allocation used for rejected op";
}
TEST(BakedOpState, tryShadowOpConstruct) {
+ Matrix4 translate10x20;
+ translate10x20.loadTranslate(10, 20, 0);
+
LinearAllocator allocator;
{
- auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect()); // Note: empty clip
+ auto snapshot = TestUtils::makeSnapshot(translate10x20, Rect()); // Note: empty clip
BakedOpState* bakedState = BakedOpState::tryShadowOpConstruct(allocator, *snapshot, (ShadowOp*)0x1234);
- EXPECT_EQ(nullptr, bakedState); // rejected by clip, so not constructed
- EXPECT_GT(8u, allocator.usedSize()); // no significant allocation space used for rejected op
+ EXPECT_EQ(nullptr, bakedState) << "op should be rejected by clip, so not constructed";
+ EXPECT_EQ(0u, allocator.usedSize()) << "no serialization, even for clip,"
+ "since op is quick rejected based on snapshot clip";
}
{
- auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(100, 200));
+ auto snapshot = TestUtils::makeSnapshot(translate10x20, Rect(100, 200));
BakedOpState* bakedState = BakedOpState::tryShadowOpConstruct(allocator, *snapshot, (ShadowOp*)0x1234);
- ASSERT_NE(nullptr, bakedState); // NOT rejected by clip, so will be constructed
- EXPECT_LE(64u, allocator.usedSize()); // relatively large alloc for non-rejected op
+ ASSERT_NE(nullptr, bakedState) << "NOT rejected by clip, so op should be constructed";
+ EXPECT_LE(64u, allocator.usedSize()) << "relatively large alloc for non-rejected op";
+
+ EXPECT_MATRIX_APPROX_EQ(translate10x20, bakedState->computedState.transform);
+ EXPECT_EQ(Rect(100, 200), bakedState->computedState.clippedBounds);
}
}
diff --git a/libs/hwui/tests/unit/OpReordererTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
similarity index 90%
rename from libs/hwui/tests/unit/OpReordererTests.cpp
rename to libs/hwui/tests/unit/FrameBuilderTests.cpp
index 0ed70a0..bded50a 100644
--- a/libs/hwui/tests/unit/OpReordererTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -18,8 +18,8 @@
#include <BakedOpState.h>
#include <DeferredLayerUpdater.h>
+#include <FrameBuilder.h>
#include <LayerUpdateQueue.h>
-#include <OpReorderer.h>
#include <RecordedOp.h>
#include <RecordingCanvas.h>
#include <tests/common/TestUtils.h>
@@ -113,7 +113,7 @@
class FailRenderer : public TestRendererBase {};
-TEST(OpReorderer, simple) {
+TEST(FrameBuilder, simple) {
class SimpleTestRenderer : public TestRendererBase {
public:
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
@@ -138,14 +138,14 @@
canvas.drawRect(0, 0, 100, 200, SkPaint());
canvas.drawBitmap(bitmap, 10, 10, nullptr);
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
createSyncedNodeList(node), sLightCenter);
SimpleTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end
}
-TEST(OpReorderer, simpleStroke) {
+TEST(FrameBuilder, simpleStroke) {
class SimpleStrokeTestRenderer : public TestRendererBase {
public:
void onPointsOp(const PointsOp& op, const BakedOpState& state) override {
@@ -164,14 +164,14 @@
strokedPaint.setStrokeWidth(10);
canvas.drawPoint(50, 50, strokedPaint);
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
createSyncedNodeList(node), sLightCenter);
SimpleStrokeTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex());
}
-TEST(OpReorderer, simpleRejection) {
+TEST(FrameBuilder, simpleRejection) {
auto node = TestUtils::createNode(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
@@ -179,14 +179,14 @@
canvas.drawRect(0, 0, 400, 400, SkPaint());
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(node), sLightCenter);
FailRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
-TEST(OpReorderer, simpleBatching) {
+TEST(FrameBuilder, simpleBatching) {
const int LOOPS = 5;
class SimpleBatchingTestRenderer : public TestRendererBase {
public:
@@ -214,15 +214,15 @@
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(node), sLightCenter);
SimpleBatchingTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2 * LOOPS, renderer.getIndex())
<< "Expect number of ops = 2 * loop count";
}
-TEST(OpReorderer, clippedMerging) {
+TEST(FrameBuilder, clippedMerging) {
class ClippedMergingTestRenderer : public TestRendererBase {
public:
void onMergedBitmapOps(const MergedBakedOpList& opList) override {
@@ -255,14 +255,14 @@
canvas.drawBitmap(bitmap, 40, 70, nullptr);
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
createSyncedNodeList(node), sLightCenter);
ClippedMergingTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
-TEST(OpReorderer, textMerging) {
+TEST(FrameBuilder, textMerging) {
class TextMergingTestRenderer : public TestRendererBase {
public:
void onMergedTextOps(const MergedBakedOpList& opList) override {
@@ -283,14 +283,14 @@
TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
createSyncedNodeList(node), sLightCenter);
TextMergingTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops";
}
-TEST(OpReorderer, textStrikethrough) {
+TEST(FrameBuilder, textStrikethrough) {
const int LOOPS = 5;
class TextStrikethroughTestRenderer : public TestRendererBase {
public:
@@ -314,15 +314,15 @@
TestUtils::drawTextToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
}
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000,
createSyncedNodeList(node), sLightCenter);
TextStrikethroughTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2 * LOOPS, renderer.getIndex())
<< "Expect number of ops = 2 * loop count";
}
-RENDERTHREAD_TEST(OpReorderer, textureLayer) {
+RENDERTHREAD_TEST(FrameBuilder, textureLayer) {
class TextureLayerTestRenderer : public TestRendererBase {
public:
void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override {
@@ -348,14 +348,14 @@
canvas.drawLayer(layerUpdater.get());
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(node), sLightCenter);
TextureLayerTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex());
}
-TEST(OpReorderer, renderNode) {
+TEST(FrameBuilder, renderNode) {
class RenderNodeTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
@@ -393,13 +393,13 @@
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(parent), sLightCenter);
RenderNodeTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
-TEST(OpReorderer, clipped) {
+TEST(FrameBuilder, clipped) {
class ClippedTestRenderer : public TestRendererBase {
public:
void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
@@ -416,14 +416,14 @@
canvas.drawBitmap(bitmap, 0, 0, nullptr);
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
200, 200, createSyncedNodeList(node), sLightCenter);
ClippedTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
-TEST(OpReorderer, saveLayer_simple) {
+TEST(FrameBuilder, saveLayer_simple) {
class SaveLayerSimpleTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
@@ -459,14 +459,14 @@
canvas.drawRect(10, 10, 190, 190, SkPaint());
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(node), sLightCenter);
SaveLayerSimpleTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
-TEST(OpReorderer, saveLayer_nested) {
+TEST(FrameBuilder, saveLayer_nested) {
/* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as:
* - startTemporaryLayer2, rect2 endLayer2
* - startTemporaryLayer1, rect1, drawLayer2, endLayer1
@@ -531,14 +531,14 @@
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800,
createSyncedNodeList(node), sLightCenter);
SaveLayerNestedTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex());
}
-TEST(OpReorderer, saveLayer_contentRejection) {
+TEST(FrameBuilder, saveLayer_contentRejection) {
auto node = TestUtils::createNode(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
@@ -551,21 +551,21 @@
canvas.restore();
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(node), sLightCenter);
FailRenderer renderer;
// should see no ops, even within the layer, since the layer should be rejected
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
-TEST(OpReorderer, saveLayerUnclipped_simple) {
+TEST(FrameBuilder, saveLayerUnclipped_simple) {
class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase {
public:
void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(0, mIndex++);
EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
- EXPECT_EQ(nullptr, state.computedState.clipState);
+ EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState);
EXPECT_TRUE(state.computedState.transform.isIdentity());
}
void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
@@ -583,7 +583,7 @@
void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(3, mIndex++);
EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
- EXPECT_EQ(nullptr, state.computedState.clipState);
+ EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState);
EXPECT_TRUE(state.computedState.transform.isIdentity());
}
};
@@ -594,14 +594,14 @@
canvas.drawRect(0, 0, 200, 200, SkPaint());
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(node), sLightCenter);
SaveLayerUnclippedSimpleTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
-TEST(OpReorderer, saveLayerUnclipped_mergedClears) {
+TEST(FrameBuilder, saveLayerUnclipped_mergedClears) {
class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase {
public:
void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
@@ -648,10 +648,10 @@
canvas.drawRect(0, 0, 100, 100, SkPaint());
canvas.restoreToCount(restoreTo);
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(node), sLightCenter);
SaveLayerUnclippedMergedClearsTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex())
<< "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect.";
}
@@ -660,7 +660,7 @@
* - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer
* - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe
*/
-TEST(OpReorderer, saveLayerUnclipped_complex) {
+TEST(FrameBuilder, saveLayerUnclipped_complex) {
class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
@@ -710,14 +710,14 @@
canvas.restore();
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600,
createSyncedNodeList(node), sLightCenter);
SaveLayerUnclippedComplexTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(12, renderer.getIndex());
}
-RENDERTHREAD_TEST(OpReorderer, hwLayer_simple) {
+RENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) {
class HwLayerSimpleTestRenderer : public TestRendererBase {
public:
void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
@@ -768,17 +768,17 @@
LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
- OpReorderer reorderer(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
syncedNodeList, sLightCenter);
HwLayerSimpleTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(6, renderer.getIndex());
// clean up layer pointer, so we can safely destruct RenderNode
*layerHandle = nullptr;
}
-RENDERTHREAD_TEST(OpReorderer, hwLayer_complex) {
+RENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) {
/* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as:
* - startRepaintLayer(child), rect(grey), endLayer
* - startTemporaryLayer, drawLayer(child), endLayer
@@ -869,10 +869,10 @@
layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100));
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
- OpReorderer reorderer(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
syncedList, sLightCenter);
HwLayerComplexTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(13, renderer.getIndex());
// clean up layer pointers, so we can safely destruct RenderNodes
@@ -894,7 +894,7 @@
node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z);
canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
}
-TEST(OpReorderer, zReorder) {
+TEST(FrameBuilder, zReorder) {
class ZReorderTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
@@ -918,14 +918,14 @@
drawOrderedRect(&canvas, 8);
drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
createSyncedNodeList(parent), sLightCenter);
ZReorderTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex());
};
-TEST(OpReorderer, projectionReorder) {
+TEST(FrameBuilder, projectionReorder) {
static const int scrollX = 5;
static const int scrollY = 10;
class ProjectionReorderTestRenderer : public TestRendererBase {
@@ -1001,10 +1001,10 @@
canvas.restore();
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
createSyncedNodeList(parent), sLightCenter);
ProjectionReorderTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(3, renderer.getIndex());
}
@@ -1020,7 +1020,7 @@
});
}
-TEST(OpReorderer, shadow) {
+TEST(FrameBuilder, shadow) {
class ShadowTestRenderer : public TestRendererBase {
public:
void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
@@ -1044,14 +1044,14 @@
canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(parent), sLightCenter);
ShadowTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex());
}
-TEST(OpReorderer, shadowSaveLayer) {
+TEST(FrameBuilder, shadowSaveLayer) {
class ShadowSaveLayerTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
@@ -1085,14 +1085,14 @@
canvas.restoreToCount(count);
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(parent), (Vector3) { 100, 100, 100 });
ShadowSaveLayerTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(5, renderer.getIndex());
}
-RENDERTHREAD_TEST(OpReorderer, shadowHwLayer) {
+RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) {
class ShadowHwLayerTestRenderer : public TestRendererBase {
public:
void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
@@ -1135,17 +1135,17 @@
auto syncedList = createSyncedNodeList(parent);
LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
- OpReorderer reorderer(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
syncedList, (Vector3) { 100, 100, 100 });
ShadowHwLayerTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(5, renderer.getIndex());
// clean up layer pointer, so we can safely destruct RenderNode
*layerHandle = nullptr;
}
-TEST(OpReorderer, shadowLayering) {
+TEST(FrameBuilder, shadowLayering) {
class ShadowLayeringTestRenderer : public TestRendererBase {
public:
void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
@@ -1164,10 +1164,10 @@
canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get());
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
createSyncedNodeList(parent), sLightCenter);
ShadowLayeringTestRenderer renderer;
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
@@ -1192,14 +1192,14 @@
canvas.drawRect(0, 0, 100, 100, paint);
});
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
createSyncedNodeList(node), sLightCenter);
PropertyTestRenderer renderer(opValidateCallback);
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op";
}
-TEST(OpReorderer, renderPropOverlappingRenderingAlpha) {
+TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) {
testProperty([](RenderProperties& properties) {
properties.setAlpha(0.5f);
properties.setHasOverlappingRendering(false);
@@ -1208,7 +1208,7 @@
});
}
-TEST(OpReorderer, renderPropClipping) {
+TEST(FrameBuilder, renderPropClipping) {
testProperty([](RenderProperties& properties) {
properties.setClipToBounds(true);
properties.setClipBounds(Rect(10, 20, 300, 400));
@@ -1218,7 +1218,7 @@
});
}
-TEST(OpReorderer, renderPropRevealClip) {
+TEST(FrameBuilder, renderPropRevealClip) {
testProperty([](RenderProperties& properties) {
properties.mutableRevealClip().set(true, 50, 50, 25);
}, [](const RectOp& op, const BakedOpState& state) {
@@ -1229,7 +1229,7 @@
});
}
-TEST(OpReorderer, renderPropOutlineClip) {
+TEST(FrameBuilder, renderPropOutlineClip) {
testProperty([](RenderProperties& properties) {
properties.mutableOutline().setShouldClip(true);
properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
@@ -1241,7 +1241,7 @@
});
}
-TEST(OpReorderer, renderPropTransform) {
+TEST(FrameBuilder, renderPropTransform) {
testProperty([](RenderProperties& properties) {
properties.setLeftTopRightBottom(10, 10, 110, 110);
@@ -1334,15 +1334,15 @@
});
auto nodes = createSyncedNodeList(node); // sync before querying height
- OpReorderer reorderer(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes, sLightCenter);
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes, sLightCenter);
SaveLayerAlphaClipTestRenderer renderer(outObservedData);
- reorderer.replayBakedOps<TestDispatcher>(renderer);
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
// assert, since output won't be valid if we haven't seen a save layer triggered
ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
}
-TEST(OpReorderer, renderPropSaveLayerAlphaClipBig) {
+TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
SaveLayerAlphaData observedData;
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
properties.setTranslationX(10); // offset rendering content
@@ -1358,7 +1358,7 @@
<< "expect content to be translated as part of being clipped";
}
-TEST(OpReorderer, renderPropSaveLayerAlphaRotate) {
+TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
SaveLayerAlphaData observedData;
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
// Translate and rotate the view so that the only visible part is the top left corner of
@@ -1377,7 +1377,7 @@
EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
}
-TEST(OpReorderer, renderPropSaveLayerAlphaScale) {
+TEST(FrameBuilder, renderPropSaveLayerAlphaScale) {
SaveLayerAlphaData observedData;
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
properties.setPivotX(0);
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 2187654..e96e9ba 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -15,11 +15,11 @@
*/
#include <gtest/gtest.h>
+#include <Rect.h>
#include <renderstate/OffscreenBufferPool.h>
#include <tests/common/TestUtils.h>
-using namespace android;
using namespace android::uirenderer;
TEST(OffscreenBuffer, computeIdealDimension) {
@@ -43,6 +43,18 @@
});
}
+TEST(OffscreenBuffer, getTextureCoordinates) {
+ TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
+ OffscreenBuffer layerAligned(thread.renderState(), Caches::getInstance(), 256u, 256u);
+ EXPECT_EQ(Rect(0, 1, 1, 0),
+ layerAligned.getTextureCoordinates());
+
+ OffscreenBuffer layerUnaligned(thread.renderState(), Caches::getInstance(), 200u, 225u);
+ EXPECT_EQ(Rect(0, 225.0f / 256.0f, 200.0f / 256.0f, 0),
+ layerUnaligned.getTextureCoordinates());
+ });
+}
+
TEST(OffscreenBufferPool, construct) {
TestUtils::runOnRenderThread([] (renderthread::RenderThread& thread) {
OffscreenBufferPool pool;
@@ -51,7 +63,6 @@
EXPECT_EQ((uint32_t) Properties::layerPoolSize, pool.getMaxSize())
<< "pool must read size from Properties";
});
-
}
TEST(OffscreenBufferPool, getPutClear) {
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 795ac30..ff098c8 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -33,14 +33,6 @@
}
}
-#define EXPECT_CLIP_RECT(expRect, clipStatePtr) \
- EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped"; \
- if ((clipStatePtr)->mode == ClipMode::Rectangle) { \
- EXPECT_EQ((expRect), reinterpret_cast<const ClipRect*>(clipStatePtr)->rect); \
- } else { \
- ADD_FAILURE() << "ClipState not a rect"; \
- }
-
TEST(RecordingCanvas, emptyPlayback) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c658675..ea1690f 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -51,6 +51,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
/**
* AudioManager provides access to volume and ringer mode control.
@@ -176,6 +177,16 @@
"android.media.MASTER_MUTE_CHANGED_ACTION";
/**
+ * @hide Broadcast intent when the master mono state changes.
+ * Includes the new mono state
+ *
+ * @see #EXTRA_MASTER_MONO
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String MASTER_MONO_CHANGED_ACTION =
+ "android.media.MASTER_MONO_CHANGED_ACTION";
+
+ /**
* The new vibrate setting for a particular type.
*
* @see #VIBRATE_SETTING_CHANGED_ACTION
@@ -254,6 +265,13 @@
"android.media.EXTRA_STREAM_VOLUME_MUTED";
/**
+ * @hide The new master mono state for the master mono changed intent.
+ * Value is boolean
+ */
+ public static final String EXTRA_MASTER_MONO =
+ "android.media.EXTRA_MASTER_MONO";
+
+ /**
* Broadcast Action: Wired Headset plugged in or unplugged.
*
* You <em>cannot</em> receive this through components declared
@@ -880,6 +898,17 @@
}
}
+ /** @hide */
+ public void setMasterMono(boolean mono) {
+ IAudioService service = getService();
+ try {
+ service.setMasterMono(mono, getContext().getOpPackageName(),
+ UserHandle.getCallingUserId());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in setMasterMono", e);
+ }
+ }
+
/**
* Returns the current ringtone mode.
*
@@ -1142,6 +1171,21 @@
}
/**
+ * get master mono state.
+ *
+ * @hide
+ */
+ public boolean isMasterMono() {
+ IAudioService service = getService();
+ try {
+ return service.isMasterMono();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in isMasterMono", e);
+ return false;
+ }
+ }
+
+ /**
* forces the stream controlled by hard volume keys
* specifying streamType == -1 releases control to the
* logic.
@@ -2115,36 +2159,73 @@
}
/**
- * Handler for audio focus events coming from the audio service.
+ * Handler for events (audio focus change, recording config change) coming from the
+ * audio service.
*/
- private final FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate =
- new FocusEventHandlerDelegate();
+ private final ServiceEventHandlerDelegate mServiceEventHandlerDelegate =
+ new ServiceEventHandlerDelegate();
/**
- * Helper class to handle the forwarding of audio focus events to the appropriate listener
+ * Event types
*/
- private class FocusEventHandlerDelegate {
+ private final static int MSSG_FOCUS_CHANGE = 0;
+ private final static int MSSG_RECORDING_CONFIG_CHANGE = 1;
+
+ /**
+ * Helper class to handle the forwarding of audio service events to the appropriate listener
+ */
+ private class ServiceEventHandlerDelegate {
private final Handler mHandler;
- FocusEventHandlerDelegate() {
+ ServiceEventHandlerDelegate() {
Looper looper;
if ((looper = Looper.myLooper()) == null) {
looper = Looper.getMainLooper();
}
if (looper != null) {
- // implement the event handler delegate to receive audio focus events
+ // implement the event handler delegate to receive events from audio service
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
- OnAudioFocusChangeListener listener = null;
- synchronized(mFocusListenerLock) {
- listener = findFocusListener((String)msg.obj);
- }
- if (listener != null) {
- Log.d(TAG, "AudioManager dispatching onAudioFocusChange("
- + msg.what + ") for " + msg.obj);
- listener.onAudioFocusChange(msg.what);
+ switch (msg.what) {
+ case MSSG_FOCUS_CHANGE:
+ OnAudioFocusChangeListener listener = null;
+ synchronized(mFocusListenerLock) {
+ listener = findFocusListener((String)msg.obj);
+ }
+ if (listener != null) {
+ Log.d(TAG, "AudioManager dispatching onAudioFocusChange("
+ + msg.what + ") for " + msg.obj);
+ listener.onAudioFocusChange(msg.arg1);
+ }
+ break;
+ case MSSG_RECORDING_CONFIG_CHANGE:
+ // optimizing for the case of a single callback
+ AudioRecordingCallback singleCallback = null;
+ ArrayList<AudioRecordingCallback> multipleCallbacks = null;
+ synchronized(mRecordCallbackLock) {
+ if ((mRecordCallbackList != null)
+ && (mRecordCallbackList.size() != 0)) {
+ if (mRecordCallbackList.size() == 1) {
+ singleCallback = mRecordCallbackList.get(0);
+ } else {
+ multipleCallbacks =
+ new ArrayList<AudioRecordingCallback>(
+ mRecordCallbackList);
+ }
+ }
+ }
+ if (singleCallback != null) {
+ singleCallback.onRecordConfigChanged();
+ } else if (multipleCallbacks != null) {
+ for (int i=0 ; i < multipleCallbacks.size() ; i++) {
+ multipleCallbacks.get(i).onRecordConfigChanged();
+ }
+ }
+ break;
+ default:
+ Log.e(TAG, "Unknown event " + msg.what);
}
}
};
@@ -2161,8 +2242,9 @@
private final IAudioFocusDispatcher mAudioFocusDispatcher = new IAudioFocusDispatcher.Stub() {
public void dispatchAudioFocusChange(int focusChange, String id) {
- Message m = mAudioFocusEventHandlerDelegate.getHandler().obtainMessage(focusChange, id);
- mAudioFocusEventHandlerDelegate.getHandler().sendMessage(m);
+ final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage(
+ MSSG_FOCUS_CHANGE/*what*/, focusChange/*arg1*/, 0/*arg2 ignored*/, id/*obj*/);
+ mServiceEventHandlerDelegate.getHandler().sendMessage(m);
}
};
@@ -2659,6 +2741,8 @@
}
+ //====================================================================
+ // Audio policy
/**
* @hide
* Register the given {@link AudioPolicy}.
@@ -2711,6 +2795,131 @@
}
+ //====================================================================
+ // Recording configuration
+ /**
+ * @hide
+ * candidate for public API
+ */
+ public static abstract class AudioRecordingCallback {
+ /**
+ * @hide
+ * candidate for public API
+ */
+ public void onRecordConfigChanged() {}
+ }
+
+ /**
+ * @hide
+ * candidate for public API
+ * @param non-null callback
+ */
+ public void registerAudioRecordingCallback(@NonNull AudioRecordingCallback cb) {
+ if (cb == null) {
+ throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument");
+ }
+ synchronized(mRecordCallbackLock) {
+ // lazy initialization of the list of recording callbacks
+ if (mRecordCallbackList == null) {
+ mRecordCallbackList = new ArrayList<AudioRecordingCallback>();
+ }
+ final int oldCbCount = mRecordCallbackList.size();
+ if (!mRecordCallbackList.contains(cb)) {
+ mRecordCallbackList.add(cb);
+ final int newCbCount = mRecordCallbackList.size();
+ if ((oldCbCount == 0) && (newCbCount > 0)) {
+ // register binder for callbacks
+ final IAudioService service = getService();
+ try {
+ service.registerRecordingCallback(mRecCb);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in registerRecordingCallback", e);
+ }
+ }
+ } else {
+ Log.w(TAG, "attempt to call registerAudioRecordingCallback() on a previously"
+ + "registered callback");
+ }
+ }
+ }
+
+ /**
+ * @hide
+ * candidate for public API
+ * @param non-null callback
+ */
+ public void unregisterAudioRecordingCallback(@NonNull AudioRecordingCallback cb) {
+ if (cb == null) {
+ throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument");
+ }
+ synchronized(mRecordCallbackLock) {
+ if (mRecordCallbackList == null) {
+ return;
+ }
+ final int oldCbCount = mRecordCallbackList.size();
+ if (mRecordCallbackList.remove(cb)) {
+ final int newCbCount = mRecordCallbackList.size();
+ if ((oldCbCount > 0) && (newCbCount == 0)) {
+ // unregister binder for callbacks
+ final IAudioService service = getService();
+ try {
+ service.unregisterRecordingCallback(mRecCb);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in unregisterRecordingCallback", e);
+ }
+ }
+ } else {
+ Log.w(TAG, "attempt to call unregisterAudioRecordingCallback() on a callback"
+ + " already unregistered or never registered");
+ }
+ }
+ }
+
+ /**
+ * @hide
+ * candidate for public API
+ * @return a non-null array of recording configurations. An array of length 0 indicates there is
+ * no recording active when queried.
+ */
+ public @NonNull AudioRecordConfiguration[] getActiveRecordConfigurations() {
+ final IAudioService service = getService();
+ try {
+ return service.getActiveRecordConfigurations();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to retrieve active record configurations", e);
+ return null;
+ }
+ }
+
+ /**
+ * constants for the recording events, to keep in sync
+ * with frameworks/av/include/media/AudioPolicy.h
+ */
+ /** @hide */
+ public final static int RECORD_CONFIG_EVENT_START = 1;
+ /** @hide */
+ public final static int RECORD_CONFIG_EVENT_STOP = 0;
+
+ /**
+ * All operations on this list are sync'd on mRecordCallbackLock.
+ * List is lazy-initialized in {@link #registerAudioRecordingCallback(AudioRecordingCallback)}.
+ * List can be null.
+ */
+ private List<AudioRecordingCallback> mRecordCallbackList;
+ private final Object mRecordCallbackLock = new Object();
+
+ private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() {
+
+ public void dispatchRecordingConfigChange() {
+ final Message m = mServiceEventHandlerDelegate.getHandler().obtainMessage(
+ MSSG_RECORDING_CONFIG_CHANGE/*what*/);
+ mServiceEventHandlerDelegate.getHandler().sendMessage(m);
+ }
+
+ };
+
+ //=====================================================================
+
/**
* @hide
* Reload audio settings. This method is called by Settings backup
diff --git a/media/java/android/media/AudioRecordConfiguration.aidl b/media/java/android/media/AudioRecordConfiguration.aidl
new file mode 100644
index 0000000..afe912b
--- /dev/null
+++ b/media/java/android/media/AudioRecordConfiguration.aidl
@@ -0,0 +1,18 @@
+/* Copyright 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.media;
+
+parcelable AudioRecordConfiguration;
diff --git a/media/java/android/media/AudioRecordConfiguration.java b/media/java/android/media/AudioRecordConfiguration.java
new file mode 100644
index 0000000..aefe692
--- /dev/null
+++ b/media/java/android/media/AudioRecordConfiguration.java
@@ -0,0 +1,102 @@
+/*
+ * 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.media;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * @hide
+ * Candidate for public API, see AudioManager.getActiveRecordConfiguration()
+ *
+ */
+public class AudioRecordConfiguration implements Parcelable {
+
+ private final int mSessionId;
+
+ private final int mClientSource;
+
+ /**
+ * @hide
+ */
+ public AudioRecordConfiguration(int session, int source) {
+ mSessionId = session;
+ mClientSource = source;
+ }
+
+ /**
+ * @return one of AudioSource.MIC, AudioSource.VOICE_UPLINK,
+ * AudioSource.VOICE_DOWNLINK, AudioSource.VOICE_CALL,
+ * AudioSource.CAMCORDER, AudioSource.VOICE_RECOGNITION,
+ * AudioSource.VOICE_COMMUNICATION.
+ */
+ public int getClientAudioSource() { return mClientSource; }
+
+ /**
+ * @return the session number of the recorder.
+ */
+ public int getAudioSessionId() { return mSessionId; }
+
+
+ public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR
+ = new Parcelable.Creator<AudioRecordConfiguration>() {
+ /**
+ * Rebuilds an AudioRecordConfiguration previously stored with writeToParcel().
+ * @param p Parcel object to read the AudioRecordConfiguration from
+ * @return a new AudioRecordConfiguration created from the data in the parcel
+ */
+ public AudioRecordConfiguration createFromParcel(Parcel p) {
+ return new AudioRecordConfiguration(p);
+ }
+ public AudioRecordConfiguration[] newArray(int size) {
+ return new AudioRecordConfiguration[size];
+ }
+ };
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSessionId, mClientSource);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSessionId);
+ dest.writeInt(mClientSource);
+ }
+
+ private AudioRecordConfiguration(Parcel in) {
+ mSessionId = in.readInt();
+ mClientSource = in.readInt();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || !(o instanceof AudioRecordConfiguration)) return false;
+
+ final AudioRecordConfiguration that = (AudioRecordConfiguration) o;
+ return ((mSessionId == that.mSessionId)
+ && (mClientSource == that.mClientSource));
+ }
+}
\ No newline at end of file
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index c59d1c7..aa0d78d 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -227,7 +227,7 @@
}
/**
- * Handles events for the audio policy manager about dynamic audio policies
+ * Handles events from the audio policy manager about dynamic audio policies
* @see android.media.audiopolicy.AudioPolicy
*/
public interface DynamicPolicyCallback
@@ -267,6 +267,33 @@
}
}
+ /**
+ * Handles events from the audio policy manager about recording events
+ * @see android.media.AudioManager.AudioRecordingCallback
+ */
+ public interface AudioRecordingCallback
+ {
+ void onRecordingConfigurationChanged(int event, int session, int source);
+ }
+
+ private static AudioRecordingCallback sRecordingCallback;
+
+ public static void setRecordingCallback(AudioRecordingCallback cb) {
+ synchronized (AudioSystem.class) {
+ sRecordingCallback = cb;
+ native_register_recording_callback();
+ }
+ }
+
+ private static void recordingCallbackFromNative(int event, int session, int source) {
+ AudioRecordingCallback cb = null;
+ synchronized (AudioSystem.class) {
+ cb = sRecordingCallback;
+ }
+ if (cb != null) {
+ cb.onRecordingConfigurationChanged(event, session, source);
+ }
+ }
/*
* Error codes used by public APIs (AudioTrack, AudioRecord, AudioManager ...)
@@ -624,6 +651,11 @@
public static native boolean getMasterMute();
public static native int getDevicesForStream(int stream);
+ /** @hide returns true if master mono is enabled. */
+ public static native boolean getMasterMono();
+ /** @hide enables or disables the master mono mode. */
+ public static native int setMasterMono(boolean mono);
+
// helpers for android.media.AudioManager.getProperty(), see description there for meaning
public static native int getPrimaryOutputSamplingRate();
public static native int getPrimaryOutputFrameCount();
@@ -641,6 +673,8 @@
// declare this instance as having a dynamic policy callback handler
private static native final void native_register_dynamic_policy_callback();
+ // declare this instance as having a recording configuration update callback handler
+ private static native final void native_register_recording_callback();
// must be kept in sync with value in include/system/audio.h
public static final int AUDIO_HW_SYNC_INVALID = 0;
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 693a519..abe92c7 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -20,9 +20,11 @@
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.media.AudioAttributes;
+import android.media.AudioRecordConfiguration;
import android.media.AudioRoutesInfo;
import android.media.IAudioFocusDispatcher;
import android.media.IAudioRoutesObserver;
+import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
import android.media.IVolumeController;
import android.media.Rating;
@@ -52,6 +54,10 @@
void setMasterMute(boolean mute, int flags, String callingPackage, int userId);
+ boolean isMasterMono();
+
+ void setMasterMono(boolean mute, String callingPackage, int userId);
+
int getStreamVolume(int streamType);
int getStreamMinVolume(int streamType);
@@ -157,4 +163,10 @@
int setFocusPropertiesForPolicy(int duckingBehavior, in IAudioPolicyCallback pcb);
void setVolumePolicy(in VolumePolicy policy);
+
+ void registerRecordingCallback(in IRecordingConfigDispatcher rcdb);
+
+ oneway void unregisterRecordingCallback(in IRecordingConfigDispatcher rcdb);
+
+ AudioRecordConfiguration[] getActiveRecordConfigurations();
}
diff --git a/media/java/android/media/IMediaResourceMonitor.aidl b/media/java/android/media/IMediaResourceMonitor.aidl
new file mode 100644
index 0000000..7b4bc39
--- /dev/null
+++ b/media/java/android/media/IMediaResourceMonitor.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 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.media;
+
+/** {@hide} */
+interface IMediaResourceMonitor
+{
+ oneway void notifyResourceGranted(in int pid, String type, String subType, long value);
+}
+
diff --git a/media/java/android/media/IRecordingConfigDispatcher.aidl b/media/java/android/media/IRecordingConfigDispatcher.aidl
new file mode 100644
index 0000000..a5eb8b9f
--- /dev/null
+++ b/media/java/android/media/IRecordingConfigDispatcher.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.media;
+
+/**
+ * AIDL for the RecordingActivity monitor in AudioService to signal audio recording updates.
+ *
+ * {@hide}
+ */
+oneway interface IRecordingConfigDispatcher {
+
+ void dispatchRecordingConfigChange();
+
+}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 478fd99..f1f8437 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2175,8 +2175,6 @@
int offset, int size, long presentationTimeUs, int flags)
throws CryptoException;
- // The following mode constants MUST stay in sync with their equivalents
- // in media/hardware/CryptoAPI.h !
public static final int CRYPTO_MODE_UNENCRYPTED = 0;
public static final int CRYPTO_MODE_AES_CTR = 1;
public static final int CRYPTO_MODE_AES_CBC = 2;
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 9bcb5e3..0fba992 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1735,8 +1735,7 @@
CodecProfileLevel[] profileLevels = mParent.profileLevels;
String mime = mParent.getMimeType();
- if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC) ||
- mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_DOLBY_AVC)) {
+ if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) {
maxBlocks = 99;
maxBlocksPerSecond = 1485;
maxBps = 64000;
@@ -2090,8 +2089,7 @@
applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
1 /* widthAlignment */, 1 /* heightAlignment */);
- } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC) ||
- mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_DOLBY_HEVC)) {
+ } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
maxBlocks = 36864;
maxBlocksPerSecond = maxBlocks * 15;
maxBps = 128000;
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index a102e51..b2fa0ac 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -92,8 +92,6 @@
public static final String MIMETYPE_VIDEO_H263 = "video/3gpp";
public static final String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
public static final String MIMETYPE_VIDEO_RAW = "video/raw";
- public static final String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
- public static final String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
public static final String MIMETYPE_AUDIO_AMR_NB = "audio/3gpp";
public static final String MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb";
diff --git a/media/java/android/mtp/MtpEvent.java b/media/java/android/mtp/MtpEvent.java
index 6ec16db..dc89a56 100644
--- a/media/java/android/mtp/MtpEvent.java
+++ b/media/java/android/mtp/MtpEvent.java
@@ -18,15 +18,152 @@
/**
* This class encapsulates information about a MTP event.
- * Event constants are defined by the USB-IF MTP specification.
+ * This corresponds to the events described in appendix G of the MTP specification.
*/
public class MtpEvent {
private int mEventCode = MtpConstants.EVENT_UNDEFINED;
+ // Parameters for event. The interpretation of event parameters depends upon mEventCode.
+ private int mParameter1;
+ private int mParameter2;
+ private int mParameter3;
+
/**
* Returns event code of MTP event.
* See the USB-IF MTP specification for the details of event constants.
* @return event code
*/
public int getEventCode() { return mEventCode; }
+
+ /**
+ * Obtains the first event parameter.
+ */
+ public int getParameter1() { return mParameter1; }
+
+ /**
+ * Obtains the second event parameter.
+ */
+ public int getParameter2() { return mParameter2; }
+
+ /**
+ * Obtains the third event parameter.
+ */
+ public int getParameter3() { return mParameter3; }
+
+ /**
+ * Obtains objectHandle event parameter.
+ *
+ * @see MtpConstants#EVENT_OBJECT_ADDED
+ * @see MtpConstants#EVENT_OBJECT_REMOVED
+ * @see MtpConstants#EVENT_OBJECT_INFO_CHANGED
+ * @see MtpConstants#EVENT_REQUEST_OBJECT_TRANSFER
+ * @see MtpConstants#EVENT_OBJECT_PROP_CHANGED
+ * @see MtpConstants#EVENT_OBJECT_REFERENCES_CHANGED
+ */
+ public int getObjectHandle() {
+ switch (mEventCode) {
+ case MtpConstants.EVENT_OBJECT_ADDED:
+ return mParameter1;
+ case MtpConstants.EVENT_OBJECT_REMOVED:
+ return mParameter1;
+ case MtpConstants.EVENT_OBJECT_INFO_CHANGED:
+ return mParameter1;
+ case MtpConstants.EVENT_REQUEST_OBJECT_TRANSFER:
+ return mParameter1;
+ case MtpConstants.EVENT_OBJECT_PROP_CHANGED:
+ return mParameter1;
+ case MtpConstants.EVENT_OBJECT_REFERENCES_CHANGED:
+ return mParameter1;
+ default:
+ throw new IllegalParameterAccess("objectHandle", mEventCode);
+ }
+ }
+
+ /**
+ * Obtains storageID event parameter.
+ *
+ * @see MtpConstants#EVENT_STORE_ADDED
+ * @see MtpConstants#EVENT_STORE_REMOVED
+ * @see MtpConstants#EVENT_STORE_FULL
+ * @see MtpConstants#EVENT_STORAGE_INFO_CHANGED
+ */
+ public int getStorageId() {
+ switch (mEventCode) {
+ case MtpConstants.EVENT_STORE_ADDED:
+ return mParameter1;
+ case MtpConstants.EVENT_STORE_REMOVED:
+ return mParameter1;
+ case MtpConstants.EVENT_STORE_FULL:
+ return mParameter1;
+ case MtpConstants.EVENT_STORAGE_INFO_CHANGED:
+ return mParameter1;
+ default:
+ throw new IllegalParameterAccess("storageID", mEventCode);
+ }
+ }
+
+ /**
+ * Obtains devicePropCode event parameter.
+ *
+ * @see MtpConstants#EVENT_DEVICE_PROP_CHANGED
+ */
+ public int getDevicePropCode() {
+ switch (mEventCode) {
+ case MtpConstants.EVENT_DEVICE_PROP_CHANGED:
+ return mParameter1;
+ default:
+ throw new IllegalParameterAccess("devicePropCode", mEventCode);
+ }
+ }
+
+ /**
+ * Obtains transactionID event parameter.
+ *
+ * @see MtpConstants#EVENT_CAPTURE_COMPLETE
+ */
+ public int getTransactionId() {
+ switch (mEventCode) {
+ case MtpConstants.EVENT_CAPTURE_COMPLETE:
+ return mParameter1;
+ default:
+ throw new IllegalParameterAccess("transactionID", mEventCode);
+ }
+ }
+
+ /**
+ * Obtains objectPropCode event parameter.
+ *
+ * @see MtpConstants#EVENT_OBJECT_PROP_CHANGED
+ * @see MtpConstants#EVENT_OBJECT_PROP_DESC_CHANGED
+ */
+ public int getObjectPropCode() {
+ switch (mEventCode) {
+ case MtpConstants.EVENT_OBJECT_PROP_CHANGED:
+ return mParameter2;
+ case MtpConstants.EVENT_OBJECT_PROP_DESC_CHANGED:
+ return mParameter1;
+ default:
+ throw new IllegalParameterAccess("objectPropCode", mEventCode);
+ }
+ }
+
+ /**
+ * Obtains objectFormatCode event parameter.
+ *
+ * @see MtpConstants#EVENT_OBJECT_PROP_DESC_CHANGED
+ */
+ public int getObjectFormatCode() {
+ switch (mEventCode) {
+ case MtpConstants.EVENT_OBJECT_PROP_DESC_CHANGED:
+ return mParameter2;
+ default:
+ throw new IllegalParameterAccess("objectFormatCode", mEventCode);
+ }
+ }
+
+ private static class IllegalParameterAccess extends UnsupportedOperationException {
+ public IllegalParameterAccess(String propertyName, int eventCode) {
+ super("Cannot obtain " + propertyName + " for the event: " + eventCode + ".");
+ }
+ }
}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 49b579c..2004a3a 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -85,6 +85,13 @@
jmethodID setNativeObjectLocked;
} gPersistentSurfaceClassInfo;
+static struct {
+ jint Unencrypted;
+ jint AesCtr;
+ jint AesCbc;
+} gCryptoModes;
+
+
struct fields_t {
jfieldID context;
jmethodID postEventFromNativeID;
@@ -94,6 +101,9 @@
jfieldID cryptoInfoKeyID;
jfieldID cryptoInfoIVID;
jfieldID cryptoInfoModeID;
+ jfieldID cryptoInfoPatternID;
+ jfieldID patternEncryptBlocksID;
+ jfieldID patternSkipBlocksID;
};
static fields_t gFields;
@@ -325,11 +335,12 @@
const uint8_t key[16],
const uint8_t iv[16],
CryptoPlugin::Mode mode,
+ const CryptoPlugin::Pattern &pattern,
int64_t presentationTimeUs,
uint32_t flags,
AString *errorDetailMsg) {
return mCodec->queueSecureInputBuffer(
- index, offset, subSamples, numSubSamples, key, iv, mode,
+ index, offset, subSamples, numSubSamples, key, iv, mode, pattern,
presentationTimeUs, flags, errorDetailMsg);
}
@@ -1275,7 +1286,26 @@
jbyteArray ivObj =
(jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
- jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
+ jint jmode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
+ enum CryptoPlugin::Mode mode;
+ if (jmode == gCryptoModes.Unencrypted) {
+ mode = CryptoPlugin::kMode_Unencrypted;
+ } else if (jmode == gCryptoModes.AesCtr) {
+ mode = CryptoPlugin::kMode_AES_CTR;
+ } else if (jmode == gCryptoModes.AesCbc) {
+ mode = CryptoPlugin::kMode_AES_CBC;
+ } else {
+ throwExceptionAsNecessary(env, INVALID_OPERATION);
+ return;
+ }
+
+ jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
+
+ CryptoPlugin::Pattern pattern;
+ if (patternObj != NULL) {
+ pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
+ pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
+ }
status_t err = OK;
@@ -1360,7 +1390,8 @@
index, offset,
subSamples, numSubSamples,
(const uint8_t *)key, (const uint8_t *)iv,
- (CryptoPlugin::Mode)mode,
+ mode,
+ pattern,
timestampUs,
flags,
&errorDetailMsg);
@@ -1658,6 +1689,22 @@
CHECK(gFields.postEventFromNativeID != NULL);
+ jfieldID field;
+ field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_UNENCRYPTED", "I");
+ CHECK(field != NULL);
+ gCryptoModes.Unencrypted =
+ env->GetStaticIntField(clazz.get(), field);
+
+ field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CTR", "I");
+ CHECK(field != NULL);
+ gCryptoModes.AesCtr =
+ env->GetStaticIntField(clazz.get(), field);
+
+ field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CBC", "I");
+ CHECK(field != NULL);
+ gCryptoModes.AesCbc =
+ env->GetStaticIntField(clazz.get(), field);
+
clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
CHECK(clazz.get() != NULL);
@@ -1682,10 +1729,22 @@
gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
CHECK(gFields.cryptoInfoModeID != NULL);
+ gFields.cryptoInfoPatternID = env->GetFieldID(clazz.get(), "pattern",
+ "Landroid/media/MediaCodec$CryptoInfo$Pattern;");
+ CHECK(gFields.cryptoInfoPatternID != NULL);
+
+ clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo$Pattern"));
+ CHECK(clazz.get() != NULL);
+
+ gFields.patternEncryptBlocksID = env->GetFieldID(clazz.get(), "mEncryptBlocks", "I");
+ CHECK(gFields.patternEncryptBlocksID != NULL);
+
+ gFields.patternSkipBlocksID = env->GetFieldID(clazz.get(), "mSkipBlocks", "I");
+ CHECK(gFields.patternSkipBlocksID != NULL);
+
clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
CHECK(clazz.get() != NULL);
- jfieldID field;
field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
CHECK(field != NULL);
gCryptoErrorCodes.cryptoErrorNoKey =
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 6650cf9..c0c47ef 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -81,6 +81,7 @@
const uint8_t key[16],
const uint8_t iv[16],
CryptoPlugin::Mode mode,
+ const CryptoPlugin::Pattern &pattern,
int64_t presentationTimeUs,
uint32_t flags,
AString *errorDetailMsg);
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 4aa12c2..130dfe5 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -98,6 +98,9 @@
// MtpEvent fields
static jfieldID field_event_eventCode;
+static jfieldID field_event_parameter1;
+static jfieldID field_event_parameter2;
+static jfieldID field_event_parameter3;
class JavaArrayWriter {
public:
@@ -573,13 +576,17 @@
env->ThrowNew(clazz_io_exception, "");
return NULL;
}
- const int eventCode = device->reapEventRequest(seq);
+ uint32_t parameters[3];
+ const int eventCode = device->reapEventRequest(seq, ¶meters);
if (eventCode <= 0) {
env->ThrowNew(clazz_operation_canceled_exception, "");
return NULL;
}
jobject result = env->NewObject(clazz_event, constructor_event);
env->SetIntField(result, field_event_eventCode, eventCode);
+ env->SetIntField(result, field_event_parameter1, static_cast<jint>(parameters[0]));
+ env->SetIntField(result, field_event_parameter2, static_cast<jint>(parameters[1]));
+ env->SetIntField(result, field_event_parameter3, static_cast<jint>(parameters[2]));
return result;
}
@@ -832,6 +839,21 @@
ALOGE("Can't find MtpObjectInfo.mEventCode");
return -1;
}
+ field_event_parameter1 = env->GetFieldID(clazz, "mParameter1", "I");
+ if (field_event_parameter1 == NULL) {
+ ALOGE("Can't find MtpObjectInfo.mParameter1");
+ return -1;
+ }
+ field_event_parameter2 = env->GetFieldID(clazz, "mParameter2", "I");
+ if (field_event_parameter2 == NULL) {
+ ALOGE("Can't find MtpObjectInfo.mParameter2");
+ return -1;
+ }
+ field_event_parameter3 = env->GetFieldID(clazz, "mParameter3", "I");
+ if (field_event_parameter3 == NULL) {
+ ALOGE("Can't find MtpObjectInfo.mParameter3");
+ return -1;
+ }
clazz_event = (jclass)env->NewGlobalRef(clazz);
clazz = env->FindClass("android/mtp/MtpDevice");
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 359a7a97a..9c01f4f 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -161,7 +161,7 @@
* </pre>
*
*/
-public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback2 {
private final static String TAG = "GLSurfaceView";
private final static boolean LOG_ATTACH_DETACH = false;
private final static boolean LOG_THREADS = false;
@@ -542,6 +542,16 @@
}
/**
+ * This method is part of the SurfaceHolder.Callback interface, and is
+ * not normally called or subclassed by clients of GLSurfaceView.
+ */
+ @Override
+ public void surfaceRedrawNeeded(SurfaceHolder holder) {
+ mGLThread.requestRenderAndWait();
+ }
+
+
+ /**
* Inform the view that the activity is paused. The owner of this view must
* call this method when the activity is paused. Calling this method will
* pause the rendering thread.
@@ -1226,6 +1236,7 @@
mHeight = 0;
mRequestRender = true;
mRenderMode = RENDERMODE_CONTINUOUSLY;
+ mWantRenderNotification = false;
mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;
}
@@ -1271,6 +1282,8 @@
mEglHelper = new EglHelper(mGLSurfaceViewWeakRef);
mHaveEglContext = false;
mHaveEglSurface = false;
+ mWantRenderNotification = false;
+
try {
GL10 gl = null;
boolean createEglContext = false;
@@ -1278,7 +1291,6 @@
boolean createGlInterface = false;
boolean lostEglContext = false;
boolean sizeChanged = false;
- boolean wantRenderNotification = false;
boolean doRenderNotification = false;
boolean askedToReleaseEglContext = false;
int w = 0;
@@ -1383,7 +1395,7 @@
if (LOG_SURFACE) {
Log.i("GLThread", "sending render notification tid=" + getId());
}
- wantRenderNotification = false;
+ mWantRenderNotification = false;
doRenderNotification = false;
mRenderComplete = true;
sGLThreadManager.notifyAll();
@@ -1422,7 +1434,7 @@
sizeChanged = true;
w = mWidth;
h = mHeight;
- wantRenderNotification = true;
+ mWantRenderNotification = true;
if (LOG_SURFACE) {
Log.i("GLThread",
"noticing that we want render notification tid="
@@ -1562,7 +1574,7 @@
break;
}
- if (wantRenderNotification) {
+ if (mWantRenderNotification) {
doRenderNotification = true;
}
}
@@ -1611,6 +1623,23 @@
}
}
+ public void requestRenderAndWait() {
+ synchronized(sGLThreadManager) {
+ mWantRenderNotification = true;
+ mRequestRender = true;
+ mRenderComplete = false;
+ sGLThreadManager.notifyAll();
+ while (!mExited && !mPaused && mRenderComplete == false) {
+ try {
+ sGLThreadManager.wait();
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ }
+ }
+
public void surfaceCreated() {
synchronized(sGLThreadManager) {
if (LOG_THREADS) {
@@ -1766,6 +1795,7 @@
private int mHeight;
private int mRenderMode;
private boolean mRequestRender;
+ private boolean mWantRenderNotification;
private boolean mRenderComplete;
private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
private boolean mSizeChanged = true;
diff --git a/packages/BackupRestoreConfirmation/res/values-de/strings.xml b/packages/BackupRestoreConfirmation/res/values-de/strings.xml
index a2e24e7..e1f797f 100644
--- a/packages/BackupRestoreConfirmation/res/values-de/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-de/strings.xml
@@ -18,19 +18,19 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="backup_confirm_title" msgid="827563724209303345">"Vollständige Sicherung"</string>
<string name="restore_confirm_title" msgid="5469365809567486602">"Vollständige Wiederherstellung"</string>
- <string name="backup_confirm_text" msgid="1878021282758896593">"Es wurde eine vollständige Sicherung sämtlicher Daten auf einen verbundenen Desktop-Computer angefordert. Möchten Sie dies zulassen?\n\nWenn Sie die Sicherung nicht selbst angefordert haben, sollten Sie dem Vorgang nicht zustimmen."</string>
+ <string name="backup_confirm_text" msgid="1878021282758896593">"Es wurde eine vollständige Sicherung sämtlicher Daten auf einen verbundenen Desktop-Computer angefordert. Möchtest du dies zulassen?\n\nWenn du die Sicherung nicht selbst angefordert hast, solltest du dem Vorgang nicht zustimmen."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Meine Daten sichern"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"Nicht sichern"</string>
- <string name="restore_confirm_text" msgid="7499866728030461776">"Es wurde eine vollständige Wiederherstellung aller Daten von einem verbundenen Desktop-Computer angefordert. Möchten Sie dies zulassen?\n\nWenn Sie die Wiederherstellung nicht selbst angefordert haben, sollten Sie dem Vorgang nicht zustimmen. Dadurch werden alle zurzeit auf dem Gerät befindlichen Daten ersetzt!"</string>
+ <string name="restore_confirm_text" msgid="7499866728030461776">"Es wurde eine vollständige Wiederherstellung aller Daten von einem verbundenen Desktop-Computer angefordert. Möchtest du dies zulassen?\n\nWenn du die Wiederherstellung nicht selbst angefordert hast, solltest du dem Vorgang nicht zustimmen. Dadurch werden alle derzeit auf dem Gerät befindlichen Daten ersetzt!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Meine Daten wiederherstellen"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Nicht wiederherstellen"</string>
- <string name="current_password_text" msgid="8268189555578298067">"Geben Sie Ihr aktuelles Sicherungspasswort unten ein:"</string>
- <string name="device_encryption_restore_text" msgid="1570864916855208992">"Geben Sie Ihr Passwort zur Geräteverschlüsselung unten ein."</string>
- <string name="device_encryption_backup_text" msgid="5866590762672844664">"Geben Sie Ihr Passwort zur Geräteverschlüsselung unten ein. Damit wird auch das Sicherungsarchiv verschlüsselt."</string>
- <string name="backup_enc_password_text" msgid="4981585714795233099">"Geben Sie ein Passwort für die Verschlüsselung der vollständigen Sicherungsdaten ein. Wenn Sie dieses Feld leer lassen, wird Ihr aktuelles Sicherungspasswort verwendet:"</string>
- <string name="backup_enc_password_optional" msgid="1350137345907579306">"Wenn Sie die gesamten Sicherungsdaten verschlüsseln möchten, geben Sie unten ein Passwort ein:"</string>
+ <string name="current_password_text" msgid="8268189555578298067">"Gib dein aktuelles Sicherungspasswort unten ein:"</string>
+ <string name="device_encryption_restore_text" msgid="1570864916855208992">"Gib dein Passwort zur Geräteverschlüsselung unten ein."</string>
+ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Gib dein Passwort zur Geräteverschlüsselung unten ein. Damit wird auch das Sicherungsarchiv verschlüsselt."</string>
+ <string name="backup_enc_password_text" msgid="4981585714795233099">"Gib ein Passwort für die Verschlüsselung der vollständigen Sicherungsdaten ein. Wenn du dieses Feld leer lässt, wird dein aktuelles Sicherungspasswort verwendet:"</string>
+ <string name="backup_enc_password_optional" msgid="1350137345907579306">"Wenn du die gesamten Sicherungsdaten verschlüsseln möchtest, gib unten ein Passwort ein:"</string>
<string name="backup_enc_password_required" msgid="7889652203371654149">"Da Ihr Gerät verschlüsselt ist, muss auch die Sicherung verschlüsselt werden. Geben Sie unten ein Passwort ein:"</string>
- <string name="restore_enc_password_text" msgid="6140898525580710823">"Geben Sie das Passwort unten ein, wenn die Daten für die Wiederherstellung verschlüsselt sind:"</string>
+ <string name="restore_enc_password_text" msgid="6140898525580710823">"Gib das Passwort unten ein, wenn die Daten für die Wiederherstellung verschlüsselt sind:"</string>
<string name="toast_backup_started" msgid="550354281452756121">"Sicherung wird gestartet..."</string>
<string name="toast_backup_ended" msgid="3818080769548726424">"Sicherung abgeschlossen"</string>
<string name="toast_restore_started" msgid="7881679218971277385">"Wiederherstellung wird gestartet..."</string>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index abb464e..6fb8b51 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -56,7 +56,6 @@
public class CaptivePortalLoginActivity extends Activity {
private static final String TAG = "CaptivePortalLogin";
- private static final String DEFAULT_SERVER = "connectivitycheck.gstatic.com";
private static final int SOCKET_TIMEOUT_MS = 10000;
private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS };
@@ -72,16 +71,14 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- String server = Settings.Global.getString(getContentResolver(), "captive_portal_server");
- if (server == null) server = DEFAULT_SERVER;
mCm = ConnectivityManager.from(this);
String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
+ if (url == null) url = mCm.getCaptivePortalServerUrl();
try {
- mURL = url != null ? new URL(url) : new URL("http", server, "/generate_204");
+ mURL = new URL(url);
} catch (MalformedURLException e) {
// System misconfigured, bail out in a way that at least provides network access.
- Log.e(TAG, "Invalid captive portal URL, server=" + server);
+ Log.e(TAG, "Invalid captive portal URL, url=" + url);
done(Result.WANTED_AS_IS);
}
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index f9bbccb..1b5911d 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -23,11 +23,11 @@
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/progress_bar_height"
android:indeterminate="true"
style="@style/TrimmedHorizontalProgressBar"
android:visibility="gone"/>
-
+
<FrameLayout
android:id="@+id/container_message_bar"
android:layout_width="match_parent"
@@ -44,7 +44,7 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
-
+
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
@@ -58,9 +58,9 @@
android:layout_height="wrap_content"
android:text="@string/button_retry"
style="?android:attr/buttonBarPositiveButtonStyle" />
-
+
</LinearLayout>
-
+
<!-- This FrameLayout works around b/24189541 -->
<FrameLayout
android:layout_width="match_parent"
@@ -68,6 +68,7 @@
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
+ android:background="@color/window_background"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index 7e0649b..a3cfde8 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -15,11 +15,19 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
+<!-- showAsAction flag impacts the behavior of SearchView.
+ When set to collapseActionView, collapsing SearchView to icon is the
+ default behavior. It would fit UX, however after expanding SearchView is
+ shown on the left site of the toolbar (replacing title). Since no way to
+ prevent this behavior was found, the flag is set to always. SearchView is
+ always visible by default and it is being collapse manually by calling
+ setIconified() method
+-->
<item
android:id="@+id/menu_search"
android:title="@string/menu_search"
android:icon="@drawable/ic_menu_search"
- android:showAsAction="always|collapseActionView"
+ android:showAsAction="always"
android:actionViewClass="android.widget.SearchView"
android:imeOptions="actionSearch" />
<item
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 153c673..c868d34 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -33,4 +33,6 @@
<color name="item_doc_background">#fffafafa</color>
<color name="item_doc_background_selected">#ffe0f2f1</color>
+ <color name="menu_search_background">#ff676f74</color>
+
</resources>
diff --git a/packages/DocumentsUI/res/values/dimens.xml b/packages/DocumentsUI/res/values/dimens.xml
index cacdf4d..5adb165 100644
--- a/packages/DocumentsUI/res/values/dimens.xml
+++ b/packages/DocumentsUI/res/values/dimens.xml
@@ -15,6 +15,9 @@
-->
<resources>
+ <dimen name="grid_container_padding">10dp</dimen>
+ <dimen name="list_container_padding">0dp</dimen>
+
<dimen name="icon_size">40dp</dimen>
<dimen name="root_icon_size">24dp</dimen>
<dimen name="root_icon_margin">0dp</dimen>
@@ -23,6 +26,8 @@
<dimen name="list_item_thumbnail_size">40dp</dimen>
<dimen name="grid_item_icon_size">30dp</dimen>
+ <dimen name="progress_bar_height">4dp</dimen>
+
<dimen name="grid_width">152dp</dimen>
<dimen name="grid_height">176dp</dimen>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 7f710fc..dfeef50 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -38,12 +38,14 @@
import android.provider.DocumentsContract.Root;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.MenuItem.OnActionExpandListener;
import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
@@ -174,6 +176,12 @@
return true;
}
+ @Override
+ protected void onDestroy() {
+ mRoots.setOnCacheUpdateListener(null);
+ super.onDestroy();
+ }
+
State buildDefaultState() {
State state = new State();
@@ -218,6 +226,7 @@
case R.id.menu_advanced:
case R.id.menu_file_size:
case R.id.menu_new_window:
+ case R.id.menu_search:
break;
default:
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
@@ -318,6 +327,8 @@
* the (abstract) directoryChanged method will be called.
* @param anim
*/
+ // TODO: Refactor the usage of the method - now it is called not only when the directory
+ // changed, but also to refresh the content of the directory while searching
final void onCurrentDirectoryChanged(int anim) {
mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
onDirectoryChanged(anim);
@@ -328,7 +339,11 @@
}
updateActionBar();
- invalidateOptionsMenu();
+
+ // Prevents searchView from being recreated while searching
+ if (!mSearchManager.isSearching()) {
+ invalidateOptionsMenu();
+ }
}
final List<String> getExcludedAuthorities() {
@@ -509,7 +524,7 @@
@Override
protected void onPostExecute(DocumentInfo result) {
- if (result != null) {
+ if (result != null && !isDestroyed()) {
openContainerDocument(result);
}
}
@@ -720,7 +735,7 @@
* Facade over the various search parts in the menu.
*/
final class SearchManager implements
- SearchView.OnCloseListener, OnActionExpandListener, OnQueryTextListener,
+ SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener,
DocumentsToolBar.OnActionViewCollapsedListener {
private boolean mSearchExpanded;
@@ -738,9 +753,10 @@
mView = (SearchView) mMenu.getActionView();
mActionBar.setOnActionViewCollapsedListener(this);
- mMenu.setOnActionExpandListener(this);
mView.setOnQueryTextListener(this);
mView.setOnCloseListener(this);
+ mView.setOnSearchClickListener(this);
+ mView.setOnQueryTextFocusChangeListener(this);
}
/**
@@ -793,19 +809,13 @@
* search currently.
*/
boolean cancelSearch() {
- boolean collapsed = false;
- boolean closed = false;
-
- if (mActionBar.hasExpandedActionView()) {
- mActionBar.collapseActionView();
- collapsed = true;
- }
-
if (isExpanded() || isSearching()) {
- onClose();
- closed = true;
+ // If the query string is not empty search view won't get iconified
+ mView.setQuery("", false);
+ mView.setIconified(true);
+ return true;
}
- return collapsed || closed;
+ return false;
}
boolean isSearching() {
@@ -816,6 +826,11 @@
return mSearchExpanded;
}
+ /**
+ * Clears the search.
+ * @return True if the default behavior of clearing/dismissing SearchView should be
+ * overridden. False otherwise.
+ */
@Override
public boolean onClose() {
mSearchExpanded = false;
@@ -824,33 +839,33 @@
return false;
}
- mState.currentSearch = null;
- onCurrentDirectoryChanged(ANIM_NONE);
+ mView.setBackgroundColor(
+ getResources().getColor(android.R.color.transparent, null));
+
+ // Refresh the directory if a search was done
+ if(mState.currentSearch != null) {
+ mState.currentSearch = null;
+ onCurrentDirectoryChanged(ANIM_NONE);
+ }
+
return false;
}
+ /**
+ * Sets mSearchExpanded.
+ * Called when search icon is clicked to start search.
+ * Used to detect when the view expanded instead of onMenuItemActionExpand, because
+ * SearchView has showAsAction set to always and onMenuItemAction* methods are not called.
+ */
@Override
- public boolean onMenuItemActionExpand(MenuItem item) {
+ public void onClick (View v) {
mSearchExpanded = true;
- updateActionBar();
- return true;
- }
-
- @Override
- public boolean onMenuItemActionCollapse(MenuItem item) {
- mSearchExpanded = false;
- if (mIgnoreNextCollapse) {
- mIgnoreNextCollapse = false;
- return true;
- }
- mState.currentSearch = null;
- onCurrentDirectoryChanged(ANIM_NONE);
- return true;
+ mView.setBackgroundColor(
+ getResources().getColor(R.color.menu_search_background, null));
}
@Override
public boolean onQueryTextSubmit(String query) {
- mSearchExpanded = true;
mState.currentSearch = query;
mView.clearFocus();
onCurrentDirectoryChanged(ANIM_NONE);
@@ -863,6 +878,18 @@
}
@Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if(!hasFocus) {
+ if(mState.currentSearch == null) {
+ mView.setIconified(true);
+ }
+ else if(TextUtils.isEmpty(mView.getQuery())) {
+ cancelSearch();
+ }
+ }
+ }
+
+ @Override
public void onActionViewCollapsed() {
updateActionBar();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index ca8ef2e..223af89 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -308,8 +308,10 @@
mSearchManager.showMenu(!picking);
// No display options in recent directories
- grid.setVisible(!(picking && recents));
- list.setVisible(!(picking && recents));
+ if (picking && recents) {
+ grid.setVisible(false);
+ list.setVisible(false);
+ }
fileSize.setVisible(fileSize.isVisible() && !picking);
settings.setVisible(false);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 4c844c4..beff196 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -297,7 +297,7 @@
for (final RootInfo root : roots) {
final RootItem item = new RootItem(root);
- if (root.isLibrary() || root.isHome()) {
+ if (root.isLibrary()) {
libraries.add(item);
} else {
others.add(item);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 84ab85e..22e81c6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -407,7 +407,6 @@
state.derivedMode = result.mode;
}
state.derivedSortOrder = result.sortOrder;
- ((BaseActivity) context).onStateChanged();
updateDisplayState();
@@ -602,11 +601,11 @@
throw new IllegalArgumentException("Unsupported layout mode: " + mode);
}
- mRecView.setLayoutManager(layout);
- // TODO: Once b/23691541 is resolved, use a listener within MultiSelectManager instead of
- // imperatively calling this function.
- mSelectionManager.handleLayoutChanged();
+ int pad = getDirectoryPadding(mode);
+ mRecView.setPadding(pad, pad, pad, pad);
// setting layout manager automatically invalidates existing ViewHolders.
+ mRecView.setLayoutManager(layout);
+ mSelectionManager.handleLayoutChanged(); // RecyclerView doesn't do this for us
mIconHelper.setMode(mode);
}
@@ -622,6 +621,20 @@
return columnCount;
}
+ private int getDirectoryPadding(int mode) {
+ switch (mode) {
+ case MODE_GRID:
+ return getResources().getDimensionPixelSize(
+ R.dimen.grid_container_padding);
+ case MODE_LIST:
+ return getResources().getDimensionPixelSize(
+ R.dimen.list_container_padding);
+ case MODE_UNKNOWN:
+ default:
+ throw new IllegalArgumentException("Unsupported layout mode: " + mode);
+ }
+ }
+
@Override
public int getColumnCount() {
return mColumnCount;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/EmptyDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/EmptyDocumentHolder.java
deleted file mode 100644
index d1f8ff7..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/EmptyDocumentHolder.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.documentsui.dirlist;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.view.View;
-import android.widget.Space;
-
-import com.android.documentsui.R;
-import com.android.documentsui.State;
-
-final class EmptyDocumentHolder extends DocumentHolder {
- final int mVisibleHeight;
-
- public EmptyDocumentHolder(Context context) {
- super(context, new Space(context));
-
- // Per UX spec, this puts a bigger gap between the folders and documents in the grid.
- mVisibleHeight = context.getResources().getDimensionPixelSize(R.dimen.grid_item_margin) * 2;
- }
-
- public void bind(State state) {
- bind(null, null, state);
- }
-
- @Override
- public void bind(Cursor cursor, String modelId, State state) {
- if (state.derivedMode == State.MODE_GRID) {
- itemView.setMinimumHeight(mVisibleHeight);
- } else {
- itemView.setMinimumHeight(0);
- }
- return;
- }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index f2bade5..cf21d15 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -187,7 +187,7 @@
}
break;
case SORT_ORDER_LAST_MODIFIED:
- longValues[pos] = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED);
+ longValues[pos] = getLastModified(mCursor);
stringValues[pos] = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
break;
case SORT_ORDER_SIZE:
@@ -309,11 +309,19 @@
} else {
final long lhs = pivotValue;
final long rhs = sortKey[mid];
- // Sort in descending numerical order. This matches legacy behaviour, which yields
- // largest or most recent items on top.
+ // Sort in descending numerical order. This matches legacy behaviour, which
+ // yields largest or most recent items on top.
compare = -Long.compare(lhs, rhs);
}
+ // If numerical comparison yields a tie, use document ID as a tie breaker. This
+ // will yield stable results even if incoming items are continually shuffling and
+ // have identical numerical sort keys. One common example of this scenario is seen
+ // when sorting a set of active downloads by mod time.
+ if (compare == 0) {
+ compare = pivotId.compareTo(ids.get(mid));
+ }
+
if (compare < 0) {
right = mid;
} else {
@@ -350,6 +358,16 @@
}
}
+ /**
+ * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null
+ * timestamp - these will be replaced with MAX_LONG so that such files get sorted to the top
+ * when sorting by date.
+ */
+ long getLastModified(Cursor cursor) {
+ long l = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED);
+ return (l == -1) ? Long.MAX_VALUE : l;
+ }
+
@Nullable Cursor getItem(String modelId) {
Integer pos = mPositions.get(modelId);
if (pos != null) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
index 3ee1d42..2485ad9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
@@ -18,10 +18,16 @@
import static com.android.internal.util.Preconditions.checkArgument;
+import android.content.Context;
+import android.database.Cursor;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView.AdapterDataObserver;
import android.util.SparseArray;
import android.view.ViewGroup;
+import android.widget.Space;
+
+import com.android.documentsui.R;
+import com.android.documentsui.State;
import java.util.List;
@@ -222,4 +228,33 @@
throw new UnsupportedOperationException();
}
}
+
+ /**
+ * The most elegant transparent blank box that spans N rows ever conceived.
+ */
+ private static final class EmptyDocumentHolder extends DocumentHolder {
+ final int mVisibleHeight;
+
+ public EmptyDocumentHolder(Context context) {
+ super(context, new Space(context));
+
+ // Per UX spec, this puts a bigger gap between the folders and documents in the grid.
+ mVisibleHeight = context.getResources().getDimensionPixelSize(
+ R.dimen.grid_item_margin);
+ }
+
+ public void bind(State state) {
+ bind(null, null, state);
+ }
+
+ @Override
+ public void bind(Cursor cursor, String modelId, State state) {
+ if (state.derivedMode == State.MODE_GRID) {
+ itemView.setMinimumHeight(mVisibleHeight);
+ } else {
+ itemView.setMinimumHeight(0);
+ }
+ return;
+ }
+ }
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
index bed7c9c..a5f0656 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
@@ -34,8 +34,10 @@
import java.util.ArrayList;
import java.util.BitSet;
+import java.util.HashSet;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
@SmallTest
@@ -50,6 +52,7 @@
Document.COLUMN_FLAGS,
Document.COLUMN_DISPLAY_NAME,
Document.COLUMN_SIZE,
+ Document.COLUMN_LAST_MODIFIED,
Document.COLUMN_MIME_TYPE
};
@@ -263,6 +266,43 @@
assertEquals(ITEM_COUNT, seen.cardinality());
}
+ public void testSort_time() {
+ final int DL_COUNT = 3;
+ MatrixCursor c = new MatrixCursor(COLUMNS);
+ Set<String> currentDownloads = new HashSet<>();
+
+ // Add some files
+ for (int i = 0; i < ITEM_COUNT; i++) {
+ MatrixCursor.RowBuilder row = c.newRow();
+ row.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY);
+ row.add(Document.COLUMN_DOCUMENT_ID, Integer.toString(i));
+ row.add(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
+ }
+ // Add some current downloads (no timestamp)
+ for (int i = ITEM_COUNT; i < ITEM_COUNT + DL_COUNT; i++) {
+ MatrixCursor.RowBuilder row = c.newRow();
+ String id = Integer.toString(i);
+ row.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY);
+ row.add(Document.COLUMN_DOCUMENT_ID, id);
+ currentDownloads.add(Model.createModelId(AUTHORITY, id));
+ }
+
+ DirectoryResult r = new DirectoryResult();
+ r.cursor = c;
+ r.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
+ model.update(r);
+
+ List<String> ids = model.getModelIds();
+
+ // Check that all items were accounted for
+ assertEquals(ITEM_COUNT + DL_COUNT, ids.size());
+
+ // Check that active downloads are sorted to the top.
+ for (int i = 0; i < DL_COUNT; i++) {
+ assertTrue(currentDownloads.contains(ids.get(i)));
+ }
+ }
+
// Tests that Model.delete works correctly.
public void testDelete() throws Exception {
// Simulate deleting 2 files.
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index dea5fa0..746457f 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -308,31 +308,31 @@
<string name="airplane_mode">Airplane mode</string>
<!-- An explanation text that the pattern needs to be solved since the device has just been restarted. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_restart_pattern">Pattern required when you restart device.</string>
+ <string name="kg_prompt_reason_restart_pattern">Pattern required after device restarts</string>
<!-- An explanation text that the pin needs to be entered since the device has just been restarted. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_restart_pin">PIN required when you restart device.</string>
+ <string name="kg_prompt_reason_restart_pin">PIN required after device restarts</string>
<!-- An explanation text that the password needs to be entered since the device has just been restarted. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_restart_password">Password required when you restart device.</string>
+ <string name="kg_prompt_reason_restart_password">Password required after device restarts</string>
<!-- An explanation text that the pattern needs to be solved since the user hasn't used strong authentication since quite some time. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_timeout_pattern">Pattern required for additional security.</string>
+ <string name="kg_prompt_reason_timeout_pattern">Pattern required for additional security</string>
<!-- An explanation text that the pin needs to be entered since the user hasn't used strong authentication since quite some time. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_timeout_pin">PIN required for additional security.</string>
+ <string name="kg_prompt_reason_timeout_pin">PIN required for additional security</string>
<!-- An explanation text that the password needs to be entered since the user hasn't used strong authentication since quite some time. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_timeout_password">Password required for additional security.</string>
+ <string name="kg_prompt_reason_timeout_password">Password required for additional security</string>
<!-- An explanation text that the pattern needs to be solved since profiles have just been switched. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_switch_profiles_pattern">Pattern required when you switch profiles.</string>
+ <string name="kg_prompt_reason_switch_profiles_pattern">Pattern required when you switch profiles</string>
<!-- An explanation text that the pin needs to be entered since profiles have just been switched. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_switch_profiles_pin">PIN required when you switch profiles.</string>
+ <string name="kg_prompt_reason_switch_profiles_pin">PIN required when you switch profiles</string>
<!-- An explanation text that the password needs to be entered since profiles have just been switched. [CHAR LIMIT=80] -->
- <string name="kg_prompt_reason_switch_profiles_password">Password required when you switch profiles.</string>
+ <string name="kg_prompt_reason_switch_profiles_password">Password required when you switch profiles</string>
<!-- An explanation text that the pattern needs to be solved since it hasn't been solved in a while. [CHAR LIMIT=80]-->
<plurals name="kg_prompt_reason_time_pattern">
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index c216c77..15b8ef3 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -7,9 +7,6 @@
import android.provider.DocumentsContract;
import android.util.Log;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpManagerTest.java
index 49b48c5..7527f54 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpManagerTest.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
+import android.mtp.MtpConstants;
+import android.mtp.MtpEvent;
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
import android.os.SystemClock;
@@ -32,12 +34,10 @@
@RealDeviceTest
public class MtpManagerTest extends InstrumentationTestCase {
-
private static final int TIMEOUT_MS = 1000;
UsbManager mUsbManager;
MtpManager mManager;
UsbDevice mUsbDevice;
- int mRequest;
@Override
public void setUp() throws Exception {
@@ -85,6 +85,19 @@
getInstrumentation().show(Arrays.toString(records[0].operationsSupported));
}
+ public void testEventObjectAdded() throws Exception {
+ while (true) {
+ getInstrumentation().show("Please take a photo by using connected MTP device.");
+ final CancellationSignal signal = new CancellationSignal();
+ MtpEvent event = mManager.readEvent(mUsbDevice.getDeviceId(), signal);
+ if (event.getEventCode() != MtpConstants.EVENT_OBJECT_ADDED) {
+ continue;
+ }
+ assertTrue(event.getObjectHandle() != 0);
+ break;
+ }
+ }
+
private Context getContext() {
return getInstrumentation().getContext();
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
index 2935267..ffcc088 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
@@ -42,9 +42,8 @@
UsbManager usbManager,
MtpManager manager) {
while (true) {
- final UsbDevice device = findMtpDevice(instrumentation, usbManager, manager);
try {
- manager.openDevice(device.getDeviceId());
+ final UsbDevice device = findMtpDevice(usbManager, manager);
waitForStorages(instrumentation, manager, device.getDeviceId());
return device;
} catch (IOException exp) {
@@ -59,41 +58,26 @@
}
private static UsbDevice findMtpDevice(
- TestResultInstrumentation instrumentation,
UsbManager usbManager,
- MtpManager manager) {
- while (true) {
- final HashMap<String,UsbDevice> devices = usbManager.getDeviceList();
- if (devices.size() == 0) {
- instrumentation.show("Wait for devices.");
- SystemClock.sleep(1000);
- continue;
- }
- final UsbDevice device = devices.values().iterator().next();
- try {
- manager.openDevice(device.getDeviceId());
- } catch (IOException e) {
- // Maybe other application is using the device.
- // Force to obtain ownership of the device so that we can use the device next call
- // of findMtpDevice.
- instrumentation.show("Tries to get ownership of MTP device.");
- final UsbDeviceConnection connection = usbManager.openDevice(device);
- if (connection == null) {
- Assert.fail("Cannot open USB connection.");
- return null;
- }
- for (int i = 0; i < device.getInterfaceCount(); i++) {
- // Since the test runs real environment, we need to call claim interface with
- // force = true to rob interfaces from other applications.
- connection.claimInterface(device.getInterface(i), true);
- connection.releaseInterface(device.getInterface(i));
- }
- connection.close();
- SystemClock.sleep(1000);
- continue;
- }
- return device;
+ MtpManager manager) throws IOException {
+ final HashMap<String,UsbDevice> devices = usbManager.getDeviceList();
+ if (devices.size() == 0) {
+ throw new IOException("Device not found.");
}
+ final UsbDevice device = devices.values().iterator().next();
+ // Tries to get ownership of the device in case that another application use it.
+ if (usbManager.hasPermission(device)) {
+ final UsbDeviceConnection connection = usbManager.openDevice(device);
+ for (int i = 0; i < device.getInterfaceCount(); i++) {
+ // Since the test runs real environment, we need to call claim interface with
+ // force = true to rob interfaces from other applications.
+ connection.claimInterface(device.getInterface(i), true);
+ connection.releaseInterface(device.getInterface(i));
+ }
+ connection.close();
+ }
+ manager.openDevice(device.getDeviceId());
+ return device;
}
private static void waitForStorages(
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 0f34e9e..57ba2b6 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Meer inligting oor hierdie drukker"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Sommige drukdienste is gedeaktiveer."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Kies drukdiens"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Soek tans vir drukkers"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Geen drukdienste is geaktiveer nie"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kanselleer tans <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Drukkerfout by <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Drukker het <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> geblokkeer"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>-druktake</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>-druktaak</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Kanselleer"</string>
<string name="restart" msgid="2472034227037808749">"Herbegin"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Geen verbinding met drukker nie"</string>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index a6e1abf..a2182fb 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ተጨማሪ የዚህ አታሚ መረጃ"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"አንዳንድ የህትመት አገልግሎቶች ተሰናክለዋል።"</string>
<string name="choose_print_service" msgid="3740309762324459694">"የህትመት አገልግሎት ይምረጡ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"አታሚዎችን በመፈለግ ላይ"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ምንም የህትመት አገልግሎቶች አልነቁም"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ን በመተው ላይ"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"የአታሚ ስህተት <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"አታሚ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ን አግዷል"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> የህትመት ስራ</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> የህትመት ስራ</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"ይቅር"</string>
<string name="restart" msgid="2472034227037808749">"እንደገና ጀምር"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ከአታሚ ጋር ምንም ግንኙነት የለም"</string>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 0291b7d..eab1339 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -65,6 +65,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"مزيد من المعلومات حول هذه الطابعة"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"بعض خدمات الطباعة معطَّلة."</string>
<string name="choose_print_service" msgid="3740309762324459694">"اختر خدمة طباعة"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"البحث عن طابعات"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"لم يتم تمكين أي خدمات طباعة"</string>
@@ -73,14 +74,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"جارٍ إلغاء <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"خطا في الطابعة <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"رفضت الطابعة <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="zero"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> مهمة طباعة</item>
- <item quantity="two">مهمتا طباعة (<xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>)</item>
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> مهام طباعة</item>
- <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> مهمة طباعة</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> من مهام الطباعة</item>
- <item quantity="one">مهمة طباعة واحدة (<xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>)</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"إلغاء"</string>
<string name="restart" msgid="2472034227037808749">"إعادة تشغيل"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"لا يوجد اتصال بالطابعة"</string>
diff --git a/packages/PrintSpooler/res/values-az-rAZ/strings.xml b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
index e162793..bff477d 100644
--- a/packages/PrintSpooler/res/values-az-rAZ/strings.xml
+++ b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Bu printer haqqında daha ətraflı məlumat"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Bəzi çap xidmətləri deaktiv edilib."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Çap xidmətini seçin"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printer axtarılır"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Heç bir çap xidməti aktiv edilməyib"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ləğv edilir"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer xətası <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> işini blokladı"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> çap işi</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> çap işi</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Ləğv et"</string>
<string name="restart" msgid="2472034227037808749">"Yenidən başlat"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printerə heç bir bağlantı yoxdur"</string>
diff --git a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
index d6e439c..b28aa29 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -62,6 +62,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Još informacija o ovom štampaču"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Neke usluge štampanja su onemogućene."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Izaberite uslugu štampanja"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Pretraga štampača"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nijedna usluga štampanja nije omogućena"</string>
@@ -70,11 +71,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazuje se <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Greška štampača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Štampač je blokirao <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one">Zadaci štampanja <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="few">Zadaci štampanja <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">Zadaci štampanja <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Otkaži"</string>
<string name="restart" msgid="2472034227037808749">"Ponovo pokreni"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nema veze sa štampačem"</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index c2393543..e8de8ea 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Още информация за този принтер"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Някои услуги за отпечатване са деактивирани."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Избиране на услуга за отпечатване"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Търсене на принтери"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Няма активирани услуги за отпечатване"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"„<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“ се анулира"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка в принтера при „<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Принтерът блокира при „<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>“"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Задания за отпечатване: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Задание за отпечатване: <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Отказ"</string>
<string name="restart" msgid="2472034227037808749">"Рестартиране"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Няма връзка с принтера"</string>
diff --git a/packages/PrintSpooler/res/values-bn-rBD/strings.xml b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
index 17a1a35..a1ca494 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"এই মুদ্রকটির বিষয়ে আরো তথ্য"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"কিছু মুদ্রণ পরিষেবা অক্ষম করা হয়েছে৷"</string>
<string name="choose_print_service" msgid="3740309762324459694">"মুদ্রণ পরিষেবা চয়ন করুন"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"মুদ্রকগুলি অনুসন্ধান করা হচ্ছে"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"মুদ্রণ পরিষেবা সক্ষম নেই"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> বাতিল করা হচ্ছে"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> মুদ্রক ত্রুটি"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"মুদ্রক <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> অবরুদ্ধ করেছে"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> মুদ্রণ কার্যগুলি</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> মুদ্রণ কার্যগুলি</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"বাতিল করুন"</string>
<string name="restart" msgid="2472034227037808749">"পুনর্সূচনা"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"মুদ্রকে কোনো সংযোগ নেই"</string>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index 2551206..aa6f992 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Més informació sobre aquesta impressora"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Hi ha serveis d\'impressió que estan desactivats."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Selecció del servei d\'impressió"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Cerca d\'impressores"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"No hi ha cap servei d\'impressió activat"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"S\'està cancel·lant <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error d\'impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Impressora bloquejada <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tasques d\'impressió</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tasca d\'impressió</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancel·la"</string>
<string name="restart" msgid="2472034227037808749">"Reinicia"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hi ha connexió amb la impressora"</string>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 0bb48f8..4bc22d4 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Další informace o této tiskárně"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Některé tiskové služby nejsou aktivovány."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Zvolte službu tisku"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhledávání tiskáren"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nejsou aktivovány žádné tiskové služby"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Rušení úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tiskárny u úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tiskárna blokuje úlohu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="few">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="many">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Tiskové úlohy: <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Zrušit"</string>
<string name="restart" msgid="2472034227037808749">"Restartovat"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nelze se připojit k tiskárně"</string>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index a9d042b..b8be624 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Flere oplysninger om denne printer"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Nogle udskrivningstjenester er deaktiveret."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Vælg udskriftstjeneste"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Søger efter printere"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ingen udskrivningstjenester er aktiveret"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annulleres"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Udskriften <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> mislykkedes"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printeren har blokeret <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>-udskriftsjob</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>-udskriftsjob</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuller"</string>
<string name="restart" msgid="2472034227037808749">"Genstart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen forbindelse til printer"</string>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index 4eb5d6a9..0b77186 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Weitere Informationen über diesen Drucker"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Einige Druckdienste sind deaktiviert."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Druckdienst auswählen"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Suche nach Druckern"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Keine Druckdienste aktiviert"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> wird abgebrochen..."</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Druckerfehler <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Drucker hat <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> blockiert."</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Druckaufträge \"<xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>\"</item>
- <item quantity="one">Druckauftrag \"<xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>\"</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Abbrechen"</string>
<string name="restart" msgid="2472034227037808749">"Neu starten"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Keine Verbindung zum Drucker"</string>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index cd35785..d9a4aeb 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Περισσότερες πληροφορίες σχετικά με αυτόν τον εκτυπωτή"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Κάποιες υπηρ. εκτύπωσης είναι απενεργοποιημένες."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Επιλέξτε υπηρεσία εκτύπωσης"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Αναζήτηση για εκτυπωτές"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Δεν έχουν ενεργοποιηθεί υπηρεσίες εκτύπωσης"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ακύρωση <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Σφάλμα εκτυπωτή <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Ο εκτυπωτής απέκλεισε <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> εργασίες εκτύπωσης</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> εργασία εκτύπωσης</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Ακύρωση"</string>
<string name="restart" msgid="2472034227037808749">"Επανεκκίνηση"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Δεν υπάρχει σύνδεση με εκτυπωτή"</string>
diff --git a/packages/PrintSpooler/res/values-en-rAU/strings.xml b/packages/PrintSpooler/res/values-en-rAU/strings.xml
index 753d9df..d8a9437 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Some print services are disabled."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"No print services enabled"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer blocked <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> print jobs</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> print job</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancel"</string>
<string name="restart" msgid="2472034227037808749">"Restart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 753d9df..d8a9437 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Some print services are disabled."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"No print services enabled"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer blocked <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> print jobs</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> print job</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancel"</string>
<string name="restart" msgid="2472034227037808749">"Restart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 753d9df..d8a9437 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Some print services are disabled."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Choose print service"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"No print services enabled"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelling <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printer error <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer blocked <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> print jobs</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> print job</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancel"</string>
<string name="restart" msgid="2472034227037808749">"Restart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No connection to printer"</string>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index 1a0d5d8..19c695b 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Más información sobre esta impresora"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Hay servicios de impresión inhabilitados."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Elegir servicio de impresión"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"No hay servicios de impresión habilitados"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"La impresora bloqueó <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>."</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Trabajos de impresión: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Trabajo de impresión: <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hay conexión con la impresora."</string>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index eac568d..d13ccda 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Más información sobre esta impresora"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Algunos servicios de impresión están inhabilitados."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Seleccionar servicio de impresión"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"No hay servicios de impresión habilitados"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error de impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"La impresora ha bloqueado <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Trabajos de impresión <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Trabajo de impresión <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Volver a empezar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"No hay conexión con la impresora"</string>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 2cde258..f03eb37 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Lisateave selle printeri kohta"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Mõned printimisteenused on keelatud."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Prinditeenuse valimine"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printerite otsimine"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ühtegi printimisteenust pole lubatud"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prinditöö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> tühistamine"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri viga: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer blokeeris töö <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> prinditööd</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> prinditöö</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Tühista"</string>
<string name="restart" msgid="2472034227037808749">"Taaskäivita"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printeriühendus puudub"</string>
diff --git a/packages/PrintSpooler/res/values-eu-rES/strings.xml b/packages/PrintSpooler/res/values-eu-rES/strings.xml
index 96a3273..d4255e2 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Informazio gehiago inprimagailuari buruz"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Desgaituta daude inprimatzeko zerbitzu batzuk."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Aukeratu inprimatze-zerbitzua"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Inprimagailuak bilatzen"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ez dago gaituta inprimatzeko zerbitzurik"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bertan behera uzten"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Errorea <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> inprimatzean"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Inprimag. <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> blokeatu du"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> inprimatze-lanak</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> inprimatze-lana</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Utzi"</string>
<string name="restart" msgid="2472034227037808749">"Berrabiarazi"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Inprimagailua ez dago konektatuta"</string>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index fdc3989..907123c 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"اطلاعات بیشتر درباره چاپگر"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"بعضی از خدمات چاپ غیرفعال هستند."</string>
<string name="choose_print_service" msgid="3740309762324459694">"انتخاب سرویس چاپ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"درحال جستجوی چاپگرها"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"هیچ خدمات چاپی فعال نیست"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"در حال لغو <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"خطای چاپگر <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"چاپگر، کار <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> را مسدود کرد"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one">کار چاپ <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">کار چاپ <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"لغو"</string>
<string name="restart" msgid="2472034227037808749">"راهاندازی مجدد"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"اتصال با چاپگر برقرار نیست"</string>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index 9267393..f57b884 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Lisätietoja tästä tulostimesta"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Osa tulostuspalveluista on poistettu käytöstä."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Valitse tulostuspalvelu"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Etsitään tulostimia"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ei käytössä olevia tulostuspalveluita"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Peruutetaan työ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Tulostinvirhe työlle <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tulostin esti työn <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tulostustyötä</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tulostustyö</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Peruuta"</string>
<string name="restart" msgid="2472034227037808749">"Käynnistä uudelleen"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ei yhteyttä tulostimeen"</string>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index bfb4862..949ba55 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Plus d\'information sur cette imprimante"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Certains services d\'impression sont désactivés."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Sélectionner le service d\'impression"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours..."</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Aucun service d\'impression activé"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression : « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> »"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Impression de « <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> » bloquée"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâche d\'impression</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâches d\'impression</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuler"</string>
<string name="restart" msgid="2472034227037808749">"Recommencer"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Aucune connexion à l\'imprimante"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index de55e29..1fcc040 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Plus d\'informations sur cette imprimante"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Certains services d\'impression sont désactivés."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Sélectionner le service d\'impression"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Aucun service d\'impression activé"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annulation de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erreur impression pour \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Impression de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" bloquée"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâche d\'impression</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tâches d\'impression</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuler"</string>
<string name="restart" msgid="2472034227037808749">"Redémarrer"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Aucune connexion à l\'imprimante."</string>
diff --git a/packages/PrintSpooler/res/values-gl-rES/strings.xml b/packages/PrintSpooler/res/values-gl-rES/strings.xml
index dc66084..2e60960 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Máis información sobre esta impresora"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Algúns servizos de impresión están desactivados."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Escoller servizo de impresión"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Busca de impresoras"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Non hai servizos de impresión activados"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impresora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A impresora bloqueou <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> traballos de impresión</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> traballo de impresión</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Non hai conexión coa impresora"</string>
diff --git a/packages/PrintSpooler/res/values-gu-rIN/strings.xml b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
index d05a392..4ba969c 100644
--- a/packages/PrintSpooler/res/values-gu-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"આ પ્રિન્ટર વિશે વધુ માહિતી"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"કેટલીક છાપ સેવાઓ અક્ષમ કરેલ છે."</string>
<string name="choose_print_service" msgid="3740309762324459694">"પ્રિન્ટ સેવા પસંદ કરો"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"પ્રિન્ટર્સ માટે શોધી રહ્યું છે"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"કોઈ છાપ સેવાઓ સક્ષમ કરેલ નથી"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ને રદ કરી રહ્યું છે"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"પ્રિન્ટર ભૂલ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"પ્રિન્ટરે <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> અવરોધિત કર્યું"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> છાપ જોબ</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> છાપ જોબ</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"રદ કરો"</string>
<string name="restart" msgid="2472034227037808749">"પુનઃપ્રારંભ કરો"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"પ્રિન્ટર માટે કોઈ કનેક્શન નથી"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 8051900..1061346 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"इस प्रिंटर के बारे में अधिक जानकारी"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"कुछ प्रिंट सेवाएं अक्षम हैं."</string>
<string name="choose_print_service" msgid="3740309762324459694">"प्रिंट सेवा चुनें"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर खोज रहा है"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"कोई भी प्रिंट सेवा सक्षम नहीं है"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द हो रहा है"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिंटर अवरोधित <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> प्रिंट कार्य</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> प्रिंट कार्य</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"अभी नहीं"</string>
<string name="restart" msgid="2472034227037808749">"पुन: आरंभ करें"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटर के लिए कोई कनेक्शन नहीं"</string>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 4dab4cc9..4a7d29f 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -62,6 +62,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Više informacija o ovom pisaču"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Neke su usluge ispisa onemogućene."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Odaberite uslugu ispisa"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Traženje pisača"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nije omogućena nijedna usluga ispisa"</string>
@@ -70,11 +71,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Otkazivanje zadatka <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Pogreška pisača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Pisač je blokirao <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadatak ispisa</item>
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadatka ispisa</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadataka ispisa</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Odustani"</string>
<string name="restart" msgid="2472034227037808749">"Ponovo pokreni"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nema veze s pisačem"</string>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 1a56ee7..5aae2e4 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"További információ erről a nyomtatóról"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Egyes nyomtatási szolgáltatások le vannak tiltva."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Nyomtatási szolgáltatás kiválasztása"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Nyomtatók keresése"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nincs engedélyezett nyomtatási szolgáltatás"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> törlése"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Nyomtatási hiba: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A(z) <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> letiltva."</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> nyomtatási feladat</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> nyomtatási feladat</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Mégse"</string>
<string name="restart" msgid="2472034227037808749">"Újraindítás"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nincs kapcsolat a nyomtatóval"</string>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index 7b99dcf..179c384 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Հավելյալ տեղեկություններ այս տպիչի մասին"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Տպելու որոշ ծառայությունները կասեցված են:"</string>
<string name="choose_print_service" msgid="3740309762324459694">"Ընտրեք տպելու ծառայությունը"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Տպիչների որոնում"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ակտիվացված տպման ծառայություններ չկան"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>-ը չեղարկվում է"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Տպիչի սխալ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Տպիչն արգելափակել է <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>-ը"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> տպման աշխատանք</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> տպման աշխատանք</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Չեղարկել"</string>
<string name="restart" msgid="2472034227037808749">"Վերագործարկել"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Տպիչի հետ կապ չկա"</string>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index a991272..7286f7a 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Informasi selengkapnya tentang printer ini"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Beberapa layanan cetak dinonaktifkan."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Pilih layanan cetak"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari printer"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Tidak ada layanan cetak yang aktif"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ada kesalahan printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer memblokir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Tugas cetak <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Tugas cetak <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Batal"</string>
<string name="restart" msgid="2472034227037808749">"Mulai Ulang"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Tidak ada sambungan ke printer"</string>
diff --git a/packages/PrintSpooler/res/values-is-rIS/strings.xml b/packages/PrintSpooler/res/values-is-rIS/strings.xml
index e93f702..9ea49a9 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Frekari upplýsingar um þennan prentara"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Hluti prentþjónustunnar er óvirkur."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Veldu prentþjónustu"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Leitar að prentara"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Engin prentþjónusta er virk"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hættir við <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Prentaravilla <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Prentari útilokaði <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> prentverk</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> prentverk</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Hætta við"</string>
<string name="restart" msgid="2472034227037808749">"Endurræsa"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Engin tenging við prentara"</string>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index ffba353..c19d012 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Ulteriori informazioni su questa stampante"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alcuni servizi di stampa sono disattivati."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Scegli servizio di stampa"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Ricerca di stampanti"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Non è stato attivato alcun servizio di stampa"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Annullamento di <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Errore della stampante: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"La stampante ha bloccato <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> processi di stampa</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> processo di stampa</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Annulla"</string>
<string name="restart" msgid="2472034227037808749">"Riavvia"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nessun collegamento alla stampante"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 2ac1093..00bf27c 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"מידע נוסף על מדפסת זו"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"שירותי הדפסה מסוימים מושבתים."</string>
<string name="choose_print_service" msgid="3740309762324459694">"בחר שירות הדפסה"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"מחפש מדפסות"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"לא הופעלו שירותי הדפסה"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"מבטל את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"שגיאת מדפסת ב-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"המדפסת חסמה את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="two"> עבודות הדפסה <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="many"> עבודות הדפסה <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other"> עבודות הדפסה <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one"> עבודת הדפסה <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"בטל"</string>
<string name="restart" msgid="2472034227037808749">"הפעל מחדש"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"אין חיבור למדפסת"</string>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index 2c3c24d..e0fc79a 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"このプリンタの詳細"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"一部の印刷サービスは無効になっています。"</string>
<string name="choose_print_service" msgid="3740309762324459694">"印刷サービスの選択"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"プリンタの検索中"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"使用できる印刷サービスがありません"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>をキャンセルしています"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"プリンタエラー: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>をブロックしました"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>の印刷ジョブ</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>の印刷ジョブ</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"キャンセル"</string>
<string name="restart" msgid="2472034227037808749">"再試行"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"プリンタに接続されていません"</string>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index 2b0285d..ad1468a 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> — <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"დამატებითი ინფორმაცია ამ პრინტერის შესახებ"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"ბეჭდვის ზოგიერთი სერვისი გათიშულია."</string>
<string name="choose_print_service" msgid="3740309762324459694">"აირჩიეთ ბეჭდვის სერვისი"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"მიმდინარეობს პრინტერების ძიება"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ბეჭდვის სერვისები გააქტიურებული არ არის"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"მიმდინარეობს <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>-ის გაუქმება"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ბეჭდვის შეცდომა <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"პრინტერმა დაბლოკა <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ბეჭდვის დავალება</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ბეჭდვის დავალება</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"გაუქმება"</string>
<string name="restart" msgid="2472034227037808749">"გადატვირთვა"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"პრინტერთან კავშირი არ არის"</string>
diff --git a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
index fc099c9..d0337a6 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Осы принтер туралы қосымша ақпарат"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Кейбір басып шығару қызметтері өшірілген."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Принтер қызметін таңдау"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлерді іздеу"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Басып шығару қызметтері қосылмаған"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> жұмысын тоқтатуда"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> принтер қателігі"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Принтер <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> жұмысын бөгеді"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> баспа тапсырмасы</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> баспа тапсырмасы</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Тоқтату"</string>
<string name="restart" msgid="2472034227037808749">"Қайта бастау"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтермен байланыс жоқ"</string>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index b51091e..c9431e9 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ព័ត៌មានបន្ថែមអំពីម៉ាស៊ីបោះពុម្ពនេះ"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"សេវាកម្មបោះពុម្ពមួយចំនួនត្រូវបានបិទដំណើរការ"</string>
<string name="choose_print_service" msgid="3740309762324459694">"ជ្រើសសេវាបោះពុម្ព"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ស្វែងរកម៉ាស៊ីនបោះពុម្ព"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"គ្មានការបើកដំណើរការសេវាបោះពុម្ពទេ"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"ការបោះបង់ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"កំហុសម៉ាស៊ីនបោះពុម្ព <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"ម៉ាស៊ីនបោះពុម្ពបានទប់ស្កាត់ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">ការងារបោះពុម្ព <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">ការងារបោះពុម្ព <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"បោះបង់"</string>
<string name="restart" msgid="2472034227037808749">"ចាប់ផ្ដើមឡើងវិញ"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មានការភ្ជាប់ទៅម៉ាស៊ីនបោះពុម្ព"</string>
diff --git a/packages/PrintSpooler/res/values-kn-rIN/strings.xml b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
index 5d5dee8..fc5149a 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ಈ ಪ್ರಿಂಟರ್ ಬಗ್ಗೆ ಇನ್ನಷ್ಟು ಮಾಹಿತಿ"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"ಕೆಲವು ಮುದ್ರಣ ಸೇವೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="choose_print_service" msgid="3740309762324459694">"ಮುದ್ರಣ ಸೇವೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ಪ್ರಿಂಟರ್ಗಳಿಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ಯಾವುದೇ ಮುದ್ರಣ ಸೇವೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿಲ್ಲ"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ರದ್ದು ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ಮುದ್ರಕ ದೋಷ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"ಮುದ್ರಕವು <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ನಿರ್ಬಂಧಿಸಿದೆ"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ಮುದ್ರಣ ಕಾರ್ಯಗಳು</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ಮುದ್ರಣ ಕಾರ್ಯಗಳು</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"ರದ್ದುಮಾಡು"</string>
<string name="restart" msgid="2472034227037808749">"ಮರುಪ್ರಾರಂಭಿಸು"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ಮುದ್ರಕಕ್ಕೆ ಸಂಪರ್ಕವಿಲ್ಲ"</string>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 98617e7..2faff1f 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"이 프린터에 대한 정보 더보기"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"프린트 서비스 일부가 사용 중지되었습니다."</string>
<string name="choose_print_service" msgid="3740309762324459694">"인쇄 서비스 선택"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"프린터 검색 중"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"사용 가능한 프린트 서비스 없음"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> 취소 중"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"프린터 오류: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"차단된 프린터: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> 인쇄 작업</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> 인쇄 작업</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"취소"</string>
<string name="restart" msgid="2472034227037808749">"다시 시작"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"프린터와 연결되지 않음"</string>
diff --git a/packages/PrintSpooler/res/values-ky-rKG/strings.xml b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
index 2a11ff8..a01e4a8 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Бул принтер жөнүндө көбүрөөк маалымат"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Басып чыгаруу кызматтарынын айрымы өчүрүлгөн."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Принтер кызматын тандоо"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлер изделүүдө"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Принтер-кызматтары иштетилген эмес"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> токтотулууда"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Принтерде ката кетти: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Принтер бөгөттөдү: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> басуу тапшырмасы</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> басуу тапшырмасы</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Айнуу"</string>
<string name="restart" msgid="2472034227037808749">"Кайра баштоо"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтер менен байланыш жок"</string>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index 788e5aa..b5d13b5 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ຂໍ້ມູນເພີ່ມເຕີມກ່ຽວກັບເຄື່ອງພິມນີ້"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"ບາງການບໍລິການພິມຖືກປິດນຳໃຊ້."</string>
<string name="choose_print_service" msgid="3740309762324459694">"ເລືອກບໍລິການການພິມ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ກຳລັງຊອກຫາເຄື່ອງພິມ"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ບໍ່ມີການບໍລິການພິມເປີດໃຊ້ງານໄວ້"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"ກຳລັງຍົກເລີກ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ເຄື່ອງພິມເກີດຂໍ້ຜິດພາດ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"ເຄື່ອງພິມຖືກບລອກ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ງານພິມ</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ງານພິມ</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"ຍົກເລີກ"</string>
<string name="restart" msgid="2472034227037808749">"ປິດເປີດໃໝ່"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ບໍ່ມີການເຊື່ອມຕໍ່ຫາເຄື່ອງພິມ"</string>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index 1826e8e..3b8f14312 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"„<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g>“ – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Daugiau informacijos apie šį spausdintuvą"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Kai kurios spausdinimo paslaugos išjungtos."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Pasirinkite spausdinimo paslaugą"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Ieškoma spausdintuvų"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Neįgalinta jokių spausdinimo paslaugų"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Atšaukiama: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Spausdintuvo klaida: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Spausdintuvas užblokavo: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduotis</item>
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduotys</item>
- <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduoties</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> spausdinimo užduočių</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Atšaukti"</string>
<string name="restart" msgid="2472034227037808749">"Paleisti iš naujo"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nėra ryšio su spausdintuvu"</string>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 5c17efe..762d0bd 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -62,6 +62,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> — <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Plašāka informācija par šo printeri"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Daži drukas pakalpojumi ir atspējoti."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Izvēlieties drukāšanas pakalpojumu"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printeru meklēšana"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nav iespējots neviens drukas pakalpojums"</string>
@@ -70,11 +71,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Pārtrauc drukas darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printera kļūda ar darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printeris bloķēja darbu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="zero"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> drukas darbi</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> drukas darbs</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> drukas darbi</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Atcelt"</string>
<string name="restart" msgid="2472034227037808749">"Restartēt"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nav savienojuma ar printeri"</string>
diff --git a/packages/PrintSpooler/res/values-mk-rMK/strings.xml b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
index ebc1181..de6d3e9 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Повеќе информации за овој печатач"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Некои услуги за печатење се оневозможени."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Избери услуга печатење"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Пребарување печатачи"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Нема овозможени услуги за печатење"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> се откажува"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка при печатење <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Печатачот го блокираше <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> работа за печатење</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> работи за печатење</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Откажи"</string>
<string name="restart" msgid="2472034227037808749">"Рестартирај"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нема поврзување со печатач"</string>
diff --git a/packages/PrintSpooler/res/values-ml-rIN/strings.xml b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
index c08a3d4..7a33e14 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ഈ പ്രിന്ററിനെ കുറിച്ചുള്ള കൂടുതൽ വിവരങ്ങൾ"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"ചില പ്രിന്റ് സേവനങ്ങൾ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു."</string>
<string name="choose_print_service" msgid="3740309762324459694">"പ്രിന്റ് സേവനം തിരഞ്ഞെടുക്കുക"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"പ്രിന്ററുകൾക്കായി തിരയുന്നു"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"പ്രിന്റ് സേവനങ്ങളൊന്നും പ്രവർത്തനക്ഷമാക്കിയിട്ടില്ല"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> റദ്ദാക്കുന്നു"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"പ്രിന്റർ പിശക് <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"പ്രിന്റർ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> തടഞ്ഞു"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> പ്രിന്റ് ജോലികൾ</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> പ്രിന്റ് ജോലി</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"റദ്ദാക്കുക"</string>
<string name="restart" msgid="2472034227037808749">"പുനരാരംഭിക്കുക"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"പ്രിന്ററിൽ കണക്ഷനൊന്നുമില്ല"</string>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index dcef28f..c94e56d 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Энэ хэвлэгчийн талаарх дэлгэрэнгүй мэдээлэл"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Зарим хэвлэх үйлчилгээг идэвхгүй болгосон байна."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Хэвлэх үйлчилгээг сонгох"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтер хайж байна"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Хэвлэх үйлчилгээг идэвхжүүлээгүй"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Цуцлаж байна <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Принтерийн алдаа <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Принтер хориглогдсон <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ажлыг хэвлэх</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ажлыг хэвлэх</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Цуцлах"</string>
<string name="restart" msgid="2472034227037808749">"Дахин эхлүүлэх"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Принтер холбогдоогүй байна"</string>
diff --git a/packages/PrintSpooler/res/values-mr-rIN/strings.xml b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
index 384f0de..ab25010 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"या प्रिंटर विषयी अधिक माहिती"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"काही मुद्रण सेवा अक्षम केल्या आहेत."</string>
<string name="choose_print_service" msgid="3740309762324459694">"मुद्रण सेवा निवडा"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर शोधत आहे"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"कोणत्याही मुद्रण सेवा सक्षम केलेल्या नाहीत"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> रद्द करीत आहे"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिंटर त्रुटी <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिंटरने <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> अवरोधित केले"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> मुद्रण कार्य</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> मुद्रण कार्ये</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"रद्द करा"</string>
<string name="restart" msgid="2472034227037808749">"रीस्टार्ट करा"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिंटरवर कोणतेही कनेक्शन नाही"</string>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 19a6e76..917ae8a 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Maklumat lanjut tentang pencetak ini"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Sesetengah perkhidmatan cetak dilumpuhkan."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Pilih perkhidmatan cetak"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari pencetak"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Perkhidmatan cetak tidak didayakan"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Membatalkan <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ralat pencetak <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Pencetak disekat <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Kerja cetakan <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Kerja cetakan <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Batal"</string>
<string name="restart" msgid="2472034227037808749">"Mulakan semula"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Tiada sambungan ke pencetak"</string>
diff --git a/packages/PrintSpooler/res/values-my-rMM/strings.xml b/packages/PrintSpooler/res/values-my-rMM/strings.xml
index d3c0672..4d4c95b 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ဤပရင်တာ အကြောင်း ပိုမိုလေ့လာပါ"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"ပရင့်ထုတ်ရေး အချို့ဝန်ဆောင်မှုများကို ပိတ်ထားပါသည်။"</string>
<string name="choose_print_service" msgid="3740309762324459694">"စာထုတ်ရန် ဝန်ဆောင်မှုကို ရွေးချယ်ပါ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"စာထုတ်စက်များကို ရှာနေပါသည်"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ပုံနှိပ်ထုတ်ယူရေး ဝန်ဆောင်မှုများ ဖွင့်မထားပါ"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ကို ပယ်ဖျက်နေပါသည်"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"စာထုတ်စက်မှ အမှား <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ကိုစာထုတ်စက်ကငြင်းလိုက်သည်"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> စာထုတ်စရာများ</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>စာထုတ်စရာ</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"ပယ်ဖျက်"</string>
<string name="restart" msgid="2472034227037808749">"အစက ပြန်စရန်"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"စာထုတ်စက်နဲ့ ဆက်သွယ်ထားမှု မရှိပါ"</string>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index c34e7bc..9efa5d1 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mer informasjon om denne printeren"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Noen utskriftstjenester er slått av."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Velg utskriftstjeneste"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Søker etter skrivere"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ingen utskriftstjenester er slått på"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Skriverfeil <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Skriveren blokkerte <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> utskriftsjobber</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> utskriftsjobb</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Avbryt"</string>
<string name="restart" msgid="2472034227037808749">"Start på nytt"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen forbindelse med skriveren"</string>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index d1959d9..281a65d 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"यस प्रिन्टरको बारेमा थप जानकारी"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"केही मुद्रण सेवाहरू असक्षम छन्।"</string>
<string name="choose_print_service" msgid="3740309762324459694">"प्रिन्ट सेवा छनौट गर्नुहोस्"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिन्टरहरू खोज्दै"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"कुनै पनि मुद्रण सेवाहरू सक्रिय छैनन्"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"रद्द गरिँदै <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिन्टर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिन्टर ब्लक गरियो <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> कार्यहरू प्रिन्ट गर्नुहोस्</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> कार्य प्रिन्ट गर्नुहोस्</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"रद्द गर्नुहोस्"</string>
<string name="restart" msgid="2472034227037808749">"पुनःस्टार्ट गर्नुहोस्"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिन्टरमा कुनै जडान छैन"</string>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 5df3298..eef9880 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Meer informatie over deze printer"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Sommige afdrukservices zijn uitgeschakeld."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Afdrukservice kiezen"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printers zoeken"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Geen afdrukservices ingeschakeld"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> annuleren"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printerfout <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> geblokkeerd door printer"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> afdruktaken</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> afdruktaak</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Annuleren"</string>
<string name="restart" msgid="2472034227037808749">"Opnieuw starten"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Geen verbinding met printer"</string>
diff --git a/packages/PrintSpooler/res/values-pa-rIN/strings.xml b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
index 57e9969..7d7860c 100644
--- a/packages/PrintSpooler/res/values-pa-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ਇਸ ਪ੍ਰਿੰਟਰ ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"ਕੁਝ ਪ੍ਰਿੰਟ ਸੇਵਾਵਾਂ ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਹਨ।"</string>
<string name="choose_print_service" msgid="3740309762324459694">"ਪ੍ਰਿੰਟ ਸੇਵਾ ਚੁਣੋ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ਪ੍ਰਿੰਟਰ ਖੋਜ ਰਿਹਾ ਹੈ"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ਪ੍ਰਿੰਟ ਸੇਵਾਵਾਂ ਯੋਗ ਨਹੀਂ ਬਣਾਈਆਂ ਗਈਆਂ"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ਨੂੰ ਰੱਦ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ਪ੍ਰਿੰਟਰ ਅਸ਼ੁੱਧੀ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"ਪ੍ਰਿੰਟਰ ਬਲੌਕ ਕੀਤਾ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ਪ੍ਰਿੰਟ ਜੌਬਸ</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ਪ੍ਰਿੰਟ ਜੌਬਸ</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"ਰੱਦ ਕਰੋ"</string>
<string name="restart" msgid="2472034227037808749">"ਰੀਸਟਾਰਟ ਕਰੋ"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ਪ੍ਰਿੰਟਰ ਲਈ ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 4439acb..6837edf 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Więcej informacji o tej drukarce"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Niektóre usługi drukowania są wyłączone."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Wybierz usługę drukowania"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Szukanie drukarek"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Brak włączonych usług drukowania"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Anulowanie: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Błąd drukarki: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Drukarka zablokowała <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadania drukowania</item>
- <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadań drukowania</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> zadania drukowania</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> zadanie drukowania</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Anuluj"</string>
<string name="restart" msgid="2472034227037808749">"Od nowa"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Brak połączenia z drukarką"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rBR/strings.xml b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
index 63bb868..c9713c9 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mais informações sobre essa impressora"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alguns serviços de impressão estão desativados."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Selecione o serviço de impressão"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Procurando impressoras"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nenhum serviço de impressão ativado"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro ao imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A impressora bloqueou <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one">Tarefas de impressão <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">Tarefas de impressão <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem conexão com a impressora"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index d364ef4..9fabc0f 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mais informações acerca desta impressora"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alguns serviços de impressão estão desativados."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Escolher o serviço de impressão"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"A procurar impressoras"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nenhum serviço de impressão ativado"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"A cancelar <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro da impressora <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A impressora bloqueou <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tarefas de impressão</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tarefa de impressão</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem ligação à impressora"</string>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 63bb868..c9713c9 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mais informações sobre essa impressora"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Alguns serviços de impressão estão desativados."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Selecione o serviço de impressão"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Procurando impressoras"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nenhum serviço de impressão ativado"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Cancelando <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Erro ao imprimir <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"A impressora bloqueou <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one">Tarefas de impressão <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">Tarefas de impressão <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Cancelar"</string>
<string name="restart" msgid="2472034227037808749">"Reiniciar"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Sem conexão com a impressora"</string>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 51dfe7a..7364eb0 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -62,6 +62,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mai multe informații despre această imprimantă"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Unele servicii de printare sunt dezactivate."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Alegeți serviciul de printare"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Se caută imprimante"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Niciun serviciu de printare activat"</string>
@@ -70,11 +71,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Se anulează <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Eroare de printare: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printare blocată: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> activități de printare</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> de activități de printare</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> activitate de printare</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Anulați"</string>
<string name="restart" msgid="2472034227037808749">"Reporniți"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Nu există conexiune la o imprimantă"</string>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index 6ba1046..bb03860 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Подробные сведения о принтере"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Некоторые сервисы печати отключены."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Выберите службу печати"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Поиск принтеров…"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Службы печати недоступны"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Отмена задания <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>…"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Ошибка задания \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Задание \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" заблокировано"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="few">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="many">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">Задания печати: <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Отмена"</string>
<string name="restart" msgid="2472034227037808749">"Повторить"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нет связи с принтером"</string>
diff --git a/packages/PrintSpooler/res/values-si-rLK/strings.xml b/packages/PrintSpooler/res/values-si-rLK/strings.xml
index 4908ea5..610442d 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"මෙම මුද්රණ යන්ත්රය ගැන තවත් තොරතුරු"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"සමහර මුද්රණ සේවා අබලයි."</string>
<string name="choose_print_service" msgid="3740309762324459694">"මුද්රණ සේවාව තෝරන්න"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"මුද්රණ යන්ත්ර සොයමින්"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"මුද්රණ සේවා සබල නැත"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"අවලංගු කෙරේ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"මුද්රණ දෝෂය <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"මුද්රණ යන්ත්රය <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> අවුරා ඇති"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one">මුද්රණ කාර්ය <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">මුද්රණ කාර්ය <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"අවලංගු කරන්න"</string>
<string name="restart" msgid="2472034227037808749">"යළි අරඹන්න"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"මුද්රණ යන්ත්රය වෙත සම්බන්ධය නැත"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 418363d..603d1d2 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Ďalšie informácie o tejto tlačiarni"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Niektoré tlačové služby sú vypnuté."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Výber tlačovej služby"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhľadávanie tlačiarní"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Žiadne tlačové služby nie sú aktivované"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Prebieha zrušenie úlohy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Chyba tlačiarne – úloha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tlačiareň zablok. úlohu <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tlačové úlohy</item>
- <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tlačovej úlohy</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tlačových úloh</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> tlačová úloha</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Zrušiť"</string>
<string name="restart" msgid="2472034227037808749">"Spustiť znova"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Žiadne pripojenie k tlačiarni"</string>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index e2be161..4a08269 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Več informacij o tem tiskalniku"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Nekatere tiskalne storitve so onemogočene."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Izberite tiskalno storitev"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Iskanje tiskalnikov"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ni omogočenih tiskalnih storitev"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Preklic: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Napaka tiskalnika: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Tiskalnik je blokiral <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalno opravilo</item>
- <item quantity="two"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalni opravili</item>
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalna opravila</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> tiskalnih opravil</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Prekliči"</string>
<string name="restart" msgid="2472034227037808749">"Začni znova"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ni povezave s tiskalnikom"</string>
diff --git a/packages/PrintSpooler/res/values-sq-rAL/strings.xml b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
index d5ebf32..b0902ef 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Më shumë informacione mbi këtë printer"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Disa shërbime printimi janë çaktivizuar."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Zgjidh shërbimin e printimit"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Po kërkon për printerë"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Nuk ka shërbime printimi të aktivizuara"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Po anulon <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri ndeshi në gabim gjatë punës: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printeri bllokoi <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> punë për printim</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> punë për printim</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Anulo"</string>
<string name="restart" msgid="2472034227037808749">"Rifillo"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printeri nuk është i lidhur"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 166e5dd..feb2940 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -62,6 +62,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Још информација о овом штампачу"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Неке услуге штампања су онемогућене."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Изаберите услугу штампања"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Претрага штампача"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Ниједна услуга штампања није омогућена"</string>
@@ -70,11 +71,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Отказује се <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка штампача <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Штампач је блокирао <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one">Задаци штампања <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="few">Задаци штампања <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="other">Задаци штампања <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Откажи"</string>
<string name="restart" msgid="2472034227037808749">"Поново покрени"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Нема везе са штампачем"</string>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index 033d583..cf398c7 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mer information om den här skrivaren"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Några utskriftstjänster har inaktiverats."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Välj utskriftstjänst"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Söker efter skrivare"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Inga utskriftstjänster har aktiverats"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Avbryter <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Skrivarfel för <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Skrivaren har blockerat <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> utskriftsjobb</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> utskriftsjobb</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Avbryt"</string>
<string name="restart" msgid="2472034227037808749">"Starta om"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Ingen anslutning till skrivaren"</string>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 0e2dcdd..7e00b70 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Maelezo zaidi kuhusu printa hii"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Baadhi ya huduma za uchapishaji zimezimwa."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Chagua huduma ya printa"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Inatafuta printa"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Huduma za kuchapisha hazijawashwa"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Inaghairi <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Hitilafu ya kuchapisha <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printa imefungwa <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Kazi ya kuchapisha ya <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Kazi ya kuchapisha ya <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> </item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Ghairi"</string>
<string name="restart" msgid="2472034227037808749">"Anzisha upya"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hakuna muunganisho kwa printa"</string>
diff --git a/packages/PrintSpooler/res/values-ta-rIN/strings.xml b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
index 2e90d38..ae0b774 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"இந்தப் பிரிண்டர் பற்றிய கூடுதல் தகவல்"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"சில அச்சுப் பொறிகள் முடக்கப்பட்டன."</string>
<string name="choose_print_service" msgid="3740309762324459694">"அச்சுப் பொறியைத் தேர்வுசெய்யவும்"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"அச்சுப்பொறிகளைத் தேடுகிறது"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"அச்சுப் பொறிகள் இல்லை"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ஐ ரத்துசெய்கிறது"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"பிரிண்டர் பிழை <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"பிரிண்டர் <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ஐத் தடுத்தது"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> அச்சுப் பணிகள்</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> அச்சுப் பணி</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"ரத்துசெய்"</string>
<string name="restart" msgid="2472034227037808749">"மீண்டும் தொடங்கு"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"அச்சுப்பொறியுடன் இணைக்கப்படவில்லை"</string>
diff --git a/packages/PrintSpooler/res/values-te-rIN/strings.xml b/packages/PrintSpooler/res/values-te-rIN/strings.xml
index 6bdbd5c..5fd8d60 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ఈ ప్రింటర్ గురించి మరింత సమాచారం"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"కొన్ని ముద్రణ సేవలు నిలిపివేయబడ్డాయి."</string>
<string name="choose_print_service" msgid="3740309762324459694">"ముద్రణ సేవను ఎంచుకోండి"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ప్రింటర్ల కోసం శోధిస్తోంది"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ముద్రణ సేవలు ఏవీ ప్రారంభించలేదు"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను రద్దు చేస్తోంది"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ప్రింటర్ లోపం <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"ప్రింటర్ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను బ్లాక్ చేసింది"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ముద్రణ జాబ్లు</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> ముద్రణ జాబ్</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"రద్దు చేయి"</string>
<string name="restart" msgid="2472034227037808749">"పునఃప్రారంభించు"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ప్రింటర్కు కనెక్షన్ లేదు"</string>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index a581357..ebd5e2a 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ข้อมูลเพิ่มเติมเกี่ยวกับเครื่องพิมพ์นี้"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"บริการพิมพ์บางอย่างถูกปิดใช้"</string>
<string name="choose_print_service" msgid="3740309762324459694">"เลือกบริการพิมพ์"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"กำลังค้นหาเครื่องพิมพ์"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"ไม่ได้เปิดใช้บริการพิมพ์"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"กำลังยกเลิก <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"ข้อผิดพลาดเครื่องพิมพ์ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"เครื่องพิมพ์ได้บล็อก <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> งานพิมพ์</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> งานพิมพ์</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"ยกเลิก"</string>
<string name="restart" msgid="2472034227037808749">"เริ่มต้นใหม่"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"ไม่มีการเชื่อมต่อไปยังเครื่องพิมพ์"</string>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index 325ce8c..ebe869b 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Higit pang impormasyon tungkol sa printer na ito"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Naka-disable ang ilang serbisyo sa pag-print."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Pumili ng serbisyo ng pag-print"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Naghahanap ng mga printer"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Walang mga naka-enable na serbisyo sa pag-print"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Kinakansela ang <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Error sa printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Naka-block ang Printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> ipi-print</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> na ipi-print</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Kanselahin"</string>
<string name="restart" msgid="2472034227037808749">"I-restart"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hindi nakakonekta sa printer"</string>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index d945979..9cd42ab 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Bu yazıcıyla ilgili daha fazla bilgi"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Bazı yazdırma hizmetleri devre dışı."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Yazdırma hizmetini seçin"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Yazıcılar aranıyor"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Etkin yazıcı hizmeti yok"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> iptal ediliyor"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Yazıcı hatası: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Yazıcı <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> işini engelledi"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> yazdırma işi</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> yazdırma işi</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"İptal"</string>
<string name="restart" msgid="2472034227037808749">"Yeniden başlat"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Yazıcı bağlantısı yok"</string>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index ffdfde0..1082147 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -63,6 +63,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Докладніше про цей принтер"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Деякі служби друку вимкнено."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Вибрати службу друку"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Пошук принтерів"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Немає служб друку"</string>
@@ -71,12 +72,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" скасовується"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Помилка завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\""</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Завдання \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" заблоковано"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдання друку</item>
- <item quantity="few"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдання друку</item>
- <item quantity="many"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдань друку</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> завдань друку</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Скасувати"</string>
<string name="restart" msgid="2472034227037808749">"Перезапустити"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Немає з’єднання з принтером"</string>
diff --git a/packages/PrintSpooler/res/values-ur-rPK/strings.xml b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
index 72a6ab9f..56f1093 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"اس پرنٹر کے بارے میں مزید معلومات"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"پرنٹ کی کچھ سروسز غیر فعال ہیں۔"</string>
<string name="choose_print_service" msgid="3740309762324459694">"پرنٹ سروس منتخب کریں"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"پرنٹرز تلاش کر رہا ہے"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"کوئی پرنٹ سروس فعال نہیں"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> کو منسوخ کر رہا ہے"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"پرنٹر کی خرابی <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"پرنٹر نے <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> کو مسدود کر دیا"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> پرنٹ جابز</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> پرنٹ جاب</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"منسوخ کریں"</string>
<string name="restart" msgid="2472034227037808749">"دوبارہ شروع کریں"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"پرنٹر کے ساتھ کوئی کنکشن نہیں ہے"</string>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index c7b4263..30b218e 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Printer haqida batafsil ma’lumot"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Bir qancha chop etish xizmatlari o‘chirilgan."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Chop etish xizmatini tanlang"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printerlar qidirilmoqda"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Hech qaysi chop etish xizmati yoqilmagan"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bekor qilinmoqda"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printerda xatolik: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printer <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ni taqiqladi"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> chop qilish vazifalari</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> chop qilish vazifasi</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Bekor qilish"</string>
<string name="restart" msgid="2472034227037808749">"Qayta boshlash"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Printer ulanmagan"</string>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index 771d57c..32aaf63 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Thông tin khác về máy in này"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Một số dịch vụ in bị vô hiệu hóa."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Chọn dịch vụ in"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Đang tìm kiếm máy in"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Chưa kích hoạt dịch vụ in nào"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Hủy <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Lỗi máy in <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Máy in đã chặn <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">Lệnh in <xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g></item>
- <item quantity="one">Lệnh in <xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g></item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Hủy"</string>
<string name="restart" msgid="2472034227037808749">"Bắt đầu lại"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Không có kết nối nào với máy in"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index bea91d7..42cf3b1 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"关于此打印机的更多信息"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"部分打印服务已停用。"</string>
<string name="choose_print_service" msgid="3740309762324459694">"选择打印服务"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜索打印机"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"未启用任何打印服务"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"打印机在打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”时出错"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"打印机拒绝打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other">“<xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g>”打印作业</item>
- <item quantity="one">“<xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g>”打印作业</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"取消"</string>
<string name="restart" msgid="2472034227037808749">"重新开始"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"未与打印机建立连接"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 4fbef0d..0a458ad 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"此打印機詳情"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"已停用部分列印服務。"</string>
<string name="choose_print_service" msgid="3740309762324459694">"選擇列印服務"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋打印機"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"沒有已啟用的列印服務"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"打印機錯誤:<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"打印機已封鎖 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> 項列印工作</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> 項列印工作</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"取消"</string>
<string name="restart" msgid="2472034227037808749">"重新開始"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"尚未與打印機連線"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 2fdcaac..7a30011 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"查看這台印表機的詳細資訊"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"部分列印服務已停用。"</string>
<string name="choose_print_service" msgid="3740309762324459694">"選擇列印服務"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋印表機"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"未啟用任何列印服務"</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"印表機發生錯誤:<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"印表機封鎖了 <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> 個列印工作</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> 個列印工作</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"取消"</string>
<string name="restart" msgid="2472034227037808749">"重新開始"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"尚未與印表機建立連線"</string>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index 92595aa..f57b58c 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -61,6 +61,7 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Olunye ulwazi mayelana nale phrinta"</string>
+ <string name="print_services_disabled_toast" msgid="1205302482388937547">"Amanye amasevisi wokuphrinta akhutshaziwe."</string>
<string name="choose_print_service" msgid="3740309762324459694">"Khetha isevisi yephrinta"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Isesha amaphrinta"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Amasevisi ephrinta akavuliwe."</string>
@@ -69,10 +70,6 @@
<string name="cancelling_notification_title_template" msgid="1821759594704703197">"Ikhansela i-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="failed_notification_title_template" msgid="2256217208186530973">"Iphutha lephrinta ye-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Iphrinta engu-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> ivinjelwe"</string>
- <plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> imisebenzi yokuphrinta</item>
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> imisebenzi yokuphrinta</item>
- </plurals>
<string name="cancel" msgid="4373674107267141885">"Khansela"</string>
<string name="restart" msgid="2472034227037808749">"Qala kabusha"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"Akukho ukuxhumana kuphrinta"</string>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index b662c58..76292a1 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -150,6 +150,9 @@
<!-- Description of printer info icon. [CHAR LIMIT=50] -->
<string name="printer_info_desc">More information about this printer</string>
+ <!-- Notification that print services as disabled. [CHAR LIMIT=50] -->
+ <string name="print_services_disabled_toast">Some print services are disabled.</string>
+
<!-- Add printer dialog -->
<!-- Title for the alert dialog for selecting a print service. [CHAR LIMIT=50] -->
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index ea11ae4..684a1de 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -173,15 +173,19 @@
if (DEBUG) {
Log.i(LOG_TAG, "[CALLED] start()");
}
- if (mState != STATE_INITIAL) {
- throw new IllegalStateException("Cannot start in state:" + stateToString(mState));
- }
- try {
- mPrintDocumentAdapter.start();
- mState = STATE_STARTED;
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error calling start()", re);
- mState = STATE_FAILED;
+ if (mState == STATE_FAILED) {
+ Log.w(LOG_TAG, "Failed before start.");
+ } else {
+ if (mState != STATE_INITIAL) {
+ throw new IllegalStateException("Cannot start in state:" + stateToString(mState));
+ }
+ try {
+ mPrintDocumentAdapter.start();
+ mState = STATE_STARTED;
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error calling start()", re);
+ mState = STATE_FAILED;
+ }
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index 5525774..cd30e26 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -207,6 +207,7 @@
PrinterInfo favoritePrinter = favoritePrinters.get(i).first;
if (!alreadyAddedPrinter.contains(favoritePrinter.getId())) {
updateAndAddPrinter(printers, favoritePrinter, discoveredPrinters);
+ alreadyAddedPrinter.add(favoritePrinter.getId());
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 81727ab..13105aa 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -65,6 +65,7 @@
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.internal.content.PackageMonitor;
import com.android.printspooler.R;
@@ -147,6 +148,14 @@
});
registerForContextMenu(mListView);
+
+ // Display a notification about disabled services if there are disabled services
+ String disabledServicesSetting = Settings.Secure.getString(getContentResolver(),
+ Settings.Secure.DISABLED_PRINT_SERVICES);
+ if (!TextUtils.isEmpty(disabledServicesSetting)) {
+ Toast.makeText(this, getString(R.string.print_services_disabled_toast),
+ Toast.LENGTH_LONG).show();
+ }
}
@Override
diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/ApprovedPrintServices.java b/packages/PrintSpooler/src/com/android/printspooler/util/ApprovedPrintServices.java
index a1e3ef4..f781159 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/util/ApprovedPrintServices.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/util/ApprovedPrintServices.java
@@ -134,6 +134,11 @@
public void pruneApprovedServices(List<ComponentName> serviceNamesToKeep) {
synchronized (sLock) {
Set<String> approvedServices = getApprovedServices();
+
+ if (approvedServices == null) {
+ return;
+ }
+
Set<String> newApprovedServices = new ArraySet<>(approvedServices.size());
final int numServiceNamesToKeep = serviceNamesToKeep.size();
diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk
index c860668..2189b55 100644
--- a/packages/SettingsLib/Android.mk
+++ b/packages/SettingsLib/Android.mk
@@ -3,9 +3,22 @@
LOCAL_MODULE := SettingsLib
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-v4 \
+ android-support-v7-recyclerview \
+ android-support-v7-preference \
+ android-support-v7-appcompat \
+ android-support-v14-preference
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
+ frameworks/support/v7/preference/res \
+ frameworks/support/v14/preference/res \
+ frameworks/support/v7/appcompat/res \
+ frameworks/support/v7/recyclerview/res
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_AAPT_FLAGS := --auto-add-overlay \
+ --extra-packages android.support.v7.preference:android.support.v14.preference:android.support.v17.preference:android.support.v7.appcompat:android.support.v7.recyclerview
+
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml b/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
new file mode 100644
index 0000000..b3d7cf9
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_settings_lock_outline.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="21dp"
+ android:height="21dp"
+ android:viewportWidth="21.0"
+ android:viewportHeight="21.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8,16c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S6.9,16,8,16zM14,7h-1V5c0-2.8-2.2-5-5-5S3,2.2,3,5v2H2C0.9,7,0,7.9,0,9v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V9C16,7.9,15.1,7,14,7z M4.9,5c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H4.9V5z M14,19H2V9h12V19z" />
+</vector>
diff --git a/packages/SettingsLib/res/layout/spinner_dropdown_restricted_item.xml b/packages/SettingsLib/res/layout/spinner_dropdown_restricted_item.xml
new file mode 100644
index 0000000..f7a9c9f
--- /dev/null
+++ b/packages/SettingsLib/res/layout/spinner_dropdown_restricted_item.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ style="?android:attr/spinnerDropDownItemStyle"
+ android:singleLine="true"
+ android:layout_width="wrap_content"
+ android:layout_height="?android:attr/listPreferredItemHeightSmall"
+ android:ellipsize="marquee" />
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index ebe8752..30a3b59 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -247,8 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Laat enige program na ekstern geskryf word, ongeag manifeswaardes"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Verplig verstelbare groottes vir aktiwiteite"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Maak grootte van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string>
- <string name="enable_freeform_support" msgid="1461893351278940416">"Aktiveer vormvrye vensters"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiveer steun vir eksperimentele vormvrye vensters."</string>
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Aktiveer vormvrye-Windows"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiveer steun vir eksperimentele vormvrye-Windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Werkskerm-rugsteunwagwoord"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Volle rekenaarrugsteune word nie tans beskerm nie"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Raak om die wagwoord vir volledige rekenaarrugsteune te verander of te verwyder"</string>
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Outomaties"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stel WebView-implementering"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Skakel om na lêerenkripsie"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Skakel om …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Lêerenkripsie is reeds uitgevoer"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurregstelling"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – sowat <xliff:g id="TIME">%2$s</xliff:g> oor"</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> tot vol"</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> tot vol op WS"</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> tot vol oor USB"</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> tot vol vanaf draadloos"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laai tans oor USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laai tans draadloos"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index e33d0fa..beac0a1 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ራስ-ሰር"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"የWebView ትግበራ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"የWebView ትግበራን ያዘጋጁ"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"የተመረጠው WebView ትግበራ ተሰናክሏል፣ እና ጥቅም ላይ እንዲውል መንቃት አለበት፣ ሊያነቁት ይፈልጋሉ?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ወደ ፋይል ምሥጠራ ቀይር"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ለውጥ…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ፋይል አስቀድሞ ተመስጥሯል"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"የቀለም ማስተካከያ"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> በዩኤስቢ ላይ እስከሚሞላ ድረስ"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"በዩኤስቢ ሃይል በመሙላት ላይ"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"በገመድ አልባ ሃይል በመሙላት ላይ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 71761b9..2386cb6 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"تلقائيًا"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"تطبيق WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تعيين تطبيق WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"إن تنفيذ ميزة WebView التي تم اختيارها معطَّل، ويجب تمكين هذه الميزة ليتسنى استخدامها، فهل تريد تمكينها؟"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"التحويل إلى تشفير ملفات"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"تحويل…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"تم استخدام تشفير ملفات من قبل"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"تصحيح الألوان"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> حتى الاكتمال عبر USB"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"جارٍ الشحن عبر USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"جارٍ الشحن لاسلكيًا"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index b5a7181..273ea30 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Avtomatik"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView icrası"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView icrasını ayarlayın"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Seçilmiş WebView icrası deaktiv edildi, istifadəsi üçün aktiv edilməlidir, aktivləşdirmək istəyirsiniz?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Fayl şifrələnməsinə çevirin"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Çevirin..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fayl artıq şifrələnib"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rəng düzəlişi"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB üzərindən qidalanır"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Naqilsiz qidalanır"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 54d2dfa..5d8b934 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Prinudno omogući promenu veličine aktivnosti"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Omogućava promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore proizvoljnog formata"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogućava podršku za eksperimentalne prozore proizvoljnog formata."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Lozinka rezervne kopije za računar"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Rezervne kopije čitavog sistema trenutno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Dodirnite da biste promenili ili uklonili lozinku za pravljenje rezervnih kopija čitavog sistema na računaru"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatski"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Primena WebView-a"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesite primenu WebView-a"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuj u šifrovanje datoteka"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuj..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Već se koristi šifrovanje datoteka"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boja"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – preostalo oko <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> dok se ne napuni"</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> dok se ne napuni punjačem"</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> dok se ne napuni preko USB-a"</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> dok se ne napuni bežično"</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 preko punjača"</string>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično 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">"Puno"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 95badc5..e5dbf50 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Позволява прилож. да се записват във външ. хранил. независимо от стойностите в манифеста"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Възможност за преоразмеряване на активностите"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Активиране на прозорците в свободна форма"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Активира поддръжката за експерименталните прозорци в свободна форма."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Наст. комп.: Парола"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Понастоящем пълните резервни копия за настолен компютър не са защитени"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Докоснете, за да промените или премахнете паролата за пълни резервни копия на настолния компютър"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Автоматично"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Внедряване на WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Задаване на внедряването на WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Преобразуване към шифроване на ниво файл"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Преобразуване…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Данните вече са шифровани на ниво файл"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекция на цветове"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> до пълно зареждане през USB"</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="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_usb" msgid="2207489369680923929">"Зареждане през USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично зареждане"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index e4d97d7..9e42f71 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলিকে আকার পরিবর্তনযোগ্য করে তোলে৷"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"ফ্রি-ফর্ম উইন্ডোগুলি সক্ষম করুন"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"পরীক্ষামূলক ফ্রি-ফর্ম উইন্ডোগুলির জন্য সহায়তা সক্ষম করুন৷"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ডেস্কটপ ব্যাকআপ পাসওয়ার্ড"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ডেস্কটপ পূর্ণ ব্যাকআপ বর্তমানে সুরক্ষিত নয়"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"ডেস্কটপ পুরো ব্যাকআপের জন্য পাসওয়ার্ড পরিবর্তন বা মুছে ফেলার জন্য স্পর্শ করুন"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"স্বয়ংক্রিয়"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"ওয়েবভিউ প্রয়োগ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ওয়েবভিউ প্রয়োগ সেট করুন"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"নির্বাচিত ওয়েবভিউ প্রয়োগটি অক্ষম করা আছে এবং ব্যবহার করার জন্য অবশ্যই সক্ষম করতে হবে, আপনি কি এটিকে সক্ষম করতে চান?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ফাইল এনক্রিপশান রূপান্তর করুন"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"রূপান্তর করুন..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ফাইল ইতিমধ্যেই এনক্রিপ্ট করা রয়েছে"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"রঙ সংশোধন"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_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_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_wireless" msgid="1829295708243159464">"<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_usb" msgid="2207489369680923929">"USB এর মাধ্যমে চার্জ হচ্ছে"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"তারবিহীনভাবে চার্জ হচ্ছে"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 93b6438..2f81098 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet que les aplicacions es puguin escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Activa les finestres de format lliure"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activa la compatibilitat amb les finestres de format lliure experimentals."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contrasenya per a còpies d\'ordinador"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les còpies de seguretat d\'ordinador completes no estan protegides"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Toca per canviar o eliminar la contrasenya per a còpies de seguretat d\'ordinador completes"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automàtic"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementació de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configura la implementació de WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La implementació de WebView que has triat està desactivada i s\'ha d\'activar per utilitzar-la. Vols activar-la?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteix en l\'encriptació de fitxers"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteix…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"El fitxer ja està encriptat"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correcció del color"</string>
<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_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_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_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_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_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="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_usb" msgid="2207489369680923929">"Càrrega per USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Càrrega sense fils"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index beb8f94..f1c9e27 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatický"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementace WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavte implementaci WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Vybraná implementace WebView je zakázána a nelze ji použít. Chcete ji povolit a použít?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Převést na šifrování souborů"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Převést…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Obsah je již na úrovni souborů zašifrován"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekce barev"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjení přes USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrátové nabíjení"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 3923dbd..90ea69a 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatisk"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Konfigurer WebView-implementering"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte WebView-implementering er deaktiveret og skal aktiveres, før den kan bruges. Vil du aktivere den?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertér til filkryptering"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede filkrypteret"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korriger farver"</string>
<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_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_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_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_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_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="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_usb" msgid="2207489369680923929">"Opladning via USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Trådløs opladning"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 0b1238b..8d95ddf 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Anpassen der Größe von Aktivitäten erzwingen"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Ermöglicht es, die Größe aller Aktivitäten an den Mehrfenstermodus anzupassen, unabhängig von den Manifestwerten."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Freiform-Fenster zulassen"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Unterstützt experimentelle Freiform-Fenster."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop-Sicherungspasswort"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Vollständige Desktop-Sicherungen sind momentan nicht passwortgeschützt."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Zum Ändern oder Entfernen des Passworts für vollständige Desktop-Sicherungen berühren"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatisch"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-Implementierung"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-Implementierung festlegen"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Zu Dateiverschlüsselung wechseln"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Wechseln…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dateiverschlüsselung wird bereits verwendet."</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Farbkorrektur"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch etwa <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> – voll in <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> – bei Stromanschluss voll in <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> – über USB voll in <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> – bei kabellosem Laden voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laden über USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kabelloses Laden"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index c3acca7..303f0e5 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Αυτόματο"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Υλοποίηση WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ορισμός υλοποίησης WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Μετατροπή σε κρυπτογράφηση αρχείου"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Μετατροπή…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Με κρυπτογράφηση αρχείου"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Διόρθωση χρωμάτων"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση με φορτιστή AC"</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> για πλήρη φόρτιση μέσω USB"</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="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_usb" msgid="2207489369680923929">"Φόρτιση μέσω USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ασύρματη φόρτιση"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index dae40d9..b938ace 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Touch to change or remove the password for desktop full backups"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</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> until full"</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> until full on AC"</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> until full over USB"</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> until full from wireless"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index dae40d9..b938ace 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Touch to change or remove the password for desktop full backups"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</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> until full"</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> until full on AC"</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> until full over USB"</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> until full from wireless"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index dae40d9..b938ace 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Makes all activities re-sizable for multi-window, regardless of manifest values."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Enables support for experimental freeform windows."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop backup password"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Desktop full backups aren\'t currently protected"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Touch to change or remove the password for desktop full backups"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatic"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"The chosen WebView implementation is disabled and must be enabled to be used, do you wish to enable it?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convert to file encryption"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convert…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Already file encrypted"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Colour correction"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – approx. <xliff:g id="TIME">%2$s</xliff:g> left"</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> until full"</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> until full on AC"</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> until full over USB"</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> until full from wireless"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 855b72c..9ddc03f 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Cualquier aplicación puede escribirse en una memoria externa, independientemente de los valores del manifiesto."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Habilita la admisión de ventanas de forma libre experimentales."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Contraseñas"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Tus copias de seguridad de escritorio no están protegidas por contraseña."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Toca para cambiar o eliminar la contraseña de las copias de seguridad completas de tu escritorio."</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar la implementación de WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a encriptación de archivo"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está encriptado"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección de color"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carga con USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carga inalámbrica"</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 realiza la carga"</string>
+ <string name="battery_info_status_full" msgid="2824614753861462808">"Cargado"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 858c1b6..f0682c2 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Establecer implementación de WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a cifrado de archivo"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está cifrado"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección del color"</string>
<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_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_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_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_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_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="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_usb" msgid="2207489369680923929">"Cargando por USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando de forma inalámbrica"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 7f1056c..ff7d7ee 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automaatne"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView\' rakendamine"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView\' rakendamise seadistamine"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Teisendamine failikrüpteeringuga andmeteks"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Teisenda …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Juba failikrüpteeringuga"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värviparandus"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laadimine USB kaudu"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Juhtmevaba laadimine"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index fe5fc29..145e8f8 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifestuan jartzen duena jartzen duela ere, jarduera guztien tamaina doitzeko aukera ematen du, hainbat leihotan erabili ahal izan daitezen."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Gaitu estilo libreko leihoak"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Estilo libreko leiho esperimentalak onartzen ditu."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Tokiko babeskop. pasahitza"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Une honetan, ordenagailuko babeskopia osoak ez daude babestuta."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Ukitu ordenagailuko babeskopia osoak egiteko pasahitza aldatzeko edo kentzeko"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatikoa"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Desgaituta dago aukeratu den Web-ikustailearen inplementazioa. Erabili nahi izanez gero, gaitu egin behar duzu. Gaitu nahi al duzu?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Eman fitxategietan oinarritutako enkriptatzea"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Enkriptatu…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fitxategietan oinarritutako enkriptatzea dauka dagoeneko"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kolore-zuzenketa"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB bidez kargatzen"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hari gabe kargatzen"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e1a35f7..5380651 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"بدون توجه به مقادیر مانیفست، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیتها به قابل تغییر اندازه بودن"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"بدون درنظر گرفتن مقادیر مانیفست، همه فعالیتها را برای چندپنجره قابل تغییر اندازه میکند."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"فعال کردن پنجرههای آزاد"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"پشتیبانی برای پنجرههای آزاد آزمایشی را امکانپذیر میکند"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"گذرواژه پشتیبانگیری محلی"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"پشتیبانگیری کامل رایانه درحال حاضر محافظت نمیشود"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"برای تغییر یا حذف گذرواژه برای نسخههای پشتیبان کامل دسکتاپ لمس کنید"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"خودکار"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تنظیم اجرای WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"پیادهسازی WebView انتخابشده غیرفعال شده است و برای استفاده شدن باید فعال شود؛ میخواهید آن را فعال کنید؟"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"تبدیل به رمزگذاری برحسب فایل"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"تبدیل…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"از قبل به رمزگذاری بر حسب فایل تبدیل شده است"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"تصحیح رنگ"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> تا شارژ کامل از طریق USB"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"شارژ از طریق USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"شارژ به صورت بیسیم"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 498f204..f9fdb63 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mahdollistaa sovellusten tallentamisen ulkoiseen tall.tilaan luettelosta riippumatta"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Pakota kaikki toiminnot hyväksymään koon muutos"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Pakottaa kaikki toiminnot hyväksymään koon muuttamisen rinnakkaisnäkymään luettelon arvoista riippumatta."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Ota käyttöön vapaamuotoiset ikkunat"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ottaa käyttöön kokeellisten vapaamuotoisten ikkunoiden tuen."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Varmuuskop. salasana"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Tietokoneen kaikkien tietojen varmuuskopiointia ei ole tällä hetkellä suojattu"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Muuta tai vaihda tietokoneen kaikkien tietojen varmuuskopioinnin salasana koskettamalla"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automaattinen"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-käyttöönotto"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Määritä WebView-käyttöönotto"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Muunna tiedostojen salaukseksi"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Muunna…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Tiedostot on jo salattu."</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Värikorjaus"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – noin <xliff:g id="TIME">%2$s</xliff:g> jäljellä"</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> kunnes täynnä"</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> kunnes täynnä (laturilataus)"</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> kunnes täynnä (USB-lataus)"</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> kunnes täynnä (WiFi-lataus)"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-lataus"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Langaton lataus"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index b32bfb7..9f802ab 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet enreg. d\'applis sur espace stockage externe"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forcer les activités à être redimensionnables"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Active la compatibilité avec les fenêtres de forme libre expérimentales."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Mot de passe sauvegarde PC"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Appuyez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur PC."</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatique"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir en chiffrement basé sur un fichier"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Déjà chiffré par un fichier"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction des couleurs"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> %% – Temps restant : environ <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> %% (chargée à 100 %% dans <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> %% (charge complète sur c.a. dans <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> %% (chargée à 100 %% par USB dans <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> %% (chargée à 100 %% avec chargeur sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge par USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 0190454..6dabba8 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rend possible enregistrement de toute appli sur espace stockage externe, indépendamment valeurs fichier manifeste."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forcer possibilité de redimensionner les activités"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Active la compatibilité avec les fenêtres de forme libre expérimentales."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Mot de passe sauvegarde PC"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Les sauvegardes complètes sur PC ne sont pas protégées actuellement."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Appuyez pour modifier ou supprimer le mot de passe utilisé pour les sauvegardes complètes sur PC."</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatique"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"La mise en œuvre WebView sélectionnée est désactivée. Vous devez l\'activer pour l\'utiliser. Souhaitez-vous l\'activer ?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir en chiffrement basé sur un fichier"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Déjà chiffré via un fichier"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correction couleur"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <xliff:g id="TIME">%2$s</xliff:g> environ"</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> (chargée à 100 %% dans <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> (chargée à 100 %% sur secteur dans <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> (chargée à 100 %% via USB dans <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> (chargée à 100 %% sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge via USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 0efe805..0f0d13d 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementación de WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter no encriptado baseado en ficheiros"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Xa se encriptou o ficheiro"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corrección da cor"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - faltan aproximadamente <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 a carga"</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 a carga con CA"</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 a carga con USB"</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 a carga co modo sen fíos"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando sen fíos"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 4b72648..9e2ec7e 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -247,8 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ એપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"તમામ પ્રવૃત્તિઓને મલ્ટી-વિંડો માટે ફરીથી કદ બદલી શકે તેવી બનાવે છે, મેનીફેસ્ટ મુલ્યોને ધ્યાનમાં લીધા સિવાય."</string>
- <string name="enable_freeform_support" msgid="1461893351278940416">"મુક્તાકાર વિંડોઝ સક્ષમ કરો"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"પ્રાયોગિક મુક્તાકાર વિંડોઝ માટે સમર્થનને સક્ષમ કરે છે."</string>
+ <string name="enable_freeform_support" msgid="1461893351278940416">"ફ્રિફોર્મ વિંડોઝ સક્ષમ કરો"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"પ્રાયોગિક ફ્રિફોર્મ વિંડોઝ માટે સમર્થનને સક્ષમ કરે છે."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ડેસ્કટૉપ બેકઅપ પાસવર્ડ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ હાલમાં સુરક્ષિત નથી"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ્સ માટેનો પાસવર્ડ બદલવા અથવા દૂર કરવા માટે ટચ કરો"</string>
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"સ્વચલિત"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView અમલીકરણ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView અમલીકરણ સેટ કરો"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"પસંદ કરેલ WebView અમલીકરણ અક્ષમ કરેલ છે અને ઉપયોગ કરવા માટે સક્ષમ કરવું આવશ્યક છે, શું તમે તેને સક્ષમ કરવા માગો છો?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ફાઇલ એન્ક્રિપ્શનમાં રૂપાંતરિત કરો"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"રૂપાંતરિત કરો..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ફાઇલ પહેલેથી જ એન્ક્રિપ્ટ કરેલ છે"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"રંગ સુધારણા"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_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_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_wireless" msgid="1829295708243159464">"<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_usb" msgid="2207489369680923929">"USB થી ચાર્જિંગ"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"વાયરલેસથી ચાર્જિંગ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 5224c38..b6b8eacb 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"स्वचालित"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट करें"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"चुना गया WebView कार्यान्वयन अक्षम है और उसे उपयोग करने के लिए सक्षम किया जाना आवश्यक है, क्या आप उसे सक्षम करना चाहते हैं?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"फ़ाइल एन्क्रिप्शन में रूपांतरित करें"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करें..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फ़ाइल पहले से एन्क्रिप्ट की हुई है"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रंग सुधार"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC पर पूरी होने तक"</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> USB पर पूरी होने तक"</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="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_usb" msgid="2207489369680923929">"USB पर चार्ज हो रही"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस रूप से चार्ज हो रही"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 5cde233..0ab13f6 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o manifestu"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Nametni mogućnost promjene veličine za aktivnosti"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Veličina svih aktivnosti može se mijenjati za više prozora, neovisno o vrijednostima manifesta."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore slobodnog oblika"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogućuje podršku za eksperimentalne prozore slobodnog oblika."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Zaporka sigurnosne kopije"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Potpune sigurnosne kopije na stolnom računalu trenutačno nisu zaštićene"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Odaberite za promjenu ili uklanjanje zaporke u potpunim sigurnosnim kopijama na stolnom računalu"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatska"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacija WebViewa"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Postavi implementaciju WebViewa"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u enkripciju datoteka"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvori…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkripcija datoteka već je izvršena"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boje"</string>
<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_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_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_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_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_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="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_usb" msgid="2207489369680923929">"Punjenje putem USB-a"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično 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>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 3559f1e..26d65fb 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatikus"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-megvalósítás"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-megvalósítás beállítása"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A kiválasztott WebView-megvalósítás le van tiltva, a használathoz viszont engedélyezni kell. Szeretné engedélyezni?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertálás fájlalapú titkosításra"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertálás…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Már fájlalapú titkosítást használ"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Színkorrekció"</string>
<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_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_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_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_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_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="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_usb" msgid="2207489369680923929">"USB-s 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_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>
</resources>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 42c9a05..7a9b16f 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Թույլ է տալիս պահել հավելվածը արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Ստիպել, որ ակտիվությունների չափերը լինեն փոփոխելի"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Ակտիվացնել կամայական ձևի պատուհանները"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ակտիվացնում է կամայական ձևի փորձնական պատուհանների աջակցումը:"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Աշխատասեղանի պահուստավորման գաղտնաբառ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Աշխատասեղանի ամբողջական պահուստավորումները այժմ պաշտպանված չեն"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Աշխատասեղանի ամբողջական պահուստավորման համար ընտրել փոխել կամ հեռացնել գաղտնաբառը"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Ավտոմատ"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-ի իրականացում"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ընտրեք WebView-ի իրականացումը"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Վերածել ֆայլային գաղտնագրման"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Փոխարկել…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ֆայլային գաղտնագրումն արդեն կատարվել է"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Գունային կարգաբերում"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> մինչև լրիվ լիցքավորումը USB-ով"</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="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_usb" msgid="2207489369680923929">"Լիցքավորում USB-ով"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Անլար լիցքավորում"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 6988a73..f2eaccf 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksterna"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktivitas agar ukurannya dapat diubah"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Aktifkan jendela berformat bebas"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Mengaktifkan dukungan untuk jendela eksperimental berformat bebas."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Sandi cadangan desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Saat ini cadangan desktop penuh tidak dilindungi"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Sentuh guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Otomatis"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Penerapan WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setel penerapan WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konversi ke enkripsi file"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konversi..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sudah dienkripsi berbasis file"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Koreksi warna"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - kira-kira tersisa. <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> sampai penuh"</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> sampai penuh pada AC"</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> sampai penuh melalui USB"</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> sampai penuh dari nirkabel"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Isi daya lewat USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Isi daya nirkabel"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 8d912e9..dc105eb 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gerir hvaða forriti sem er kleift að skrifa í ytri geymslu, burtséð frá gildum í upplýsingaskrá"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Þvinga breytanlega stærð virkni"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Gerir stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Virkja glugga með frjálsu sniði"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Kveikir á stuðningi við glugga með frjálsu sniði á tilraunastigi."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Aðgangsorð tölvuafritunar"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Heildarafritun á tölvu er ekki varin sem stendur."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Snertu til að breyta eða fjarlægja aðgangsorðið fyrir heildarafritun á tölvu"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Sjálfvirkt"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Innleiðing WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stilla innleiðingu WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Umbreyta í dulkóðun skráa"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Umbreyta…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Þegar dulkóðað á grundvelli skráa"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Litaleiðrétting"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – u.þ.b. <xliff:g id="TIME">%2$s</xliff:g> eftir"</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> í fulla hleðslu"</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> í fulla hleðslu með hleðslutæki"</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> í fulla hleðslu í gegnum USB"</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> í fulla hleðslu þráðlaust"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Hleður um USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hleður þráðlaust"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 2d98a74..eedfa33 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatico"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementazione di WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Imposta l\'implementazione di WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"L\'implementazione di WebView selezionata non è attiva e deve essere attivata per poterla utilizzare. Vuoi attivarla?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converti in crittografia basata su file"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converti..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Crittografia su base file già eseguita"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correzione del colore"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tempo rimanente: <xliff:g id="TIME">%2$s</xliff:g> circa"</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> alla carica completa"</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> alla carica completa tramite CA"</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> alla carica completa tramite USB"</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> lla carica completa con wireless"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"In carica tramite USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"In carica, wireless"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index e175208..ec8f1a5 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -190,7 +190,7 @@
<string name="hdcp_checking_title" msgid="8605478913544273282">"בדיקת HDCP"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"הגדר אופן בדיקת HDCP"</string>
<string name="debug_debugging_category" msgid="6781250159513471316">"ניפוי באגים"</string>
- <string name="debug_app" msgid="8349591734751384446">"בחר אפליקציה לניפוי"</string>
+ <string name="debug_app" msgid="8349591734751384446">"בחר אפליקציה לניפוי באגים"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"לא הוגדרה אפליקציה לניפוי"</string>
<string name="debug_app_set" msgid="2063077997870280017">"אפליקציה לניפוי: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"בחר אפליקציה"</string>
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"אלץ יכולת קביעת גודל של הפעילויות"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"מאפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא קשר לערך המניפסט."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"הפעל את האפשרות לשנות את הגודל והמיקום של החלונות"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"מפעיל תמיכה בתכונה הניסיונית של שינוי הגודל והמיקום של החלונות."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"סיסמת גיבוי מקומי"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"גיבויים מלאים בשולחן העבודה אינם מוגנים כעת"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"גע כדי לשנות או להסיר את הסיסמה עבור גיבויים מלאים בשולחן העבודה"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"באופן אוטומטי"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"יישום WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"הגדרת יישום WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"המר להצפנת קבצים"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"המר..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"הצפנת קבצים כבר מוגדרת"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"תיקון צבע"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> עד למילוי ב-USB"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"טוען ב-USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"טוען באופן אלחוטי"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index bf9bf8a..9a32d44 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"アクティビティをサイズ変更可能にする"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようになります。"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"フリーフォーム ウィンドウの有効化"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"テスト段階のフリーフォーム ウィンドウのサポートを有効にします。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"PCバックアップパスワード"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"デスクトップのフルバックアップは現在保護されていません"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"デスクトップのフルバックアップ用のパスワードを変更または削除する場合にタップします"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"自動"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView の実装"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView の実装の設定"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ファイル暗号化に変換する"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"変換…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ファイルは既に暗号化済みです"</string>
@@ -295,4 +295,20 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色補正"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(AC)"</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>(USB)"</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="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_usb" msgid="2207489369680923929">"USBで充電しています"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"無線で充電しています"</string>
+ <string name="battery_info_status_discharging" msgid="310932812698268588">"充電していません"</string>
+ <string name="battery_info_status_not_charging" msgid="2820070506621483576">"充電していません"</string>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for battery_info_status_full (2824614753861462808) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index da9d204..0cfb6ec 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"აპები ჩაიწერ. გარე მეხს.-ზე აღწ. ფაილის მნიშვნ. მიუხედ."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ზომაცვლადი აქტივობების იძულება"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"მანიფესტის მნიშვნელობების მიუხედავად, ყველა აქტივობას მრავალი ფანჯრის რეჟიმისთვის ზომაცვლადად აქცევს."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ჩართავს თავისუფალი ფორმის მქონე ფანჯრების მხარდაჭერის ექსპერიმენტულ ფუნქციას"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"დესკტოპის სარეზერვო ასლის პაროლი"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"დესკტოპის სრული სარეზერვო ასლები ამჟამად დაცული არ არის"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"შეეხეთ დესკტოპის სრული სარეზერვო ასლების პაროლის შესაცვლელად ან წასაშლელად"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ავტომატური"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView რეალიზაცია"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView რეალიზაციის დაყენება"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ფაილების დაშიფვრაზე გარდაქმნა"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"გარდაქმნა…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"უკვე დაშიფრულია ფაილების დონეზე"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ფერის კორექცია"</string>
<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_discharging_duration" msgid="1605929174734600590">"დაახლ. <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_ac" msgid="3969186192576594254">"<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> USB-თი სრულ დატენვამდე"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"დატენვა USB-ზე"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"დატენვა უსადენოდ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 549711c..b629522 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттерді өлшемін өзгертуге болатын етуге мәжбүрлеу"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Манифест мәндеріне қарамастан барлық әрекеттерді бірнеше терезе үшін өлшемін өзгертуге болатын етеді."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Еркін пішіндегі терезелерді қосу"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Эксперименттік еркін пішіндегі терезелерді қолдауды қосады."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Компьютер үстелінің сақтық көшірмесі"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Жұмыс үстелінің сақтық көшірмелері қазір қорғалмаған"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Жұмыс үстелінің толық сақтық көшірмесінің кілтсөзін өзгерту немесе жою үшін түртіңіз"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Aвтоматты"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ендіру"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ендіруін орнату"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлды шифрлауға түрлендіру"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Түрлендіру..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл шифрланып қойылған"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Түсті түзету"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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_wireless" msgid="1829295708243159464">"<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">"Айнымалы токпен зар."</string>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB арқылы зарядтау"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Сымсыз зарядтау"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index aed4365..1155c07 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃជាក់លាក់"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"កំណត់ឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុផ្ទាំងវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេសឡើយ។"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"បើកដំណើរការគាំទ្រផ្ទាំងវិនដូទម្រង់សេរីសាកល្បង"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ពាក្យសម្ងាត់បម្រុងទុកលើផ្ទៃតុ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ការបម្រុងទុកពេញលេញលើផ្ទៃតុបច្ចុប្បន្នមិនត្រូវបានការពារទេ។"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"ប៉ះ ដើម្បីប្ដូរ ឬលុបពាក្យសម្ងាត់សម្រាប់ការបម្រុងទុកពេញលេញលើផ្ទៃតុ"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ស្វ័យប្រវត្តិ"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"ការប្រតិបត្តិ WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"កំណត់ការប្រតិបត្តិ WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"បម្លែងទៅជាការអ៊ីនគ្រីបឯកសារ"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"បម្លែង…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"បានអ៊ីនគ្រីបឯកសាររួចហើយ"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ការកែពណ៌"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> រហូតដល់ពេញតាមយូអេសប៊ី"</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="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_usb" msgid="2207489369680923929">"បញ្ចូលថ្មតាមយូអេសប៊ី"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"បញ្ចូលថ្មដោយឥតខ្សែ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 50e5955..948c665315 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ಸ್ವಯಂಚಾಲಿತ"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿಸಿ"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ಆಯ್ಕೆಮಾಡಲಾದ WebView ಅನುಷ್ಠಾನಗೊಳಿಸುವಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಮತ್ತು ಬಳಸಲು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕಾಗಿದೆ, ಇದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ನೀವು ಬಯಸುತ್ತೀರಾ?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ಫೈಲ್ ಎನ್ಕ್ರಿಪ್ಶನ್ಗೆ ಪರಿವರ್ತಿಸು"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ಪರಿವರ್ತಿಸು…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ಫೈಲ್ ಈಗಾಗಲೇ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
<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_discharging_duration" msgid="1605929174734600590">"ಸುಮಾರು <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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ನಲ್ಲಿ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</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> USB ಮೂಲಕ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</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="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_usb" msgid="2207489369680923929">"USB ಮೂಲಕ ಚಾರ್ಜ್"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ನಿಸ್ತಂತುವಾಗಿ ಚಾರ್ಜ್"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index ea5dc00..7f5cee2 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"매니페스트 값에 관계없이 앱을 외부 저장소에 작성"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"활동의 크기가 조정 가능하도록 설정"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"자유 형식 창 사용"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"자유 형식 창(베타) 지원 사용"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"데스크톱 백업 비밀번호"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"데스크톱 전체 백업에 비밀번호가 설정되어 있지 않음"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"데스크톱 전체 백업에 대한 비밀번호를 변경하거나 삭제하려면 터치하세요."</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"자동"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 구현"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView 구현 설정"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"파일 암호화로 변환"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"변환..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"파일이 이미 암호화됨"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"색보정"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(AC 전원)"</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> 후 충전 완료(USB)"</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="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_usb" msgid="2207489369680923929">"충전 중(USB)"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"충전 중(무선)"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 6a47406..c00e827 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Аракеттердин өлчөмүн өзгөртүүнү мажбурлоо"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Манифест маанилерине карабастан бардык аракеттерди мульти-терезеге өлчөмү өзгөртүлгүдөй кылат."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Эркин формадагы терезелерди түзүүнү иштетүү"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Эркин формадагы терезелерди түзүү боюнча сынамык функцияны иштетүү"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Компүтердеги бэкаптын сырсөзү"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Компүтердеги толук бэкап учурда корголгон эмес"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Тийип, компүтердеги толук бэкаптын сырсөзүн өзгөртүңүз же жок кылыңыз"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Автоматтык"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView аткарылышы"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView аткарылышын коюу"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файл шифрлөөсүнө айландыруу"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Айландыруу…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл мурунтан эле шифрленген"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Түсүн тууралоо"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC аркылуу толгончо"</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> USB аркылуу толгончо"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB\'ден кубатталууда"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Зымсыз кубатталууда"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 538a38c..6dd3097 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ບ່ອນຈັດເກັບພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ບັງຄັງໃຫ້ກິດຈະກຳປ່ຽນຂະໜາດໄດ້"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"ເຮັດໃຫ້ທຸກກິດຈະກຳປ່ຽນຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຕ່າງ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"ເປີດໃຊ້ໜ້າຕ່າງຮູບແບບອິດສະຫຼະ"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"ເປີດໃຊ້ການຮອງຮັບໜ້າຕ່າງຮູບແບບອິດສະຫຼະທີ່ທົດລອງໃຊ້."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ລະຫັດຜ່ານການສຳຮອງຂໍ້ມູນເດັກສະທັອບ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັກສະທັອບຍັງບໍ່ໄດ້ຮັບການປ້ອງກັນໃນເວລານີ້"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"ແຕະເພື່ອປ່ຽນ ຫຼືລຶບລະຫັດຂອງການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບໃນເດັກສະທັອບ"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ອັດຕະໂນມັດ"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ຕັ້ງການຈັດຕັ້ງປະຕິບັດ WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ປ່ຽນເປັນການເຂົ້າລະຫັດໄຟລ໌"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ປ່ຽນ..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ໄຟລ໌ເຂົ້າລະຫັດຮຽບຮ້ອຍແລ້ວ"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ການປັບແຕ່ງສີ"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມໂດຍສາກດ້ວຍໄຟ AC"</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> ຈຶ່ງຈະເຕັມໂດຍສາກດ້ວຍ USB"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"ກຳລັງສາກຜ່ານ USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ກຳລັງສາກໄຮ້ສາຍ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 014a6fb..6010c7a 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Vis. pr. gal. įr. į vid. saug. nepais. apr. vert."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Nustatoma, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Įgalinti laisvos formos langus"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Įgalinamas eksperimentinių laisvos formos langų palaikymas."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Viet. atsrg. kop. slapt."</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Šiuo metu visos vietinės atsarginės kopijos neapsaugotos"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Jei norite pakeisti ar pašalinti visų vietinių atsarginių kopijų slaptažodį, palieskite"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatinė"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"„WebView“ diegimas"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"„WebView“ diegimo nustatymas"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuoti į failų šifruotę"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuoti…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau konvertuota į failų šifruotę"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Spalvų taisymas"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko maždaug <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> iki visiško įkrovimo"</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> iki visiško įkrovimo naud. kint. sr."</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> iki visiško įkrovimo naudojant USB"</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> iki visiško įkrovimo belaid. ryš."</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Įkraunama naud. USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Įkraunama be laidų"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 87da105..d50e1ea 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Pielāgot darbības"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Pielāgo visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Iespējot brīvās formas logus"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Iespējo eksperimentālo brīvās formas logu atbalstu."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Datora dublējuma parole"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Darbvirsmas pilnie dublējumi pašlaik nav aizsargāti."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Pieskarieties, lai mainītu vai noņemtu paroli pilniem darbvirsmas dublējumiem."</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automātiski"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ieviešana"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Iestatīt WebView ieviešanu"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Pārvērst par failu šifrējumu"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pārvērst…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau šifrēts failu līmenī"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Krāsu korekcija"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB uzlāde"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezvadu uzlāde"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index b588c2c..03feddd 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Автоматски"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Воведување WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Поставете воведување WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертирајте до шифрирање датотеки"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертирај..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Датотеката е веќе шифрирана"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција на боја"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна на AC"</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> до целосно полна преку USB"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Полнење преку УСБ"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично полнење"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index d76e87f..e47afc4 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"വലിപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ പ്രവർത്തനങ്ങളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലിപ്പം മാറ്റുന്നു."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"പരീക്ഷണാത്മക ഫ്രീഫോം വിൻഡോകൾക്കുള്ള പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുന്നു."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ഡെസ്ക്ടോപ്പ് ബാക്കപ്പ് പാസ്വേഡ്"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾ നിലവിൽ പരിരക്ഷിച്ചിട്ടില്ല"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"ഡെസ്ക്ടോപ്പ് പൂർണ്ണ ബാക്കപ്പുകൾക്കായി പാസ്വേഡുകൾ മാറ്റാനോ നീക്കംചെയ്യാനോ സ്പർശിക്കുക"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ഓട്ടോമാറ്റിക്"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView നടപ്പാക്കൽ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView നടപ്പാക്കൽ സജ്ജമാക്കുക"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ഫയൽ എൻക്രിപ്ഷനിലേക്ക് പരിവർത്തിപ്പിക്കുക"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"പരിവർത്തിപ്പിക്കുക…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ഇതിനകം തന്നെ ഫയൽ എൻക്രിപ്റ്റ് ചെയ്തു"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"വർണ്ണം ക്രമീകരിക്കൽ"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_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_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_wireless" msgid="1829295708243159464">"<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_usb" msgid="2207489369680923929">"USB-യിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"വയർലെസ്സ് കണക്ഷനിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 4aea631..01925f7 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест утгыг нь үл хамааран дурын апп-ыг гадаад санах ойд бичих боломжтой болгодог"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааг олон цонхонд хэмжээг нь өөрчилж болохуйц болгох."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Туршилтын чөлөөт хэлбэрийн цонхны дэмжлэгийг идэвхжүүлдэг."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Десктоп нөөшлөлтийн нууц үг"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Десктоп бүрэн нөөцлөлт одоогоор хамгаалалтгүй байна"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Десктоп дээрх бүрэн нөөшлөлтийн нууц үгийг өөрчлөх буюу арилгахын тулд хүрнэ үү"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Автоматаар"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView хэрэгжилт"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView хэрэгжилтийг тохируулах"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файлын шифрлэлт болгон хөрвүүлэх"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Хөрвүүлэх..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Аль хэдийнэ файл шифрлэгдсэн"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Өнгө тохируулах"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"АС-р дүүртэл <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">"USB-р дүүртэл <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="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_usb" msgid="2207489369680923929">"USB-р цэнэглэж байна"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Кабльгүйгээр цэнэглэж байна"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index ed57fb7..804fab0 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"स्वयंचलित"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"वेबदृश्य अंमलबजावणी"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबदृश्य अंमलबजावणी सेट करा"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"निवडलेली WebView अंमलबजावणी अक्षम आहे आणि वापरण्यास सक्षम असणे आवश्यक आहे, आपण ती सक्षम करू इच्छिता?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"फाईल कूटबद्धीकरणावर रूपांतरित करा"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करा..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फाईल आधीपासून कूटबद्ध केली"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रंग सुधारणा"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC वरून पूर्ण होण्यात"</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> USB वरून पूर्ण होण्यात"</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="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_usb" msgid="2207489369680923929">"USB वरून चार्ज करीत आहे"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस वरून चार्ज करीत आहे"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 1f72d04..ed4d071 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Menjadikan sebarang apl layak ditulis ke storan luaran, walau apa juga nilai manifesnya"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktiviti supaya boleh diubah saiz"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Menjadikan semua aktiviti boleh diubah saiz untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Dayakan tetingkap bentuk bebas"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Mendayakan sokongan untuk tetingkap bentuk bebas percubaan."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Kata laluan sandaran komputer meja"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Sandaran penuh komputer meja tidak dilindungi pada masa ini"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Sentuh untuk menukar atau mengalih keluar kata laluan untuk sandaran penuh komputer meja"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatik"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Pelaksanaan WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Tetapkan pelaksanaan WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Tukar kepada penyulitan fail"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Tukar..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sudah disulitkan fail"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pembetulan warna"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Mengecas melalui USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Mengecas tanpa wayar"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index cd4812f..ab7a8d0 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ပြနေတဲ့ တန်ဖိုး ဘယ်လိုပဲရှိနေနေ၊ ဘယ် appကို မဆို အပြင် သိုလှောင်ခန်းသို့ ရေးသားခွင့် ပေးတယ်"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ ဆိုက်ညှိရနိုင်ရန် လုပ်ခိုင်းပါ"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"မန်နီးဖက်စ် တန်ဖိုးမရွေး၊ လုပ်ဆောင်ချက် အားလုံး ဆိုက်ညှိရနိုင်အောင် လုပ်ပေးပါ။"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"အခမဲ့ပုံစံ ဝင်းဒိုးကို ဖွင့်ပါ"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"စမ်းသပ်မှု အခမဲ့ပုံစံ ဝင်းဒိုးများအတွက် ပံ့ပိုးမှုကို ဖွင့်ပါ။"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Desktop အရန်စကားဝှက်"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"အလုပ်ခုံတွင် အရန်သိမ်းဆည်းခြင်းများကို လောလောဆယ် မကာကွယ်နိုင်ပါ။"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"အလုပ်ခုံ တွင် အရန်သိမ်းဆည်းခြင်းအပြည့်လုပ်ရန် အတွက် စကားဝှက်ဖယ်ရန် သို့ ပြောင်းရန် တို့ထိပါ။"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"အလိုအလျောက်"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView အကောင်အထည်ဖော်မှု"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView အကောင်အထည်ဖော်မှု သတ်မှတ်ပါ"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ဖိုင်လုံခြုံအောင်ပြုလုပ်ခြင်းသို့ ပြောင်းပါ"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ပြောင်းရန်…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ဖိုင်ကို လုံခြုံအောင်ပြုလုပ်ပြီးပါပြီ"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"အရောင်ပြင်ဆင်မှု"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> USB ဖြင့် အပြည့်အထိ"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBဖြင့် အားသွင်းနေ"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ကြိုးမဲ့ အားသွင်းနေ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index ae0b15d..e39cf30 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gjør at apper kan skrives til ekstern lagring, uavhengig av manifestverdier"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til å kunne endre størrelse"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Dette gjør at alle aktivitene kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Slå på vinduer i fritt format"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Slår på støtte for vinduer i eksperimentelt fritt format."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Passord for sikkerhetskopiering på datamaskin"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Fullstendig sikkerhetskopiering på datamaskin beskyttes ikke for øyeblikket."</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Trykk for å endre eller fjerne passordet for fullstendige sikkerhetskopier på datamaskinen"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatisk"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Angi WebView-implementering"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valgte implementeringen av nettvisningen er slått av – den må slås på for å brukes. Vil du slå den på?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertér til kryptert fil"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede kryptert og lagret som fil"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Fargekorrigering"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca. <xliff:g id="TIME">%2$s</xliff:g> igjen"</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> – fulladet om <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> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> med vekselstrøm"</string>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Lader via USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Lader trådløst"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 5885513..d9cfbcc 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -247,8 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"म्यानिफेेस्टको उपेक्षा गरी, कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न योग्य बनाउँछ"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउँछ।"</string>
- <string name="enable_freeform_support" msgid="1461893351278940416">"फ्रीफर्म विन्डोहरू सक्रिय गर्नुहोस्"</string>
- <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रयोगात्मक फ्रीफर्म विन्डोहरूका लागि समर्थनलाई सक्रिय गर्छ।"</string>
+ <string name="enable_freeform_support" msgid="1461893351278940416">"फ्रिफर्म विन्डोहरू सक्रिय गर्नुहोस्"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"प्रयोगात्मक फ्रिफर्म विन्डोहरूका लागि समर्थनलाई सक्रिय गर्छ।"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"डेस्कटप ब्याकअप पासवर्ड"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"डेस्कटप पूर्ण जगेडाहरू हाललाई सुरक्षित छैनन्"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"डेस्कटप पूर्ण ब्याकअपको लागि पासवर्ड बदल्न वा हटाउन छुनुहोस्"</string>
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"स्वचालित"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView कार्यान्वयन"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView कार्यान्वयन सेट गर्नुहोस्"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"फाइल इन्क्रिप्सनमा रूपान्तरण गर्नुहोस्"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रुपान्तरण गर्नुहोस्…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"पहिल्यै फाइल इन्क्रिप्ट गरिएको छ"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रङ्ग सुधार"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC मा पूर्ण नभए सम्म"</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> USB मा पूर्ण नभए सम्म"</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="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_usb" msgid="2207489369680923929">"USB मा चार्ज गर्दै"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"बिना तार चार्ज गर्दै"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 1dd477d..4873ac3 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatisch"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementatie"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-implementatie instellen"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"De gekozen WebView-implementatie is uitgeschakeld en moet worden ingeschakeld voor gebruik. Wil je deze inschakelen?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteren naar versleuteling op basis van bestanden"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteren…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Al versleuteld op basis van bestanden"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Kleurcorrectie"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - ca. <xliff:g id="TIME">%2$s</xliff:g> resterend"</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> tot vol"</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> tot vol via wisselstroom"</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> tot vol via USB"</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> tot vol via draadloos"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladen via USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Draadloos opladen"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index 85f9ffb..61f187d 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ਆਟੋਮੈਟਿਕ"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ਅਮਲ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ਅਮਲ ਸੈੱਟ ਕਰੋ"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ਚੁਣਿਆ ਗਿਆ WebView ਅਮਲ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ, ਅਤੇ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਜਾਣਾ ਜ਼ਰੂਰੀ ਹੈ, ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਯੋਗ ਬਣਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ਫ਼ਾਈਲ ਇਨਕ੍ਰਿਪਸ਼ਨ ਵਿੱਚ ਤਬਦੀਲ ਕਰੋ"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ਤਬਦੀਲ ਕਰੋ ..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ਫ਼ਾਈਲ ਪਹਿਲਾਂ ਤੋਂ ਇਨਕ੍ਰਿਪਟਡ ਹੈ"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ਰੰਗ ਸੰਸ਼ੋਧਨ"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</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> USB ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</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="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_usb" msgid="2207489369680923929">"USB ਤੇ ਚਾਰਜਿੰਗ"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ਵਾਇਰਲੈਸ ਤੌਰ ਤੇ ਚਾਰਜਿੰਗ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 9f7c022..0189fab 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatycznie"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacja WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ustaw implementację WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Przekształć na szyfrowanie plików"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Przekształć…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Pliki są już zaszyfrowane"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcja kolorów"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostało ok. <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 pełnego naładowania"</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 pełnego naładowania z gniazdka"</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 pełnego naładowania przez USB"</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 pełnego naładowania bezprzewodowo"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Ładowanie przez USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ład. bezprzewodowe"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index dd4b58d..ee701a6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</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> até concluir"</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> até concluir em CA"</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> até concluir via USB"</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> até concluir sem fio"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 0cbe5e4..2f25ae2 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementação WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"A implementação WebView escolhida foi desativada e tem de ser ativada para poder ser utilizada. Pretende ativá-la?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para a encriptação de ficheiros"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Os ficheiros já estão encriptados"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção da cor"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) aprox. <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> até ficar completa"</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> até ficar completa através de CA"</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> até ficar completa através de USB"</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> até ficar compl. por rede s/ fios"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"A carregar por USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"A carregar sem fios"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index dd4b58d..ee701a6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Torna todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ativa a compatibilidade com janelas de forma livre experimentais."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Senha do backup local"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Os backups completos do computador não estão protegidos no momento"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Toque para alterar ou remover a senha de backups completos do desktop"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automático"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correção de cor"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - cerca de <xliff:g id="TIME">%2$s</xliff:g> restantes"</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> até concluir"</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> até concluir em CA"</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> até concluir via USB"</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> até concluir sem fio"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index a666da0..29d878f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Forțați redimensionarea activităților"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Permite redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Activați ferestrele cu formă liberă"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Activează compatibilitatea pentru ferestrele experimentale cu formă liberă."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Parolă copie rez. desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"În prezent, copiile de rezervă complete pe desktop nu sunt protejate"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Atingeţi pentru a modifica sau pentru a elimina parola pentru copiile de rezervă complete pe desktop"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automat"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementare WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setați implementarea WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Faceți conversia la criptarea bazată pe sistemul de fișiere"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertiți…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Criptarea bazată pe sistemul de fișiere este finalizată"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Corecția culorii"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Se încarcă prin USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Se încarcă fără fir"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index e93bae1..ba21d3e 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Разрешает сохранение приложений на внешние накопители независимо от значения манифеста"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Изменение размера в многооконном режиме"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Позволяет менять размер в многооконном режиме (независимо от значений манифеста)"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Разрешить создание окон произвольной формы"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Включить экспериментальную функцию создания окон произвольной формы"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Пароль для резервного копирования"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Полные резервные копии в настоящее время не защищены"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Изменить или удалить пароль для резервного копирования"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Автоматическое переключение"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Сервис WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Настройки сервиса WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Переход к шифрованию файлов"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Перейти…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Шифрование файлов уже включено"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Коррекция цвета"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> до полной зарядки (через USB)"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарядка через USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Беспроводная зарядка"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 6753624..0f32a0c 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් අභ්යන්තර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"ක්රියාකාරකම් ප්රතිප්රමාණ කළ හැකි බවට බල කරන්න"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළු සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරයි."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"අනියම් හැඩැති කවුළු සබල කරන්න"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"පරීක්ෂණාත්මක අනියම් හැඩැති කවුළු සඳහා සහාය සබල කරයි."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ඩෙස්ක්ටොප් උපස්ථ මුරපදය"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ දැනට ආරක්ෂා කර නොමැත"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"ඩෙස්ක්ටොප් සම්පූර්ණ උපස්ථ සඳහා මුරපදය වෙනස් කිරීමට හෝ ඉවත් කිරීමට ස්පර්ශ කරන්න"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"ස්වයංක්රීය"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ක්රියාත්මක කිරීම"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ක්රියාත්මක කිරීම සකසන්න"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ගොනු සංකේතනයට පරිවර්තනය කරන්න"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"පරිවර්තනය කරන්න..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"දැනටමත් ගොනුව සංකේතනය කර ඇත"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"වර්ණ නිවැරදි කිරීම"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"AC හි <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">"USB හරහ <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="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_usb" msgid="2207489369680923929">"USB හරහා ආරෝපණය වෙමින්"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"රැහැන් රහිතව ආරෝපණය වෙමින්"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 7db7835..8df02ea 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Vynútiť možnosť zmeny veľkosti aktivít"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Veľkosti všetkých aktivít bude možné zmeniť na niekoľko okien (bez ohľadu na hodnoty manifestu)."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Povoliť okná s voľným tvarom"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Povolenie podpory pre experimentálne okná s voľným tvarom."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Heslo pre zálohy v počítači"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Úplné zálohy na počítači nie sú momentálne chránené"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Dotykom zmeníte alebo odstránite heslo pre úplné zálohy do počítača"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatický"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementácia komponenta WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavenie implementácie komponenta WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Zvolená implementácia technológie WebView je zakázaná. Ak ju chcete použiť, musíte ju najprv povoliť. Chcete ju povoliť?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertovať na šifrovanie súborov"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertovať…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Súbory sú už šifrované"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Úprava farieb"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjanie cez USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrôtové nabíjanie"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index ed37933..5d47af9 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Vsili povečanje velikosti za aktivnosti"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim povečati velikost za način z več okni."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Omogočanje oken svobodne oblike"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Omogočanje podpore za poskusna okna svobodne oblike"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Geslo za varn. kop. rač."</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Popolne varnostne kopije namizja trenutno niso zaščitene"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Dotaknite se, če želite spremeniti ali odstraniti geslo za popolno varnostno kopiranje namizja."</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Samodejno"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Izvedba spletnega pogleda"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Nastavitev izvedbe spletnega pogleda"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Preklop na šifriranje podatkov"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Preklop …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Šifriranje podatkov je že uveljavljeno"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Popravljanje barv"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – še približno <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 napolnjenosti"</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 napolnjenosti prek napajalnika"</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 napolnjenosti prek USB-ja"</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 napolnjenosti prek brezž. pol."</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Polnj. prek USB-ja"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Brezžično polnjenje"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 7f4d6a8..8e8112f 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -277,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatike"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Zbatimi i WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Cakto zbatimin e WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konverto në enkriptimin e skedarit"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konverto..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkriptimi i skedarit është kryer tashmë"</string>
@@ -293,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korrigjimi i ngjyrës"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Po ngarkohet me USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Po ngarkohet me valë"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 9596ce5..935f44d 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Принудно омогући промену величине активности"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Омогућава промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Омогући прозоре произвољног формата"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Омогућава подршку за експерименталне прозоре произвољног формата."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Лозинка резервне копије за рачунар"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Резервне копије читавог система тренутно нису заштићене"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Додирните да бисте променили или уклонили лозинку за прављење резервних копија читавог система на рачунару"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Аутоматски"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Примена WebView-а"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Подесите примену WebView-а"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертуј у шифровање датотека"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертуј..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Већ се користи шифровање датотека"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекција боја"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> док се не напуни преко USB-а"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Пуњење преко USB-а"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бежично пуњење"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 7d0d0a0..1bdf6b2 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Appen kan skrivas till extern lagring, oavsett manifestvärden"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Framtvinga storleksanpassning för aktiviteter"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Detta gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivera frihandsfönster"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Aktiverar stöd för experimentella frihandsfönster."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Lösenord för säkerhetskopia av datorn"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"De fullständiga säkerhetskopiorna av datorn är för närvarande inte skyddade"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Tryck om du vill ändra eller ta bort lösenordet för fullständig säkerhetskopiering av datorn"</string>
@@ -279,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Automatiskt"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ange WebView-implementering"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Den valda WebView-implementeringen har inaktiverats och måste aktiveras om du ska kunna använda den. Vill du aktivera den?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertera till filkryptering"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertera …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Filkryptering används redan"</string>
@@ -295,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Färgkorrigering"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – ca <xliff:g id="TIME">%2$s</xliff:g> kvar"</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> till fulladdat"</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> till fulladdat via laddare"</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> till fulladdat via USB"</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> till fulladdat via trådlös laddning"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laddas via USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laddas trådlöst"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d1041da..8a5ddd0 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Huweka programu kwenye hifadhi ya nje, bila kujali maelezo"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwa ajili ya dirisha nyingi, bila kujali thamani za faili ya maelezo."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Washa madirisha yenye muundo huru"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Huwasha uwezo wa kutumia madirisha ya majaribio yenye muundo huru."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Nenosiri la hifadhi rudufu ya eneo kazi"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Hifadhi rudufu kamili za eneo kazi hazijalindwa kwa sasa"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Gusa ili ubadilishe au uondoe nenosiri la hifadhi rudufu kamili za eneo kazi"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Otomatiki"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Utekelezaji wa WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Weka utekelezaji wa WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Badilisha kuwa usimbaji fiche wa faili"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Badilisha..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Tayari faili imesimbwa kwa njia fiche"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Usahihishaji wa rangi"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takriban <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> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae"</string>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Inachaji kupitia USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Inachaji bila kutumia waya"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index e66f073..42a5534 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"மேனிஃபெஸ்ட் மதிப்புகளை பொருட்படுத்தாமல், எந்தப் பயன்பாட்டையும் வெளிப்புற சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமைக்கும்."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"பரிசோதனைக்குரிய குறிப்பிட்ட வடிவமில்லாத சாளரங்களுக்கான ஆதரவை இயக்கும்."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"டெஸ்க்டாப் காப்புப்பிரதி கடவுச்சொல்"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"டெஸ்க்டாப்பின் முழு காப்புப்பிரதிகள் தற்போது பாதுகாக்கப்படவில்லை"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"டெஸ்க்டாப்பின் முழுமையான காப்புப்பிரதிகளுக்கான கடவுச்சொல்லை மாற்றுவதற்கு அல்லது அகற்றுவதற்குத் தொடவும்"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"தானியங்கு"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView செயல்படுத்தல்"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView செயல்படுத்தலை அமை"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"கோப்பு முறைமையாக்கத்திற்கு மாற்று"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"மாற்று…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ஏற்கனவே கோப்பு முறைமையாக்கப்பட்டது"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"வண்ணத்திருத்தம்"</string>
<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_discharging_duration" msgid="1605929174734600590">"தோராயம்: <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_ac" msgid="3969186192576594254">"முழு AC சார்ஜிற்கு: <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">"முழு USB சார்ஜிற்கு: <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="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_usb" msgid="2207489369680923929">"USB மூலம் சார்ஜாகிறது"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"வயர்லெஸில் சார்ஜாகிறது"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 80b84f0..04f0ca0 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"స్వయంచాలకం"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"వెబ్ వీక్షణ అమలు"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"వెబ్ వీక్షణ అమలుని సెట్ చేయండి"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"ఎంచుకున్న వెబ్ వీక్షణ అమలు నిలిపివేయబడింది, కానీ ఉపయోగించడానికి తప్పనిసరిగా ప్రారంభించాల్సి ఉంటుంది, మీరు దీన్ని ప్రారంభించాలనుకుంటున్నారా?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ఫైల్ గుప్తీకరణకు మార్చు"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"మార్చండి…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ఫైల్ ఇప్పటికే గుప్తీకరించబడింది"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_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_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_wireless" msgid="1829295708243159464">"<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_usb" msgid="2207489369680923929">"USB ద్వారా ఛార్జ్ అవుతోంది"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"వైర్లెస్ ద్వారా ఛార్జ్ అవుతోంది"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 6826419..241fd06 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"ให้สามารถเขียนแอปต่างๆ ไปยังที่เก็บภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"บังคับให้กิจกรรมปรับขนาดได้"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"เปิดการสนับสนุนหน้าต่างรูปแบบอิสระแบบทดลอง"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"รหัสผ่านการสำรองข้อมูลในเดสก์ท็อป"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"การสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป ไม่ได้รับการป้องกันในขณะนี้"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"แตะเพื่อเปลี่ยนหรือลบรหัสผ่านสำหรับการสำรองข้อมูลเต็มรูปแบบในเดสก์ท็อป"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"อัตโนมัติ"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"การใช้งาน WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ตั้งค่าการใช้งาน WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"แปลงเป็นการเข้ารหัสไฟล์"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"แปลง…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"เข้ารหัสไฟล์แล้ว"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"การแก้สี"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน AC"</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> จนกว่าจะเต็มเมื่อชาร์จผ่าน USB"</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="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_usb" msgid="2207489369680923929">"กำลังชาร์จผ่าน USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"กำลังชาร์จแบบไร้สาย"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8f62326..d1a525b 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mara-write na sa external storage ang anumang app, anuman ang manifest value"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Sapilitang gawing resizable ang mga aktibidad"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Gawing resizable para sa multi-window ang lahat ng aktibidad, anuman ang mga manifest value."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"I-enable ang mga freeform window"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Ine-enable ang suporta para sa mga pang-eksperimentong freeform window."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Password ng pag-backup ng desktop"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Kasalukuyang hindi pinoprotektahan ang mga buong pag-backup ng desktop"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Pindutin upang baguhin o alisin ang password para sa mga buong pag-backup ng desktop"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Awtomatiko"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Pagpapatupad sa WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Itakda ang pagpapatupad sa WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"I-convert at gawing pag-encrypt ng file"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"I-convert..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Na-encrypt na ang file"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Pagtatama ng kulay"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nagcha-charge sa USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Wireless nag-charge"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 5e0839a..d4c211c 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bildirilen değerlerden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir hale getirir."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Serbest biçimli pencereleri etkinleştir"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Deneysel serbest biçimli pencereleri etkinleştirir."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Masaüstü yedekleme şifresi"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Masaüstü tam yedeklemeleri şu an korunmuyor"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Masaüstü tam yedeklemelerinin şifresini değiştirmek veya kaldırmak için dokunun"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Otomatik"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView kullanımı"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView kullanımını ayarla"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Dosya şifrelemeye dönüştür"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Dönüştür…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dosya şifreleme zaten uygulandı"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Renk düzeltme"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - yaklaşık <xliff:g id="TIME">%2$s</xliff:g> kaldı"</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> - tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ile şarj oluyor"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kablosuz şarj oluyor"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 2448b23..3e89cce 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Автоматично"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Застосування WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Налаштувати застосування WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Вибране застосування WebView вимкнено. Увімкнути його?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертувати в зашифрований файл"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертація…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Уже конвертовано в зашифрований файл"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекція кольору"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> до повного зарядження через USB"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Заряджання через USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Заряджання без дроту"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 0834303..0a2adf7 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بناتا ہے۔"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"freeform ونڈوز فعال کریں"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"تجرباتی freeform ونڈوز کے لئے سپورٹ فعال کرتا ہے۔"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"ڈیسک ٹاپ کا بیک اپ پاس ورڈ"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"ڈیسک ٹاپ کے مکمل بیک اپس فی الحال محفوظ کیے ہوئے نہیں ہیں"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"ڈیسک ٹاپ کے مکمل بیک اپس کیلئے پاس ورڈ کو تبدیل کرنے یا ہٹانے کیلئے ٹچ کریں"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"خودکار"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView کا نفاذ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView کا نفاذ سیٹ کریں"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"فائل مرموز کاری میں بدلیں"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"بدلیں…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"فائل پہلے ہی مرموز شدہ ہے"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"رنگ کی اصلاح"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC پر پورا ہونے تک"</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> USB پر پورا ہونے تک"</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="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_usb" msgid="2207489369680923929">"USB پر چارج ہورہی ہے"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"وائرلیس چارجنگ"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index d2d8b76..13494a5 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtiradi."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Erkin shakldagi oynalarni yoqish"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Tajribaviy erkin shakldagi oynalar ta’minotini yoqadi"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Zaxira nusxa uchun parol"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Kompyuterdagi zaxira nusxalar hozirgi vaqtda himoyalanmagan"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Ish stoli to\'liq zaxira nusxalari parolini o‘zgartirish yoki o‘chirish uchun bu yerni bosing."</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Avtomatik"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ta’minotchisi"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView ta’minotchisini sozlash"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Faylli shifrga o‘girish"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"O‘girish…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fayl allaqachon shifrlangan"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Rangni tuzatish"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</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>, to‘lguncha"</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>, o‘zgaruvchan tok orqali to‘lguncha"</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>, USB orqali to‘lguncha"</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>, simsiz quvvatlash orqali to‘lguncha"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Quvvat olmoqda (USB)"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Simsiz quvvat olmoqda"</string>
+ <string name="battery_info_status_discharging" msgid="310932812698268588">"Quvvatlantirilmayapti"</string>
+ <string name="battery_info_status_not_charging" msgid="2820070506621483576">"Quvvatlanmayapti"</string>
+ <string name="battery_info_status_full" msgid="2824614753861462808">"To‘la"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 178e301..81b87da 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"Giúp ứng dụng bất kỳ đủ điều kiện được ghi vào bộ nhớ ngoài bất kể giá trị tệp kê khai là gì"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"Buộc các hoạt động có thể thay đổi kích thước"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"Giúp tất cả hoạt động có thể thay đổi kích thước cho nhiều cửa sổ bất kể giá trị tệp kê khai là gì."</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"Bật cửa sổ dạng tự do"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"Bật tính năng hỗ trợ cửa sổ dạng tự do thử nghiệm."</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"Mật khẩu sao lưu của máy tính"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"Sao lưu toàn bộ máy tính hiện không được bảo vệ"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"Chạm để thay đổi hoặc xóa mật khẩu dành cho bộ sao lưu toàn bộ tới máy tính"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Tự động"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Triển khai WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Đặt triển khai WebView"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Chuyển đổi sang mã hóa tệp"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Chuyển đổi..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Đã mã hóa tệp"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Sửa màu"</string>
<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_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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Sạc qua USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Sạc không dây"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 5b96383..5ffcc0c 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"强制将活动设为可调整大小"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"将所有活动设为可配合多窗口环境调整大小(无论清单值是什么)。"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"启用可自由调整的窗口"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"启用可自由调整的窗口这一实验性功能。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"桌面备份密码"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"桌面完整备份当前未设置密码保护"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"触摸可更改或删除用于桌面完整备份的密码"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"自动"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 实现"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"设置 WebView 实现"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"转换为文件加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"转换…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"文件已加密"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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>充满(USB充电)"</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="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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在通过USB充电"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在无线充电"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index db5f09b..8eedf6d 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將所有應用程式寫入到外部儲存完間 (所有資訊清單值)"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"強制可變更活動尺寸"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"在任何資訊清單值下,允許為多個視窗變更所有活動的尺寸。"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形態視窗"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"啟用實驗版自由形態視窗的支援功能。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"桌面電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"桌上電腦的完整備份目前未受保護"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"輕觸即可更改或移除桌上電腦完整備份的密碼"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"自動"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 設置"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 設置"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"轉換為檔案加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"轉換…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"已加密檔案"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<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> 後完成充電 (透過 USB 充電)"</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="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_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 787a442..10d2e01f 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -247,10 +247,8 @@
<string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string>
<string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string>
<string name="force_resizable_activities_summary" msgid="4508217476997182216">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string>
- <!-- no translation found for enable_freeform_support (1461893351278940416) -->
- <skip />
- <!-- no translation found for enable_freeform_support_summary (2252563497485436534) -->
- <skip />
+ <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形式視窗"</string>
+ <string name="enable_freeform_support_summary" msgid="2252563497485436534">"啟用實驗版自由形式視窗的支援功能。"</string>
<string name="local_backup_password_title" msgid="3860471654439418822">"電腦備份密碼"</string>
<string name="local_backup_password_summary_none" msgid="6951095485537767956">"電腦完整備份目前未受保護"</string>
<string name="local_backup_password_summary_change" msgid="2731163425081172638">"輕觸即可變更或移除電腦完整備份的密碼"</string>
@@ -279,6 +277,8 @@
<string name="night_mode_auto" msgid="7508348175804304327">"自動"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 實作"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"設定 WebView 實作"</string>
+ <!-- no translation found for select_webview_provider_confirmation_text (6671472080671066972) -->
+ <skip />
<string name="convert_to_file_encryption" msgid="3060156730651061223">"轉換成檔案加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"轉換..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"已將檔案加密"</string>
@@ -295,4 +295,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"色彩校正"</string>
<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_discharging_duration" msgid="1605929174734600590">"<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_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (AC)"</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>後充飽 (USB)"</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="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_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</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>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index bf3addf..f42abbc 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -277,6 +277,7 @@
<string name="night_mode_auto" msgid="7508348175804304327">"Okuzenzakalelayo"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Ukufakwa ke-WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Sesba ukufakwa kwe-WebView"</string>
+ <string name="select_webview_provider_confirmation_text" msgid="6671472080671066972">"Ukusetshenziswa kwe-WebView okukhethiwe kukhutshaziwe, futhi kuzomele kunikwe amandla ukuze kusetshenziswe, ingabe ufisa ukukunika amandla?"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Phendulisela ekubethelweni kwefayela"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Iyaphendulela..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sekuvele kubethelwe ngefayela"</string>
@@ -293,4 +294,18 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ukulungiswa kombala"</string>
<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_discharging_duration" msgid="1605929174734600590">"<xliff:g id="LEVEL">%1$s</xliff:g> - isilinganiso esingu-<xliff:g id="TIME">%2$s</xliff:g> esisele"</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> kuze igcwale"</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> kuze igcwale ku-AC"</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> kuze igcwale ngaphezulu kwe-USB"</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> kuze igcwale kusukela kokungenantambo"</string>
+ <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>
+ <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Iyashaja ngaphezulu kwe-USB"</string>
+ <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Iyashaja ngaphandle kwentambo"</string>
+ <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>
</resources>
diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml
new file mode 100644
index 0000000..46267a2
--- /dev/null
+++ b/packages/SettingsLib/res/values/attrs.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<resources>
+ <declare-styleable name="RestrictedPreference">
+ <attr name="userRestriction" format="string"/>
+ </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml
new file mode 100644
index 0000000..c090468
--- /dev/null
+++ b/packages/SettingsLib/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+ <color name="disabled_text_color">#66000000</color> <!-- 38% black -->
+</resources>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index d7c78f6..9a1d6a4 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -31,4 +31,8 @@
<dimen name="user_spinner_padding">4dp</dimen>
<dimen name="user_spinner_padding_sides">20dp</dimen>
<dimen name="user_spinner_item_height">56dp</dimen>
+
+ <!-- Lock icon for preferences locked by admin -->
+ <dimen name="restricted_lock_icon_size">16dp</dimen>
+ <dimen name="restricted_lock_icon_padding">4dp</dimen>
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f7e25db..6dfa9ad 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -684,6 +684,8 @@
<string name="select_webview_provider_title">WebView implementation</string>
<!-- Developer settings: select WebView provider dialog title -->
<string name="select_webview_provider_dialog_title">Set WebView implementation</string>
+ <!-- Developer settings: confirmation dialog text for the WebView provider selection dialog -->
+ <string name="select_webview_provider_confirmation_text">The chosen WebView implementation is disabled, and must be enabled to be used, do you wish to enable it?</string>
<!-- Developer settings screen, convert userdata to file encryption option name -->
<string name="convert_to_file_encryption">Convert to file encryption</string>
@@ -726,4 +728,41 @@
<!-- Summary shown for color space correction preference when its value is overridden by another preference [CHAR LIMIT=35] -->
<string name="daltonizer_type_overridden">Overridden by <xliff:g id="title" example="Simulate color space">%1$s</xliff:g></string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when discharging with duration -->
+ <string name="power_discharging_duration"><xliff:g id="level">%1$s</xliff:g>
+ - approx. <xliff:g id="time">%2$s</xliff:g> left</string>
+
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when charging -->
+ <string name="power_charging"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="state">%2$s</xliff:g></string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
+ <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g> until full</string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
+ <string name="power_charging_duration_ac"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g> until full on AC</string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
+ <string name="power_charging_duration_usb"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g> until full over USB</string>
+ <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
+ <string name="power_charging_duration_wireless"><xliff:g id="level">%1$s</xliff:g> -
+ <xliff:g id="time">%2$s</xliff:g> until full from wireless</string>
+
+ <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="battery_info_status_unknown">Unknown</string>
+ <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging from an unknown source. -->
+ <string name="battery_info_status_charging">Charging</string>
+ <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging on AC. -->
+ <string name="battery_info_status_charging_ac">Charging on AC</string>
+ <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging over USB. -->
+ <string name="battery_info_status_charging_usb">Charging over USB</string>
+ <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging over a wireless connection. -->
+ <string name="battery_info_status_charging_wireless">Charging wirelessly</string>
+ <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="battery_info_status_discharging">Not charging</string>
+ <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="battery_info_status_not_charging">Not charging</string>
+ <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="battery_info_status_full">Full</string>
+
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
new file mode 100644
index 0000000..d81bdeb
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
@@ -0,0 +1,107 @@
+/*
+ * 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.settingslib;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.text.format.Formatter;
+import com.android.internal.os.BatteryStatsHelper;
+
+public class BatteryInfo {
+
+ public String mChargeLabelString;
+ public int mBatteryLevel;
+ public boolean mDischarging = true;
+ public long remainingTimeUs = 0;
+
+ public interface Callback {
+ void onBatteryInfoLoaded(BatteryInfo info);
+ }
+
+ public static void getBatteryInfo(final Context context, final Callback callback) {
+ new AsyncTask<Void, Void, BatteryStats>() {
+ @Override
+ protected BatteryStats doInBackground(Void... params) {
+ BatteryStatsHelper statsHelper = new BatteryStatsHelper(context, true);
+ statsHelper.create((Bundle) null);
+ return statsHelper.getStats();
+ }
+
+ @Override
+ protected void onPostExecute(BatteryStats batteryStats) {
+ final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
+ Intent batteryBroadcast = context.registerReceiver(null,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ BatteryInfo batteryInfo = BatteryInfo.getBatteryInfo(context,
+ batteryBroadcast, batteryStats, elapsedRealtimeUs);
+ callback.onBatteryInfoLoaded(batteryInfo);
+ }
+ }.execute();
+ }
+
+ public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
+ BatteryStats stats, long elapsedRealtimeUs) {
+ BatteryInfo info = new BatteryInfo();
+ info.mBatteryLevel = Utils.getBatteryLevel(batteryBroadcast);
+ String batteryPercentString = Utils.formatPercentage(info.mBatteryLevel);
+ if (batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) == 0) {
+ final long drainTime = stats.computeBatteryTimeRemaining(elapsedRealtimeUs);
+ if (drainTime > 0) {
+ info.remainingTimeUs = drainTime;
+ String timeString = Formatter.formatShortElapsedTime(context,
+ drainTime / 1000);
+ info.mChargeLabelString = context.getResources().getString(
+ R.string.power_discharging_duration, batteryPercentString, timeString);
+ } else {
+ info.mChargeLabelString = batteryPercentString;
+ }
+ } else {
+ final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
+ final String statusLabel = Utils.getBatteryStatus(
+ context.getResources(), batteryBroadcast);
+ final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
+ info.mDischarging = false;
+ info.remainingTimeUs = chargeTime;
+ String timeString = Formatter.formatShortElapsedTime(context,
+ chargeTime / 1000);
+ int plugType = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+ int resId;
+ if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
+ resId = R.string.power_charging_duration_ac;
+ } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
+ resId = R.string.power_charging_duration_usb;
+ } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
+ resId = R.string.power_charging_duration_wireless;
+ } else {
+ resId = R.string.power_charging_duration;
+ }
+ info.mChargeLabelString = context.getResources().getString(
+ resId, batteryPercentString, timeString);
+ } else {
+ info.mChargeLabelString = context.getResources().getString(
+ R.string.power_charging, batteryPercentString, statusLabel);
+ }
+ }
+ return info;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
new file mode 100644
index 0000000..c2f885d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
@@ -0,0 +1,153 @@
+/*
+ * 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.settingslib;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.support.v7.preference.DropDownPreference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+public class RestrictedDropDownPreference extends DropDownPreference {
+ private Spinner mSpinner;
+ private final Drawable mRestrictedPadlock;
+ private final int mRestrictedPadlockPadding;
+ private List<RestrictedItem> mRestrictedItems = new ArrayList<>();
+
+ public RestrictedDropDownPreference(Context context) {
+ this(context, null);
+ }
+
+ public RestrictedDropDownPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(context);
+ mRestrictedPadlockPadding = context.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_padding);
+ }
+
+ private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
+ if (position >= 0) {
+ String value = getEntryValues()[position].toString();
+ RestrictedItem item = getRestrictedItemForEntryValue(value);
+ if (item != null) {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
+ item.enforcedAdmin);
+ mSpinner.setSelection(findIndexOfValue(getValue()));
+ } else if (!value.equals(getValue()) && callChangeListener(value)) {
+ setValue(value);
+ }
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // noop
+ }
+ };
+
+ @Override
+ protected ArrayAdapter createAdapter() {
+ return new RestrictedArrayItemAdapter(getContext());
+ }
+
+ @Override
+ public void setValue(String value) {
+ if (getRestrictedItemForEntryValue(value) != null) {
+ return;
+ }
+ super.setValue(value);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
+ mSpinner = (Spinner) view.itemView.findViewById(R.id.spinner);
+ mSpinner.setOnItemSelectedListener(mItemSelectedListener);
+ }
+
+ private class RestrictedArrayItemAdapter extends ArrayAdapter<String> {
+ public RestrictedArrayItemAdapter(Context context) {
+ super(context, R.layout.spinner_dropdown_restricted_item);
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ TextView view = (TextView) super.getView(position, convertView, parent);
+ CharSequence entry = getItem(position);
+ boolean isEntryRestricted = isRestrictedForEntry(entry);
+ RestrictedLockUtils.setTextViewPadlock(getContext(), view, isEntryRestricted);
+ view.setEnabled(!isEntryRestricted);
+ return view;
+ }
+ }
+
+ private boolean isRestrictedForEntry(CharSequence entry) {
+ if (entry == null) {
+ return false;
+ }
+ for (RestrictedItem item : mRestrictedItems) {
+ if (entry.equals(item.entry)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private RestrictedItem getRestrictedItemForEntryValue(CharSequence entryValue) {
+ if (entryValue == null) {
+ return null;
+ }
+ for (RestrictedItem item : mRestrictedItems) {
+ if (entryValue.equals(item.entryValue)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public void addRestrictedItem(RestrictedItem item) {
+ mRestrictedItems.add(item);
+ }
+
+ public static class RestrictedItem {
+ public CharSequence entry;
+ public CharSequence entryValue;
+ public EnforcedAdmin enforcedAdmin;
+
+ public RestrictedItem(CharSequence entry, CharSequence entryValue,
+ EnforcedAdmin enforcedAdmin) {
+ this.entry = entry;
+ this.entryValue = entryValue;
+ this.enforcedAdmin = enforcedAdmin;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
new file mode 100644
index 0000000..e63130d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
@@ -0,0 +1,70 @@
+/*
+ * 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.settingslib;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.text.style.ImageSpan;
+
+/**
+ * An extension of ImageSpan which adds a padding before the image.
+ */
+public class RestrictedLockImageSpan extends ImageSpan {
+ private Context mContext;
+ private final float mExtraPadding;
+ private final Drawable mRestrictedPadlock;
+
+ public RestrictedLockImageSpan(Context context) {
+ // we are overriding getDrawable, so passing null to super class here.
+ super((Drawable) null);
+
+ mContext = context;
+ mExtraPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_padding);
+ mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
+ }
+
+ @Override
+ public Drawable getDrawable() {
+ return mRestrictedPadlock;
+ }
+
+ @Override
+ public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
+ int bottom, Paint paint) {
+ Drawable drawable = getDrawable();
+ canvas.save();
+
+ // Add extra padding before the padlock.
+ float transX = x + mExtraPadding;
+ float transY = bottom - drawable.getBounds().bottom - paint.getFontMetricsInt().descent;
+
+ canvas.translate(transX, transY);
+ drawable.draw(canvas);
+ canvas.restore();
+ }
+
+ @Override
+ public int getSize(Paint paint, CharSequence text, int start, int end,
+ Paint.FontMetricsInt fontMetrics) {
+ int size = super.getSize(paint, text, start, end, fontMetrics);
+ size += 2 * mExtraPadding;
+ return size;
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
new file mode 100644
index 0000000..f6caaa9
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -0,0 +1,229 @@
+/*
+ * 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.settingslib;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.Spanned;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.ImageSpan;
+import android.view.MenuItem;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * Utility class to host methods usable in adding a restricted padlock icon and showing admin
+ * support message dialog.
+ */
+public class RestrictedLockUtils {
+ /**
+ * @return drawables for displaying with settings that are locked by a device admin.
+ */
+ public static Drawable getRestrictedPadlock(Context context) {
+ Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
+ final int iconSize = context.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_size);
+ restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
+ return restrictedPadlock;
+ }
+
+ /**
+ * Checks if a restriction is enforced on a user and returns the enforced admin and
+ * admin userId.
+ *
+ * @param userRestriction Restriction to check
+ * @param userId User which we need to check if restriction is enforced on.
+ * @return EnforcedAdmin Object containing the enforce admin and admin user details, or
+ * {@code null} If the restriction is not set. If the restriction is set by both device owner
+ * and profile owner, then the admin will be set to {@code null} and userId to
+ * {@link UserHandle#USER_NULL}.
+ */
+ public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
+ String userRestriction, int userId) {
+ DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnAnyUser();
+ int deviceOwnerUserId = dpm.getDeviceOwnerUserId();
+ boolean enforcedByDeviceOwner = false;
+ if (deviceOwner != null && deviceOwnerUserId != UserHandle.USER_NULL) {
+ Bundle enforcedRestrictions = dpm.getUserRestrictions(deviceOwner, deviceOwnerUserId);
+ if (enforcedRestrictions != null
+ && enforcedRestrictions.getBoolean(userRestriction, false)) {
+ enforcedByDeviceOwner = true;
+ }
+ }
+
+ ComponentName profileOwner = null;
+ boolean enforcedByProfileOwner = false;
+ if (userId != UserHandle.USER_NULL) {
+ profileOwner = dpm.getProfileOwnerAsUser(userId);
+ if (profileOwner != null) {
+ Bundle enforcedRestrictions = dpm.getUserRestrictions(profileOwner, userId);
+ if (enforcedRestrictions != null
+ && enforcedRestrictions.getBoolean(userRestriction, false)) {
+ enforcedByProfileOwner = true;
+ }
+ }
+ }
+
+ if (!enforcedByDeviceOwner && !enforcedByProfileOwner) {
+ return null;
+ }
+
+ EnforcedAdmin admin = null;
+ if (enforcedByDeviceOwner && enforcedByProfileOwner) {
+ admin = new EnforcedAdmin();
+ } else if (enforcedByDeviceOwner) {
+ admin = new EnforcedAdmin(deviceOwner, deviceOwnerUserId);
+ } else {
+ admin = new EnforcedAdmin(profileOwner, userId);
+ }
+ return admin;
+ }
+
+ /**
+ * Checks if lock screen notification features are disabled by policy. This should be
+ * only used for keyguard notification features but not the keyguard features
+ * (e.g. KEYGUARD_DISABLE_FINGERPRINT) where a profile owner can set them on the parent user
+ * as it won't work for that case.
+ *
+ * @param keyguardNotificationFeatures Could be any of notification features that can be
+ * disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}.
+ * @return EnforcedAdmin Object containing the enforce admin and admin user details, or
+ * {@code null} If the notification features are not disabled. If the restriction is set by
+ * multiple admins, then the admin will be set to {@code null} and userId to
+ * {@link UserHandle#USER_NULL}.
+ */
+ public static EnforcedAdmin checkIfKeyguardNotificationFeaturesDisabled(Context context,
+ int keyguardNotificationFeatures) {
+ final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ boolean isDisabledByMultipleAdmins = false;
+ ComponentName adminComponent = null;
+ List<ComponentName> admins = dpm.getActiveAdmins();
+ int disabledKeyguardFeatures;
+ for (ComponentName admin : admins) {
+ disabledKeyguardFeatures = dpm.getKeyguardDisabledFeatures(admin);
+ if ((disabledKeyguardFeatures & keyguardNotificationFeatures) != 0) {
+ if (adminComponent == null) {
+ adminComponent = admin;
+ } else {
+ isDisabledByMultipleAdmins = true;
+ break;
+ }
+ }
+ }
+ EnforcedAdmin enforcedAdmin = null;
+ if (adminComponent != null) {
+ if (!isDisabledByMultipleAdmins) {
+ enforcedAdmin = new EnforcedAdmin(adminComponent, UserHandle.myUserId());
+ } else {
+ enforcedAdmin = new EnforcedAdmin();
+ }
+ }
+ return enforcedAdmin;
+ }
+
+ /**
+ * Set the menu item as disabled by admin by adding a restricted padlock at the end of the
+ * text and set the click listener which will send an intent to show the admin support details
+ * dialog.
+ */
+ public static void setMenuItemAsDisabledByAdmin(final Context context,
+ final MenuItem item, final EnforcedAdmin admin) {
+ SpannableStringBuilder sb = new SpannableStringBuilder(item.getTitle());
+ removeExistingRestrictedSpans(sb);
+
+ final int disabledColor = context.getColor(R.color.disabled_text_color);
+ sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ImageSpan image = new RestrictedLockImageSpan(context);
+ sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ item.setTitle(sb);
+
+ item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ sendShowAdminSupportDetailsIntent(context, admin);
+ return true;
+ }
+ });
+ }
+
+ private static void removeExistingRestrictedSpans(SpannableStringBuilder sb) {
+ final int length = sb.length();
+ RestrictedLockImageSpan[] imageSpans = sb.getSpans(length - 1, length,
+ RestrictedLockImageSpan.class);
+ for (ImageSpan span : imageSpans) {
+ sb.removeSpan(span);
+ }
+ ForegroundColorSpan[] colorSpans = sb.getSpans(0, length, ForegroundColorSpan.class);
+ for (ForegroundColorSpan span : colorSpans) {
+ sb.removeSpan(span);
+ }
+ }
+
+ /**
+ * Send the intent to trigger the {@link android.settings.ShowAdminSupportDetailsDialog}.
+ */
+ public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
+ Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
+ int adminUserId = UserHandle.myUserId();
+ if (admin != null) {
+ if (admin.component != null) {
+ intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
+ }
+ if (admin.userId != UserHandle.USER_NULL) {
+ adminUserId = admin.userId;
+ }
+ intent.putExtra(Intent.EXTRA_USER_ID, adminUserId);
+ }
+ context.startActivityAsUser(intent, new UserHandle(adminUserId));
+ }
+
+ public static void setTextViewPadlock(Context context,
+ TextView textView, boolean showPadlock) {
+ final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText());
+ removeExistingRestrictedSpans(sb);
+ if (showPadlock) {
+ final ImageSpan image = new RestrictedLockImageSpan(context);
+ sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ textView.setText(sb);
+ }
+
+ public static class EnforcedAdmin {
+ public ComponentName component = null;
+ public int userId = UserHandle.USER_NULL;
+
+ public EnforcedAdmin(ComponentName component, int userId) {
+ this.component = component;
+ this.userId = userId;
+ }
+
+ public EnforcedAdmin() {}
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
new file mode 100644
index 0000000..569017a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
@@ -0,0 +1,91 @@
+/*
+ * 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.settingslib;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+/**
+ * Preference class that supports being disabled by a user restriction
+ * set by a device admin.
+ */
+public class RestrictedPreference extends Preference {
+ RestrictedPreferenceHelper mHelper;
+
+ public RestrictedPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mHelper = new RestrictedPreferenceHelper(context, this, attrs);
+ }
+
+ public RestrictedPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public RestrictedPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.preferenceStyle,
+ android.R.attr.preferenceStyle));
+ }
+
+ public RestrictedPreference(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ mHelper.onBindViewHolder(holder);
+ }
+
+ @Override
+ public void performClick() {
+ if (!mHelper.performClick()) {
+ super.performClick();
+ }
+ }
+
+ @Override
+ protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+ mHelper.onAttachedToHierarchy();
+ super.onAttachedToHierarchy(preferenceManager);
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, UserHandle.myUserId());
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
+ }
+
+ public void setDisabledByAdmin(EnforcedAdmin admin) {
+ if (mHelper.setDisabledByAdmin(admin)) {
+ notifyChanged();
+ }
+ }
+
+ public boolean isDisabledByAdmin() {
+ return mHelper.isDisabledByAdmin();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
new file mode 100644
index 0000000..f041504
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -0,0 +1,142 @@
+/*
+ * 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.settingslib;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.text.Spanned;
+import android.text.SpannableStringBuilder;
+import android.text.style.ImageSpan;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.TextView;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+/**
+ * Helper class for managing settings preferences that can be disabled
+ * by device admins via user restrictions.
+ */
+public class RestrictedPreferenceHelper {
+ private final Context mContext;
+ private final Preference mPreference;
+ private final Drawable mRestrictedPadlock;
+ private final int mRestrictedPadlockPadding;
+
+ private boolean mDisabledByAdmin;
+ private EnforcedAdmin mEnforcedAdmin;
+ private String mAttrUserRestriction = null;
+
+ RestrictedPreferenceHelper(Context context, Preference preference,
+ AttributeSet attrs) {
+ mContext = context;
+ mPreference = preference;
+
+ mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
+ mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_padding);
+
+ mAttrUserRestriction = attrs.getAttributeValue(
+ R.styleable.RestrictedPreference_userRestriction);
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.RestrictedPreference);
+ final TypedValue userRestriction =
+ attributes.peekValue(R.styleable.RestrictedPreference_userRestriction);
+ CharSequence data = null;
+ if (userRestriction != null && userRestriction.type == TypedValue.TYPE_STRING) {
+ if (userRestriction.resourceId != 0) {
+ data = context.getText(userRestriction.resourceId);
+ } else {
+ data = userRestriction.string;
+ }
+ }
+ mAttrUserRestriction = data == null ? null : data.toString();
+ }
+
+ /**
+ * Modify PreferenceViewHolder to add padlock if restriction is disabled.
+ */
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
+ if (titleView != null) {
+ RestrictedLockUtils.setTextViewPadlock(mContext, titleView, mDisabledByAdmin);
+ if (mDisabledByAdmin) {
+ holder.itemView.setEnabled(true);
+ }
+ }
+ }
+
+ /**
+ * Check if the preference is disabled if so handle the click by informing the user.
+ *
+ * @return true if the method handled the click.
+ */
+ public boolean performClick() {
+ if (mDisabledByAdmin) {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mEnforcedAdmin);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Disable / enable if we have been passed the restriction in the xml.
+ */
+ protected void onAttachedToHierarchy() {
+ if (mAttrUserRestriction != null) {
+ checkRestrictionAndSetDisabled(mAttrUserRestriction, UserHandle.myUserId());
+ }
+ }
+
+ /**
+ * Set the user restriction that is used to disable this preference.
+ *
+ * @param userRestriction constant from {@link android.os.UserManager}
+ * @param userId user to check the restriction for.
+ */
+ public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
+ EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
+ userRestriction, userId);
+ setDisabledByAdmin(admin);
+ }
+
+ /**
+ * Disable this preference based on the enforce admin.
+ *
+ * @param EnforcedAdmin Details of the admin who enforced the restriction. If it
+ * is {@code null}, then this preference will be enabled. Otherwise, it will be disabled.
+ * @return true if the disabled state was changed.
+ */
+ public boolean setDisabledByAdmin(EnforcedAdmin admin) {
+ final boolean disabled = (admin != null ? true : false);
+ mEnforcedAdmin = (disabled ? admin : null);
+ if (mDisabledByAdmin != disabled) {
+ mDisabledByAdmin = disabled;
+ mPreference.setEnabled(!disabled);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isDisabledByAdmin() {
+ return mDisabledByAdmin;
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
new file mode 100644
index 0000000..308477b0
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -0,0 +1,91 @@
+/*
+ * 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.settingslib;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.support.v14.preference.SwitchPreference;
+import android.util.AttributeSet;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+/**
+ * Version of SwitchPreference that can be disabled by a device admin
+ * using a user restriction.
+ */
+public class RestrictedSwitchPreference extends SwitchPreference {
+ RestrictedPreferenceHelper mHelper;
+
+ public RestrictedSwitchPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mHelper = new RestrictedPreferenceHelper(context, this, attrs);
+ }
+
+ public RestrictedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public RestrictedSwitchPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.switchPreferenceStyle,
+ android.R.attr.switchPreferenceStyle));
+ }
+
+ public RestrictedSwitchPreference(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ mHelper.onBindViewHolder(holder);
+ }
+
+ @Override
+ public void performClick() {
+ if (!mHelper.performClick()) {
+ super.performClick();
+ }
+ }
+
+ @Override
+ protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+ mHelper.onAttachedToHierarchy();
+ super.onAttachedToHierarchy(preferenceManager);
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, UserHandle.myUserId());
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
+ }
+
+ public void setDisabledByAdmin(EnforcedAdmin admin) {
+ if (mHelper.setDisabledByAdmin(admin)) {
+ notifyChanged();
+ }
+ }
+
+ public boolean isDisabledByAdmin() {
+ return mHelper.isDisabledByAdmin();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 621a09cd..72df96d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -1,17 +1,21 @@
package com.android.settingslib;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.UserInfo;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
+import android.os.BatteryManager;
import android.os.UserManager;
-
import com.android.internal.util.UserIcons;
import com.android.settingslib.drawable.CircleFramedDrawable;
-public final class Utils {
+import java.text.NumberFormat;
+
+public class Utils {
/**
* Return string resource that best describes combination of tethering
@@ -81,4 +85,57 @@
return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(
UserIcons.getDefaultUserIcon(user.id, /* light= */ false)));
}
+
+ /** Formats the ratio of amount/total as a percentage. */
+ public static String formatPercentage(long amount, long total) {
+ return formatPercentage(((double) amount) / total);
+ }
+
+ /** Formats an integer from 0..100 as a percentage. */
+ public static String formatPercentage(int percentage) {
+ return formatPercentage(((double) percentage) / 100.0);
+ }
+
+ /** Formats a double from 0.0..1.0 as a percentage. */
+ private static String formatPercentage(double percentage) {
+ return NumberFormat.getPercentInstance().format(percentage);
+ }
+
+ public static int getBatteryLevel(Intent batteryChangedIntent) {
+ int level = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
+ int scale = batteryChangedIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
+ return (level * 100) / scale;
+ }
+
+ public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) {
+ final Intent intent = batteryChangedIntent;
+
+ int plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+ int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ String statusString;
+ if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
+ int resId;
+ if (plugType == BatteryManager.BATTERY_PLUGGED_AC) {
+ resId = R.string.battery_info_status_charging_ac;
+ } else if (plugType == BatteryManager.BATTERY_PLUGGED_USB) {
+ resId = R.string.battery_info_status_charging_usb;
+ } else if (plugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
+ resId = R.string.battery_info_status_charging_wireless;
+ } else {
+ resId = R.string.battery_info_status_charging;
+ }
+ statusString = res.getString(resId);
+ } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
+ statusString = res.getString(R.string.battery_info_status_discharging);
+ } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
+ statusString = res.getString(R.string.battery_info_status_not_charging);
+ } else if (status == BatteryManager.BATTERY_STATUS_FULL) {
+ statusString = res.getString(R.string.battery_info_status_full);
+ } else {
+ statusString = res.getString(R.string.battery_info_status_unknown);
+ }
+
+ return statusString;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
new file mode 100644
index 0000000..f1beb10
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
@@ -0,0 +1,371 @@
+/*
+ * 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.settingslib.users;
+
+import android.app.AppGlobals;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class AppRestrictionsHelper {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "AppRestrictionsHelper";
+
+ private final Context mContext;
+ private final PackageManager mPackageManager;
+ private final IPackageManager mIPm;
+ private final UserManager mUserManager;
+ private final UserHandle mUser;
+ private final boolean mRestrictedProfile;
+
+ HashMap<String,Boolean> mSelectedPackages = new HashMap<>();
+ private List<SelectableAppInfo> mVisibleApps;
+
+ public AppRestrictionsHelper(Context context, UserHandle user) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+ mIPm = AppGlobals.getPackageManager();
+ mUser = user;
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mRestrictedProfile = mUserManager.getUserInfo(mUser.getIdentifier()).isRestricted();
+ }
+
+ public void setPackageSelected(String packageName, boolean selected) {
+ mSelectedPackages.put(packageName, selected);
+ }
+
+ public boolean isPackageSelected(String packageName) {
+ return mSelectedPackages.get(packageName);
+ }
+
+ public List<SelectableAppInfo> getVisibleApps() {
+ return mVisibleApps;
+ }
+
+ public void applyUserAppsStates(OnDisableUiForPackageListener listener) {
+ final int userId = mUser.getIdentifier();
+ if (!mUserManager.getUserInfo(userId).isRestricted() && userId != UserHandle.myUserId()) {
+ Log.e(TAG, "Cannot apply application restrictions on another user!");
+ return;
+ }
+ for (Map.Entry<String,Boolean> entry : mSelectedPackages.entrySet()) {
+ String packageName = entry.getKey();
+ boolean enabled = entry.getValue();
+ applyUserAppState(packageName, enabled, listener);
+ }
+ }
+
+ public void applyUserAppState(String packageName, boolean enabled,
+ OnDisableUiForPackageListener listener) {
+ final int userId = mUser.getIdentifier();
+ if (enabled) {
+ // Enable selected apps
+ try {
+ ApplicationInfo info = mIPm.getApplicationInfo(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ if (info == null || !info.enabled
+ || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
+ mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier());
+ if (DEBUG) {
+ Log.d(TAG, "Installing " + packageName);
+ }
+ }
+ if (info != null && (info.privateFlags&ApplicationInfo.PRIVATE_FLAG_HIDDEN) != 0
+ && (info.flags&ApplicationInfo.FLAG_INSTALLED) != 0) {
+ listener.onDisableUiForPackage(packageName);
+ mIPm.setApplicationHiddenSettingAsUser(packageName, false, userId);
+ if (DEBUG) {
+ Log.d(TAG, "Unhiding " + packageName);
+ }
+ }
+ } catch (RemoteException re) {
+ // Ignore
+ }
+ } else {
+ // Blacklist all other apps, system or downloaded
+ try {
+ ApplicationInfo info = mIPm.getApplicationInfo(packageName, 0, userId);
+ if (info != null) {
+ if (mRestrictedProfile) {
+ mIPm.deletePackageAsUser(packageName, null, mUser.getIdentifier(),
+ PackageManager.DELETE_SYSTEM_APP);
+ if (DEBUG) {
+ Log.d(TAG, "Uninstalling " + packageName);
+ }
+ } else {
+ listener.onDisableUiForPackage(packageName);
+ mIPm.setApplicationHiddenSettingAsUser(packageName, true, userId);
+ if (DEBUG) {
+ Log.d(TAG, "Hiding " + packageName);
+ }
+ }
+ }
+ } catch (RemoteException re) {
+ // Ignore
+ }
+ }
+ }
+
+ public void fetchAndMergeApps() {
+ mVisibleApps = new ArrayList<>();
+ final PackageManager pm = mPackageManager;
+ final IPackageManager ipm = mIPm;
+
+ final HashSet<String> excludePackages = new HashSet<>();
+ addSystemImes(excludePackages);
+
+ // Add launchers
+ Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
+ launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ addSystemApps(mVisibleApps, launcherIntent, excludePackages);
+
+ // Add widgets
+ Intent widgetIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
+ addSystemApps(mVisibleApps, widgetIntent, excludePackages);
+
+ List<ApplicationInfo> installedApps = pm.getInstalledApplications(
+ PackageManager.MATCH_UNINSTALLED_PACKAGES);
+ for (ApplicationInfo app : installedApps) {
+ // If it's not installed, skip
+ if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue;
+
+ if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+ && (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) {
+ // Downloaded app
+ SelectableAppInfo info = new SelectableAppInfo();
+ info.packageName = app.packageName;
+ info.appName = app.loadLabel(pm);
+ info.activityName = info.appName;
+ info.icon = app.loadIcon(pm);
+ mVisibleApps.add(info);
+ } else {
+ try {
+ PackageInfo pi = pm.getPackageInfo(app.packageName, 0);
+ // If it's a system app that requires an account and doesn't see restricted
+ // accounts, mark for removal. It might get shown in the UI if it has an icon
+ // but will still be marked as false and immutable.
+ if (mRestrictedProfile
+ && pi.requiredAccountType != null && pi.restrictedAccountType == null) {
+ mSelectedPackages.put(app.packageName, false);
+ }
+ } catch (PackageManager.NameNotFoundException re) {
+ // Skip
+ }
+ }
+ }
+
+ // Get the list of apps already installed for the user
+ List<ApplicationInfo> userApps = null;
+ try {
+ ParceledListSlice<ApplicationInfo> listSlice = ipm.getInstalledApplications(
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, mUser.getIdentifier());
+ if (listSlice != null) {
+ userApps = listSlice.getList();
+ }
+ } catch (RemoteException re) {
+ // Ignore
+ }
+
+ if (userApps != null) {
+ for (ApplicationInfo app : userApps) {
+ if ((app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) continue;
+
+ if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+ && (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) {
+ // Downloaded app
+ SelectableAppInfo info = new SelectableAppInfo();
+ info.packageName = app.packageName;
+ info.appName = app.loadLabel(pm);
+ info.activityName = info.appName;
+ info.icon = app.loadIcon(pm);
+ mVisibleApps.add(info);
+ }
+ }
+ }
+
+ // Sort the list of visible apps
+ Collections.sort(mVisibleApps, new AppLabelComparator());
+
+ // Remove dupes
+ Set<String> dedupPackageSet = new HashSet<String>();
+ for (int i = mVisibleApps.size() - 1; i >= 0; i--) {
+ SelectableAppInfo info = mVisibleApps.get(i);
+ if (DEBUG) Log.i(TAG, info.toString());
+ String both = info.packageName + "+" + info.activityName;
+ if (!TextUtils.isEmpty(info.packageName)
+ && !TextUtils.isEmpty(info.activityName)
+ && dedupPackageSet.contains(both)) {
+ mVisibleApps.remove(i);
+ } else {
+ dedupPackageSet.add(both);
+ }
+ }
+
+ // Establish master/slave relationship for entries that share a package name
+ HashMap<String,SelectableAppInfo> packageMap = new HashMap<String,SelectableAppInfo>();
+ for (SelectableAppInfo info : mVisibleApps) {
+ if (packageMap.containsKey(info.packageName)) {
+ info.masterEntry = packageMap.get(info.packageName);
+ } else {
+ packageMap.put(info.packageName, info);
+ }
+ }
+ }
+
+ /**
+ * Find all pre-installed input methods that are marked as default
+ * and add them to an exclusion list so that they aren't
+ * presented to the user for toggling.
+ * Don't add non-default ones, as they may include other stuff that we
+ * don't need to auto-include.
+ * @param excludePackages the set of package names to append to
+ */
+ private void addSystemImes(Set<String> excludePackages) {
+ InputMethodManager imm = (InputMethodManager)
+ mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ List<InputMethodInfo> imis = imm.getInputMethodList();
+ for (InputMethodInfo imi : imis) {
+ try {
+ if (imi.isDefault(mContext) && isSystemPackage(imi.getPackageName())) {
+ excludePackages.add(imi.getPackageName());
+ }
+ } catch (Resources.NotFoundException rnfe) {
+ // Not default
+ }
+ }
+ }
+
+ /**
+ * Add system apps that match an intent to the list, excluding any packages in the exclude list.
+ * @param visibleApps list of apps to append the new list to
+ * @param intent the intent to match
+ * @param excludePackages the set of package names to be excluded, since they're required
+ */
+ private void addSystemApps(List<SelectableAppInfo> visibleApps, Intent intent,
+ Set<String> excludePackages) {
+ final PackageManager pm = mPackageManager;
+ List<ResolveInfo> launchableApps = pm.queryIntentActivities(intent,
+ PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+ for (ResolveInfo app : launchableApps) {
+ if (app.activityInfo != null && app.activityInfo.applicationInfo != null) {
+ final String packageName = app.activityInfo.packageName;
+ int flags = app.activityInfo.applicationInfo.flags;
+ if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0
+ || (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ // System app
+ // Skip excluded packages
+ if (excludePackages.contains(packageName)) continue;
+ int enabled = pm.getApplicationEnabledSetting(packageName);
+ if (enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ || enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+ // Check if the app is already enabled for the target user
+ ApplicationInfo targetUserAppInfo = getAppInfoForUser(packageName,
+ 0, mUser);
+ if (targetUserAppInfo == null
+ || (targetUserAppInfo.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
+ continue;
+ }
+ }
+ SelectableAppInfo info = new SelectableAppInfo();
+ info.packageName = app.activityInfo.packageName;
+ info.appName = app.activityInfo.applicationInfo.loadLabel(pm);
+ info.icon = app.activityInfo.loadIcon(pm);
+ info.activityName = app.activityInfo.loadLabel(pm);
+ if (info.activityName == null) info.activityName = info.appName;
+
+ visibleApps.add(info);
+ }
+ }
+ }
+ }
+
+ private boolean isSystemPackage(String packageName) {
+ try {
+ final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+ if (pi.applicationInfo == null) return false;
+ final int flags = pi.applicationInfo.flags;
+ if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0
+ || (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+ return true;
+ }
+ } catch (PackageManager.NameNotFoundException nnfe) {
+ // Missing package?
+ }
+ return false;
+ }
+
+ private ApplicationInfo getAppInfoForUser(String packageName, int flags, UserHandle user) {
+ try {
+ return mIPm.getApplicationInfo(packageName, flags, user.getIdentifier());
+ } catch (RemoteException re) {
+ return null;
+ }
+ }
+
+ public interface OnDisableUiForPackageListener {
+ void onDisableUiForPackage(String packageName);
+ }
+
+ public static class SelectableAppInfo {
+ public String packageName;
+ public CharSequence appName;
+ public CharSequence activityName;
+ public Drawable icon;
+ public SelectableAppInfo masterEntry;
+
+ @Override
+ public String toString() {
+ return packageName + ": appName=" + appName + "; activityName=" + activityName
+ + "; icon=" + icon + "; masterEntry=" + masterEntry;
+ }
+ }
+
+ private static class AppLabelComparator implements Comparator<SelectableAppInfo> {
+
+ @Override
+ public int compare(SelectableAppInfo lhs, SelectableAppInfo rhs) {
+ String lhsLabel = lhs.activityName.toString();
+ String rhsLabel = rhs.activityName.toString();
+ return lhsLabel.toLowerCase().compareTo(rhsLabel.toLowerCase());
+ }
+ }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9546c8d..6201fd6 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -58,6 +58,7 @@
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
<uses-permission android:name="android.permission.CONTROL_VPN" />
<uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
@@ -142,6 +143,9 @@
<!-- Block notifications inline notifications -->
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+ <!-- Access battery information -->
+ <uses-permission android:name="android.permission.BATTERY_STATS" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
new file mode 100644
index 0000000..ea4db4b
--- /dev/null
+++ b/packages/SystemUI/res/layout/battery_detail.xml
@@ -0,0 +1,64 @@
+<?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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="true">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="32dp" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toStartOf="@android:id/toggle"
+ android:layout_toEndOf="@android:id/icon"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary"
+ android:text="@string/battery_detail_switch_title" />
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_toStartOf="@android:id/toggle"
+ android:layout_toEndOf="@android:id/icon"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary"
+ android:text="@string/battery_detail_switch_summary" />
+
+ <Switch
+ android:id="@android:id/toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginEnd="16dp"
+ android:clickable="false"
+ android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 83cfc76..cce07bd 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -23,16 +23,16 @@
android:id="@+id/remote_input"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:paddingStart="16dp"
- android:paddingEnd="12dp"
- android:paddingBottom="4dp"
- android:paddingTop="2dp">
+ android:paddingEnd="12dp">
<view class="com.android.systemui.statusbar.policy.RemoteInputView$RemoteEditText"
android:id="@+id/remote_input_text"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1"
+ android:paddingTop="2dp"
+ android:paddingBottom="4dp"
+ android:paddingStart="16dp"
android:paddingEnd="12dp"
android:gravity="start|center_vertical"
android:textAppearance="?android:attr/textAppearance"
@@ -47,7 +47,9 @@
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical">
+ android:layout_gravity="center_vertical"
+ android:paddingTop="2dp"
+ android:paddingBottom="4dp">
<ImageButton
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 7ac9c41..39da8d0 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -84,16 +84,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- <com.android.systemui.statusbar.phone.PanelHolder
- android:id="@+id/panel_holder"
+ <include layout="@layout/status_bar_expanded"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/transparent" >
- <include layout="@layout/status_bar_expanded"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone" />
- </com.android.systemui.statusbar.phone.PanelHolder>
+ android:visibility="gone" />
<com.android.systemui.statusbar.ScrimView android:id="@+id/scrim_in_front"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 0187993..19fb28e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Pas toe"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bevestig instellings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Sommige kleurinstellings kan hierdie toestel onbruikbaar maak. Klik OK om hierdie kleurinstellings te bevestig; andersins sal hierdie instellings ná 10 sekondes teruggestel word."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Battery (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterybespaarder is nie beskikbaar wanneer gelaai word nie"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterybespaarder"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Verminder werkverrigting en agtergronddata"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 503a767..208aaff 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"ተግብር"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ቅንብሮችን ያረጋግጡ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"አንዳንድ የቀለም ቅንብሮች ይህን መሣሪያ የማይጠቅም ሊያደርጉት ይችላሉ። እነዚህን የቀለም ቅንብሮች ለማረጋገጥ እሺ የሚለውን ጠቅ ያድርጉ፣ አለበለዚያ እነዚህ ቅንብሮች ከ10 ሰከንዶች በኋላ ዳግም ይጀምራሉ።"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ባትሪ (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index d89d036..35e78c2 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -476,4 +476,8 @@
<string name="color_apply" msgid="9212602012641034283">"تطبيق"</string>
<string name="color_revert_title" msgid="4746666545480534663">"تأكيد الإعدادات"</string>
<string name="color_revert_message" msgid="9116001069397996691">"يمكن أن تتسبب بعض إعدادات الألوان في تعطيل إمكانية استخدام الجهاز. يمكنك النقر على \"موافق\" لتأكيد إعدادات الألوان هذه، وإلا فستتم إعادة تعيين هذه الإعدادات بعد 10 ثوانٍ."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"البطارية (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 55f0841..864fd32 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Tətbiq edin"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Ayarları təsdiq edin"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bəzi renk ayarları bu cihazı yararsız edə bilər. Bu rənk ayarlarını təsdiq etmək üçün OK basın, əks halda bu ayarlar 10 saniyə sonra sıfırlanacaq."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Enerji (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Enerji Qənaəti doldurulma zamanı əlçatan deyil"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Enerji Qənaəti"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Performansı azaldır və arxa fon datasını məhdudlaşdırır"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 4056963..6879d75 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -473,4 +473,8 @@
<string name="color_apply" msgid="9212602012641034283">"Primeni"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdite podešavanja"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Neka podešavanja boja mogu da učine uređaj neupotrebljivim. Kliknite na Potvrdi da biste potvrdili ova podešavanja boja, pošto će se u suprotnom ova podešavanja resetovati nakon 10 sekundi."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Baterija (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ušteda baterije nije dostupna tokom punjenja"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ušteda baterije"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Smanjuje performanse i pozadinske podatke"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 93c26a4..f5713c2 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Прилагане"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Потвърждаване на настройките"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Някои настройки за цветовете могат да направят това устройство неизползваемо. За да ги потвърдите, кликнете върху „OK“. В противен случай те ще бъдат нулирани след 10 секунди."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Батерия (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 939465b6..bfcb258 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"প্রয়োগ করুন"</string>
<string name="color_revert_title" msgid="4746666545480534663">"সেটিংস নিশ্চিত করুন"</string>
<string name="color_revert_message" msgid="9116001069397996691">"কিছু রঙের সেটিংস এই ডিভাইসকে ব্যবহারের অযোগ্য করে দিতে পারে৷ এই রঙের সেটিংস নিশ্চিত করতে ওকে এ ক্লিক করুন, অন্যথায় ১০ সেকেন্ড পরে এই সেটিংস পুনরায় সেট হবে৷"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ব্যাটারি (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e19aa0e..c7a30f0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplica"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirma la configuració"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunes opcions de configuració de color poden deixar el dispositiu inservible. Fes clic a D\'acord per confirmar la configuració de color; en cas contrari, la configuració es restablirà al cap de 10 segons."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateria (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"La funció Estalvi de bateria no està disponible durant la càrrega"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Estalvi de bateria"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Redueix el rendiment i les dades en segon pla"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index b1cd561..df18347 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"Použít"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Ověření nastavení"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Některá nastavení barev mohou způsobit, že zařízení nebude použitelné. Kliknutím na OK toto nastavení barev potvrdíte, v opačném případě se nastavení po 10 sekundách resetuje."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Baterie (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Spořič baterie při nabíjení není k dispozici."</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Spořič baterie"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Omezuje výkon a data na pozadí"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 2100c57..d69e943 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Anvend"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bekræft indstillingerne"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Nogle farveindstillinger kan medføre, at du ikke kan bruge enheden. Klik på OK for at bekræfte disse farveindstillinger. Ellers nulstilles disse indstillinger efter ti sekunder."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batteri (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparefunktionen er ikke tilgængelig under opladning"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparefunktion"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reducerer ydeevne og baggrundsdata"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 1ad5b26..9e17f253 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -35,7 +35,7 @@
<string name="battery_low_title" msgid="6456385927409742437">"Akku ist schwach"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend"</string>
<string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend. Der Energiesparmodus ist aktiviert."</string>
- <string name="invalid_charger" msgid="4549105996740522523">"USB-Aufladung wird nicht unterstützt.\nVerwenden Sie das mitgelieferte Aufladegerät."</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB-Aufladung wird nicht unterstützt.\nVerwende das mitgelieferte Aufladegerät."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"Laden per USB wird nicht unterstützt."</string>
<string name="invalid_charger_text" msgid="5474997287953892710">"Verwenden Sie nur das im Lieferumfang enthaltene Ladegerät."</string>
<string name="battery_low_why" msgid="4553600287639198111">"Einstellungen"</string>
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Übernehmen"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Einstellungen bestätigen"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Einige Farbeinstellungen können dazu führen, dass das Gerät nicht mehr genutzt werden kann. Klicke auf \"OK\", um diese Farbeinstellungen zu bestätigen. Anderenfalls werden diese Einstellungen in 10 Sekunden zurückgesetzt."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Akku (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Der Energiesparmodus ist beim Aufladen nicht verfügbar."</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Energiesparmodus"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduzierung der Leistung und Hintergrunddaten"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f56d630..fb09669 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Εφαρμογή"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Επιβεβαίωση ρυθμίσεων"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Ορισμένες ρυθμίσεις χρωμάτων μπορεί να μην επιτρέπουν τη χρήση αυτής της συσκευής. Κάντε κλικ στην επιλογή OK για να επιβεβαιώσετε αυτές τις ρυθμίσεις χρωμάτων, διαφορετικά θα γίνει επαναφορά αυτών των ρυθμίσεων μετά από 10 δευτερόλεπτα."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Μπαταρία (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index f6fc997..a96c23c 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Apply"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Battery (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index f6fc997..a96c23c 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Apply"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Battery (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index f6fc997..a96c23c 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Apply"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Battery (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduces performance and background data"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index fd59418..6ba8a43 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar la configuración"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden provocar que el dispositivo quede inutilizable. Haz clic en Aceptar para confirmar estos parámetros de color. De lo contrario, la configuración se restablecerá en diez segundos."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batería (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no está disponible durante la carga"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce el rendimiento y el uso de datos en segundo plano"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 223e684..0598078 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden hacer que el dispositivo no se pueda utilizar. Haz clic en Aceptar para confirmar esta configuración. Si no lo haces, se restablecerá esta configuración cuando transcurran 10 segundos."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batería (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no disponible mientras se carga el dispositivo"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce el rendimiento y las conexiones automáticas"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index f50e78c..8d25d48 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Rakenda"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Seadete kinnitamine"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Mõni värviseade ei saa seadet võib-olla kasutada. Nende värviseadete kinnitamiseks klõpsake OK, muidu lähtestatakse need seaded 10 sekundi pärast."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Aku (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akusäästja pole laadimise ajal saadaval"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akusäästja"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Vähendab jõudlust ja taustaandmeid"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index c481f52..fc96b42 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplikatu"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Berretsi ezarpenak"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Baliteke gailua kolore-ezarpen batzuekin ezin erabili izatea. Kolore-ezarpenak berresteko, sakatu Ados. Bestela, hamar segundoren buruan berrezarriko dira ezarpenak."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateria (%% <xliff:g id="ID_1">%1$d</xliff:g>)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Bateria-aurrezlea ez dago erabilgarri gailua kargatzen ari denean"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Bateria-aurrezlea"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Errendimendua eta atzeko planoko datuen erabilera murrizten ditu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 3dee7c9..3a98e9c 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"اعمال کردن"</string>
<string name="color_revert_title" msgid="4746666545480534663">"تأیید تنظیمات"</string>
<string name="color_revert_message" msgid="9116001069397996691">"بعضی از تنظیمات رنگ میتوانند این دستگاه را غیرقابل استفاده کنند. برای تأیید این تنظیمات رنگ روی «تأیید» کلیک کنید، در غیر این صورت این تغییرات بعد از ۱۰ ثانیه بازنشانی میشوند."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"باتری (<xliff:g id="ID_1">%1$d</xliff:g>٪٪)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4a5c302..8c963af 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Käytä"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Vahvista asetukset"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Jotkin väriasetukset voivat häiritä laitteen käyttöä. Vahvista uudet väriasetukset valitsemalla OK. Muussa tapauksessa aiemmat asetukset palautetaan 10 sekunnin kuluttua."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Akku (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Virransäästö ei ole käytettävissä latauksen aikana."</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Virransäästö"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Rajoittaa suorituskykyä ja taustatiedonsiirtoa."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 2a4f4d9..bcde17a 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmer les paramètres"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur « OK » pour valider ces paramètres, sinon ils seront réinitialisés après 10 secondes."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Pile (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Le mode Économie d\'énergie n\'est pas accessible pendant la charge"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Économie d\'énergie"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Réduit les performances et les données en arrière-plan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 928a8b3..952baab 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Vérifier les paramètres"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur \"OK\" pour valider ces paramètres, sans quoi ils seront réinitialisés après 10 secondes."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batterie (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"L\'économiseur de batterie n\'est pas disponible lorsque l\'appareil est en charge."</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Économiseur de batterie"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Limite les performances et les données en arrière-plan."</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 2a951f7..9d490c2 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algunhas opcións de configuración de cor poden facer que este dispositivo sexa inutilizable. Fai clic en Aceptar para confirmar esta configuración de cor; en caso contrario, a configuración restablecerase tras 10 segundos."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batería (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A función aforro de batería non está dispoñible durante a carga"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Aforro de batería"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce o rendemento e os datos en segundo plano"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index f331ef9..d45167f 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"લાગુ કરો"</string>
<string name="color_revert_title" msgid="4746666545480534663">"સેટિંગ્સની પુષ્ટિ કરો"</string>
<string name="color_revert_message" msgid="9116001069397996691">"કેટલીક રંગ સેટિંગ્સ આ ઉપકરણને બિનઉપયોગી બનાવી શકે છે. આ રંગ સેટિંગ્સની પુષ્ટિ કરવા માટે ઑકે ક્લિક કરો, અન્યથા 10 સેકંડ પછી આ સેટિંગ્સ ફરીથી સેટ થશે."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"બૅટરી (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index b31c1e0..3e2ab2a 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"लागू करें"</string>
<string name="color_revert_title" msgid="4746666545480534663">"सेेटिंग की पुष्टि करें"</string>
<string name="color_revert_message" msgid="9116001069397996691">"कुछ रंग सेटिंग इस डिवाइस को अनुपयोगी बना सकती हैं. इन रंग सेटिंग की पुष्टि करने के लिए ठीक क्लिक करें, अन्यथा 10 सेकंड के बाद ये सेटिंग रीसेट हो जाएंगी."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"बैटरी (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 3bef6e9..fbdc5fe 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -473,4 +473,8 @@
<string name="color_apply" msgid="9212602012641034283">"Primijeni"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdite postavke"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Neke postavke boja mogu učiniti uređaj neupotrebljivim. Kliknite U redu da biste potvrdili postavke boja jer će se u suprotnom poništiti za 10 sekundi."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Baterija (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Štednja baterije nije dostupna tijekom punjenja"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Štednja baterije"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Smanjuje količinu rada i pozadinske podatke"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8dc9a19..9d26c36 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Alkalmaz"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Beállítások megerősítése"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bizonyos színbeállítások használhatatlanná tehetik ezt az eszközt. A színbeállítás megerősítéséhez kattintson az OK lehetőségre, máskülönben a rendszer 10 másodpercen belül visszaáll a korábbira."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Akkumulátor (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Az Akkumulátorkímélő módot töltés közben nem lehet használni"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akkumulátorkímélő mód"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Csökkenti a teljesítményt és a háttéradatok használatát"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 99d6980..29e3a29 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Կիրառել"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Հաստատել կարգավորումները"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Գունային որոշ կարգավորումները կարող են այս սարքը օգտագործման համար ոչ պիտանի դարձնել: Սեղմեք Լավ կոճակը՝ գունային այս կարգավորումները հաստատելու համար: Հակառակ դեպքում այս կարգավորումները կվերակայվեն 10 վայրկյան հետո:"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Մարտկոց (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f6124db..f7f3370 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Terapkan"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Konfirmasi setelan"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Beberapa setelan warna dapat membuat perangkat ini tidak dapat digunakan. Klik OKE untuk mengonfirmasi setelan warna ini. Jika tidak, setelan ini akan disetel ulang setelah 10 detik."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Baterai (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penghemat Baterai tidak tersedia selama pengisian daya"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Penghemat Baterai"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Mengurangi performa dan data latar belakang"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 7ea1746..c1d3591 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Nota"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Staðfesta stillingar"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Sumar litastillingar kunna að bitna á notagildi tækisins. Veldu „Í lagi“ til að staðfesta þessar litastillingar, að öðrum kosti verða litirnir endurstilltir eftir tíu sekúndur."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Rafhlaða (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ekki er hægt að nota rafhlöðusparnað meðan á hleðslu stendur"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Rafhlöðusparnaður"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Dregur úr afköstum og bakgrunnsgögnum"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b395f8b..dd65970 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Applica"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Conferma le impostazioni"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Alcune impostazioni relative ai colori potrebbero rendere inutilizzabile il dispositivo. Fai clic su OK per confermare queste impostazioni; in caso contrario, le impostazioni verranno reimpostate dopo 10 secondi."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batteria (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Risparmio energetico non disponibile durante la ricarica"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Risparmio energetico"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Riduce le prestazioni e i dati in background"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 2c894f5..95bbe20 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"החל"</string>
<string name="color_revert_title" msgid="4746666545480534663">"אישור הגדרות"</string>
<string name="color_revert_message" msgid="9116001069397996691">"הגדרות צבע מסוימות עלולות להפוך את המכשיר הזה לבלתי שמיש. לחץ על אישור כדי לאשר את הגדרות הצבע האלה, אחרת הגדרות אלה יתאפסו לאחר 10 שניות."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"סוללה (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 580d995..ed0c7e9 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"適用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"設定の確認"</string>
<string name="color_revert_message" msgid="9116001069397996691">"一部の色設定を適用すると、この端末を使用できなくなることがあります。この色設定を確認するには、[OK] をクリックしてください。確認しない場合、10 秒後に設定はリセットされます。"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"バッテリー(<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 7a51668..5c861f8 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"გამოყენება"</string>
<string name="color_revert_title" msgid="4746666545480534663">"პარამეტრების დადასტურება"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ფერთა ზოგიერთ პარამეტრს ამ მოწყობილობასთან მუშაობის გართულება შეუძლია. ფერთა ამჟამინდელი პარამეტრების დასადასტურებლად, დააწკაპუნეთ „კარგი“-ზე. წინააღმდეგ შემთხვევაში, პარამეტრები 10 წამის შემდეგ ჩამოიყრება."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ბატარეა (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index eb8995e..42e6a5d 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Қолдану"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Параметрлерді растау"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Кейбір түс параметрлері бұл құрылғыны пайдалану мүмкін емес етуі мүмкін. Бұл түс параметрлерін растау үшін OK түймесін басыңыз, әйтпесе параметрлер 10 секундтан кейін ысырылады."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Батарея (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 5c10213..53f5868 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"អនុវត្ត"</string>
<string name="color_revert_title" msgid="4746666545480534663">"បញ្ជាក់ការកំណត់"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ការកំណត់ពណ៌មួយចំនួនអាចធ្វើឲ្យឧបករណ៍នេះមិនអាចប្រើបាន។ សូមចុច យល់ព្រម ដើម្បីបញ្ជាក់ការកំណត់ពណ៌ទាំងនេះ បើមិនដូច្នេះទេការកំណត់ទាំងនេះនឹងកំណត់ឡើងវិញក្នុងរយៈពេល 10 វិនាទីបន្ទាប់។"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ថ្ម (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 28b2de5..1b212f0 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"ಅನ್ವಯಿಸು"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಖಚಿತಪಡಿಸಿ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ಕೆಲವು ಬಣ್ಣ ಸೆಟ್ಟಿಂಗ್ಗಳು ಈ ಸಾಧನವನ್ನು ಅನುಪಯುಕ್ತಗೊಳಿಸಬಹುದು. ಈ ಬಣ್ಣ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಖಚಿತಪಡಿಸಲು ಸರಿ ಕ್ಲಿಕ್ ಮಾಡಿ, ಇಲ್ಲವಾದರೆ ಈ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು 10 ಸೆಕೆಂಡುಗಳ ನಂತರ ಮರುಹೊಂದಿಸಿ."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ಬ್ಯಾಟರಿ (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 110376f..ecff2ad 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"적용"</string>
<string name="color_revert_title" msgid="4746666545480534663">"설정 확인"</string>
<string name="color_revert_message" msgid="9116001069397996691">"일부 색상 설정으로 인해 이 기기를 사용하지 못할 수 있습니다. 확인을 클릭하여 이러한 색상 설정을 확인하지 않으면 10초 후에 설정이 초기화됩니다."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"배터리(<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index ee2ef5d..ad430ec 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Колдонуу"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Жөндөөлөрдү ырастоо"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Айрым түс жөндөөлөрү бул түзмөктү колдонулгус кылып коюшу мүмкүн. Бул түс жөндөөлөрүн ырастоо үчүн OK баскычын чыкылдатыңыз, болбосо бул жөндөөлөр 10 секунддан кийин баштапкы абалына келтирилет."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Батарея (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index ed103ea..48d94cd 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"ນຳໃຊ້"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ຢືນຢັນການຕັ້ງຄ່າ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ບາງການຕັ້ງຄ່າສີສາມາດເຮັດໃຫ້ອຸປະກອນນີ້ບໍ່ສາມາດໃຊ້ໄດ້. ຄລິກ ຕົກລົງ ເພື່ອຢືນຢັນການຕັ້ງຄ່າສີເຫຼົ່ານີ້, ຖ້າບໍ່ດັ່ງນັ້ນ ການຕັ້ງຄ່າເຫຼົ່ານີ້ຈະຕັ້ງຄືນໃໝ່ ຫຼັງຈາກ 10 ວິນາທີ."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ແບັດເຕີຣີ (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index ba98e2b..adb5a53 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"Taikyti"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Nustatymų patvirtinimas"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Dėl kai kurių spalvų nustatymų įrenginys gali būti netinkamas naudoti. Spustelėkite „Gerai“, kad patvirtintumėte šiuos spalvų nustatymus. Kitaip šie nustatymai bus nustatyti iš naujo po 10 sekundžių."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Akumuliatorius (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumuliatoriaus tausojimo priemonė nepasiekiama įkraunant"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumuliatoriaus tausojimo priemonė"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Sumažinamas našumas ir foninių duomenų naudojimas"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 0143fea..b8a6d01 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -473,4 +473,8 @@
<string name="color_apply" msgid="9212602012641034283">"Lietot"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Iestatījumu apstiprināšana"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Noteiktu krāsu iestatījumu dēļ šī ierīce var kļūt nelietojama. Lai apstiprinātu šos krāsu iestatījumus, noklikšķiniet uz Labi. Ja to neizdarīsiet, pēc 10 sekundēm šie iestatījumi tiks atiestatīti."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Akumulators (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumulatora jaudas taupīšanas režīms uzlādes laikā nav pieejams."</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumulatora jaudas taupīšanas režīms"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Samazina veiktspēju un fona datus."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index c573139..8ba8094 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Примени"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Потврдете ги поставките"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Некои поставки на боите може да го направат уредот неупотреблив. Кликнете на Во ред за да ги потврдите овие поставки на боите, инаку тие поставки ќе се ресетираат по 10 секунди."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Батерија (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index c6a08e6..240373b 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"ബാധകമാക്കുക"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ക്രമീകരണം സ്ഥിരീകരിക്കുക"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ചില വർണ്ണ ക്രമീകരണത്തിന് ഈ ഉപകരണത്തെ ഉപയോഗരഹിതമാക്കാനാകും. ഈ വർണ്ണ ക്രമീകരണം സ്ഥിരീകരിക്കുന്നതിന് ശരി എന്നതിൽ ക്ലിക്കുചെയ്യുക, അല്ലെങ്കിൽ 10 സെക്കൻഡിന് ശേഷം ഈ ക്രമീകരണം പുനഃക്രമീകരിക്കപ്പെടും."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ബാറ്ററി (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 91c817a..de5c035 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -470,4 +470,8 @@
<string name="color_apply" msgid="9212602012641034283">"Хэрэгжүүлэх"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Тохиргоог баталгаажуулах"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Зарим өнгөний тохиргоо энэ төхөөрөмжийг ашиглах боломжгүй болгож болзошгүй. OK товчлуурыг дарж эдгээр өнгөний тохиргоог зөвшөөрөхгүй бол энэ тохиргоо нь 10 секундын дараа шинэчлэгдэх болно."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Тэжээл (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 5d3a96f..80dc12e 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"लागू करा"</string>
<string name="color_revert_title" msgid="4746666545480534663">"सेटिंग्जची पुष्टी करा"</string>
<string name="color_revert_message" msgid="9116001069397996691">"काही रंग सेटिंग्ज या डिव्हाइसला निरुपयोगी करू शकतात. या रंग सेटिंग्जची पुष्टी करण्यासाठी ठीक आहे दाबा अन्यथा या सेटिंग्ज 10 सेकंदांनंतर रीसेट होतील."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"बॅटरी (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index f0a013c..ec4b28c 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Gunakan"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Sahkan tetapan"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Sesetengah tetapan warna boleh menjadikan peranti ini tidak dapat digunakan. Klik OK untuk mengesahkan tetapan warna ini, jika tidak, tetapan ini akan ditetapkan semula selepas 10 saat."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateri (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penjimat Bateri tidak tersedia semasa mengecas"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Penjimat Bateri"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Mengurangkan prestasi dan data latar belakang"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 75008cb..257dd43 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"အသုံးပြုပါ"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ဆက်တင်များကို အတည်ပြုပါ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"အချို့သော အရောင်ဆက်တက်များက ဤကိရိယာကို သုံးမရအောင် လုပ်ပစ်နိုင်ပါသည်။ ဤအရောင် ဆက်တင်များကို အတည်ပြုရန် အိုကေကို နှိပ်ပါ၊ သို့မဟုတ် ဤဆက်တင်များကို ၁၀ စက္ကန့် အကြာတွင် ပြန်ညှိလိုက်ပါမည်။"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ဘက်ထရီ ( <xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"အားသွင်းနေချိန်မှာ Battery Saver ကို သုံးမရပါ"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"လုပ်ဆောင်မှု နှင့် နောက်ခံ ဒေတာကို လျော့နည်းစေပါသည်"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 295a49a..4446a77 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Bruk"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bekreft innstillingene"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Noen fargeinnstillinger kan gjøre denne enheten ubrukelig. Klikk på OK for å bekrefte disse fargeinnstillingene, ellers blir de tilbakestilt etter ti sekunder."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batteri (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparing er ikke tilgjengelig under lading"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparing"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduserer ytelsen og begrenser bakgrunnsdataene"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index d0aa510..f1009550 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"लागू गर्नुहोस्"</string>
<string name="color_revert_title" msgid="4746666545480534663">"सेटिङहरूको पुष्टि गर्नुहोस्"</string>
<string name="color_revert_message" msgid="9116001069397996691">"केही रङ सेटिङहरूले यस यन्त्रलाई अनुपयोगी बनाउन सक्छन्। यी रङ सेटिङहरू पुष्टि गर्न ठीक छ मा क्लिक गर्नुहोस्, अन्यथा यी सेटिङहरू १० सेकेण्डपछि रिसेट हुनेछन्।"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ब्याट्री (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 75812ad..c6562d6 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Toepassen"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Instellingen bevestigen"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bij sommige kleurinstellingen kan het apparaat onbruikbaar worden. Klik op OK om deze kleurinstellingen te bevestigen, anders worden deze instellingen na tien seconden gereset."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Accu (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Accubesparing niet beschikbaar tijdens opladen"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Accubesparing"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Vermindert de prestaties en achtergrondgegevens"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index fc5a3ea..fd17dac 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"ਲਾਗੂ ਕਰੋ"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ਸੈਟਿੰਗਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
<string name="color_revert_message" msgid="9116001069397996691">"ਕੁਝ ਰੰਗ ਸੈਟਿੰਗਾਂ ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਬੇਕਾਰ ਕਰ ਸਕਦੀਆਂ ਹਨ। ਇਹਨਾਂ ਰੰਗ ਸੈਟਿੰਗਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਠੀਕ \'ਤੇ ਕਲਿੱਕ ਕਰੋ, ਨਹੀਂ ਤਾਂ ਇਹ ਸੈਟਿੰਗਾਂ 10 ਸਕਿੰਟ ਬਾਅਦ ਮੁੜ-ਸੈੱਟ ਹੋ ਜਾਣਗੀਆਂ।"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"ਬੈਟਰੀ (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 8ef50c9..3630429 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"Zastosuj"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potwierdź ustawienia"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Niektóre ustawienia kolorów mogą utrudniać korzystanie z urządzenia. Kliknij OK, by potwierdzić te ustawienia kolorów. Jeśli tego nie zrobisz, zostaną one zresetowane po 10 sekundach."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateria (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Oszczędzanie baterii nie jest dostępne podczas ładowania"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Oszczędzanie baterii"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Zmniejsza wydajność i ogranicza dane w tle"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 8f61478..7fa28ad 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateria (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados em segundo plano"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8a727a1..3d29d7e 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar as definições"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas definições de cor podem tornar este dispositivo instável. Clique em OK para confirmar estas definições de cor. Caso contrário, estas definições serão repostas após 10 segundos."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateria (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Poupança de bateria não disponível durante o carregamento"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Poupança de bateria"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados de segundo plano"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 8f61478..7fa28ad 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateria (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduz o desempenho e os dados em segundo plano"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 3ab8bf2..13f3ef2 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -473,4 +473,8 @@
<string name="color_apply" msgid="9212602012641034283">"Aplicați"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmați setările"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Unele setări pentru culori pot face dispozitivul să nu mai funcționeze. Dați clic pe OK pentru a confirma aceste setări pentru culori. În caz contrar, acestea se vor reseta după 10 secunde."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Baterie (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Economisirea bateriei nu este disponibilă pe durata încărcării"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Economisirea bateriei"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Reduce performanța și datele de fundal"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 6ffd333..4d7ee69 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"Применить"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Подтвердите настройки"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Некоторые цветовые настройки могут затруднить работу с устройством. Чтобы применить выбранные параметры, нажмите \"ОК\". В противном случае они будут сброшены через 10 секунд."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Батарея (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index efbc042..f73ff6c 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"යොදන්න"</string>
<string name="color_revert_title" msgid="4746666545480534663">"සැකසීම් තහවුරු කරන්න"</string>
<string name="color_revert_message" msgid="9116001069397996691">"සමහර වර්ණ සැකසීම් මෙම උපාංගය භාවිත කළ නොහැකි තත්ත්වයට පත් කළ හැකිය. මෙම වර්ණ සැකසීම් තහවුරු කිරීමට හරි ක්ලික් කරන්න, නැතහොත් මෙම සැකසීම් තත්පර 10කට පසුව යළි සකසනු ඇත."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"බැටරිය (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 31985b4..ddf2de8 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"Použiť"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdenie nastavení"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Niektoré nastavenia farieb môžu toto zariadenie znefunkčniť. Tieto nastavenia farieb potvrdíte kliknutím na tlačidlo OK, ináč sa tieto nastavenia o 10 sekúnd obnovia."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batéria (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Počas nabíjania nie je Šetrič batérie k dispozícii"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Šetrič batérie"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Obmedzí výkonnosť a údaje na pozadí"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 7c8d443..249c1ad 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"Uporabi"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potrditev nastavitev"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Zaradi nekaterih barvnih nastavitev lahko postane ta naprava neuporabna. Kliknite »V redu«, če želite potrditi te barvne nastavitve. V nasprotnem primeru se bodo čez 10 sekund ponastavile na prvotno vrednost."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Akumulator (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Varčevanje z energijo akumulatorja med polnjenjem ni na voljo"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Varčevanje z energijo akumulatorja"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Omeji zmogljivost delovanja in prenos podatkov v ozadju"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index c8add94..60e2e80 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Zbato"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Konfirmo cilësimet"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Disa cilësime ngjyrash mund ta bëjnë këtë pajisje të papërdorshme. Kliko OK për të konfirmuar këto cilësime ngjyrash, përndryshe këto cilësime do të rivendosen pas 10 sekondash."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Bateria (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"\"Kursyesi i baterisë\" nuk është i disponueshëm gjatë karikimit"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Kursyesi i baterisë"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Pakëson veprimtarinë dhe të dhënat në sfond"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index bec1fd4..4954f05 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -473,4 +473,8 @@
<string name="color_apply" msgid="9212602012641034283">"Примени"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Потврдите подешавања"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Нека подешавања боја могу да учине уређај неупотребљивим. Кликните на Потврди да бисте потврдили ова подешавања боја, пошто ће се у супротном ова подешавања ресетовати након 10 секунди."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Батерија (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d4a9cdc..8f67f0e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Verkställ"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Bekräfta inställningarna"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Vissa färginställningar kan göra den här enheten oanvändbar. Klicka på OK om du vill bekräfta färginställningarna, annars återställs inställningarna efter 10 sekunder."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Batteri (<xliff:g id="ID_1">%1$d</xliff:g> %%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparläget är inte tillgängligt vid laddning"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparläge"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Minskar prestanda och bakgrundsdata"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 2ffbf2b..0f66826 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Tumia"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Thibitisha mipangilio"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Baadhi ya mipangilio ya rangi inaweza kufanya kifaa hiki kisitumike. Bofya Sawa ili uthibitishe mipangilio hii ya rangi, vinginevyo, mipangilio hii itajiweka upya baada ya sekunde 10."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Betri (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Kiokoa Betri hakipatikani unapochaji betri"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Kiokoa Betri"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Hupunguza data ya chini chini na utendaji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 168a11b..0653843 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"பயன்படுத்து"</string>
<string name="color_revert_title" msgid="4746666545480534663">"அமைப்புகளை உறுதிப்படுத்து"</string>
<string name="color_revert_message" msgid="9116001069397996691">"சில வண்ண அமைப்புகள் இந்தச் சாதனத்தைப் பயன்படுத்த முடியாதபடி செய்யலாம். இந்த வண்ண அமைப்புகளை உறுதிப்படுத்த, சரி என்பதைக் கிளிக் செய்யவும், இல்லையெனில் இந்த அமைப்புகள் 10 வினாடிகளுக்குப் பின் மீட்டமைக்கப்படும்."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"பேட்டரி (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 086dede..f711544 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"వర్తింపజేయి"</string>
<string name="color_revert_title" msgid="4746666545480534663">"సెట్టింగ్లను నిర్ధారించండి"</string>
<string name="color_revert_message" msgid="9116001069397996691">"కొన్ని రంగు సెట్టింగ్ల వలన ఈ పరికరం ఉపయోగించలేని విధంగా అయిపోవచ్చు. ఈ రంగు సెట్టింగ్లను నిర్ధారించడానికి సరే క్లిక్ చేయండి లేదంటే ఈ సెట్టింగ్లు 10 సెకన్ల తర్వాత రీసెట్ చేయబడతాయి."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"బ్యాటరీ (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8c1a7d3..8c284a1 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"ใช้"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ยืนยันการตั้งค่า"</string>
<string name="color_revert_message" msgid="9116001069397996691">"การตั้งค่าสีบางอย่างอาจทำให้อุปกรณ์นี้ใช้งานไม่ได้ คลิกตกลงเพื่อยืนยันการตั้งค่าสีเหล่านี้ มิฉะนั้นระบบจะรีเซ็ตการตั้งค่าหลังจาก 10 วินาที"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"แบตเตอรี่ (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 4bee3ea..33e5968 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Ilapat"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Kumpirmahin ang mga setting"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Maaaring hindi magamit ang device na ito dahil sa ilang setting ng kulay. I-click ang OK upang kumpirmahin ang mga setting ng kulay na ito, kung hindi ay mare-reset ang mga setting na ito pagkatapos ng 10 segundo."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Baterya (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Hindi available ang Pangtipid sa Baterya kapag nagcha-charge"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Pangtipid sa Baterya"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Binabawasan ang pagganap at data sa background"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index c0ecc78..d937dc3 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Uygula"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Ayarları onaylayın"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Bazı renkler bu cihazı kullanılmaz yapabilir. Bu renkleri onaylamak için Tamam\'ı tıklayın. Tıklamazsanız bu ayarlar 10 saniye sonra sıfırlanacaktır."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Pil (%%<xliff:g id="ID_1">%1$d</xliff:g>)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Şarj sırasında Pil Tasarrufu özelliği kullanılamaz"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Pil Tasarrufu"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Performansı ve arka plan verilerini azaltır"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 3109403..5503cb8 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -474,4 +474,8 @@
<string name="color_apply" msgid="9212602012641034283">"Застосувати"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Підтвердити налаштування"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Деякі налаштування кольорів можуть зробити цей пристрій непридатним для використання. Натисніть OK, щоб підтвердити налаштування, інакше їх буде скинуто через 10 секунд."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Акумулятор (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 52aa580..f3dea97 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"لاگو کریں"</string>
<string name="color_revert_title" msgid="4746666545480534663">"ترتیبات کی توثیق کریں"</string>
<string name="color_revert_message" msgid="9116001069397996691">"رنگوں کی کچھ ترتیبات اس آلے کو ناقابل استعمال بنا سکتی ہیں۔ رنگوں کی ان ترتیبات کی توثیق کرنے کیلئے ٹھیک ہے پر کلک کریں، بصورت دیگر 10 سیکنڈ بعد یہ ترتیبات ری سیٹ ہو جائیں گی۔"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"بیٹری (%%<xliff:g id="ID_1">%1$d</xliff:g>)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index a849cfc..c781082 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Qo‘llash"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Sozlamalarni tasdiqlang"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Ba’zi rang sozlamalari qurilmadan foydalanishni qiyinlashtirish mumkin. Tanlgan parametrlarni tasdiqlash uchun “OK” tugmasini bosing. Aks holda, ular 10 soniyadan so‘ng qayta tiklanadi."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Quvvat (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Quvvat tejash rejimi"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Unumdorlikni pasaytiradi va fonda internetdan foydalanishni cheklaydi"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index fa835ba..38283ad 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Áp dụng"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Xác nhận cài đặt"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Một số cài đặt màu có thể khiến thiết bị này không sử dụng được. Hãy nhấp vào OK để xác nhận các cài đặt màu này, nếu không những cài đặt này sẽ được đặt lại sau 10 giây."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Pin (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Trình tiết kiệm pin không khả dụng trong khi sạc"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Trình tiết kiệm pin"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Giảm hiệu suất và dữ liệu nền"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index bb8f4ad..8534d82 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -77,7 +77,7 @@
<string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器(MTP)装载"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"作为相机(PTP)装载"</string>
- <string name="installer_cd_button_title" msgid="2312667578562201583">"安装适用于Mac的Android文件传输应用"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"安装适用于 Mac 的 Android 文件传输应用"</string>
<string name="accessibility_back" msgid="567011538994429120">"返回"</string>
<string name="accessibility_home" msgid="8217216074895377641">"主屏幕"</string>
<string name="accessibility_menu" msgid="316839303324695949">"菜单"</string>
@@ -460,10 +460,8 @@
<string name="notification_importance_default" msgid="4926529615920610817">"显示这些通知,但不发出提示音"</string>
<string name="notification_importance_high" msgid="3222680136612408223">"在通知列表顶部显示,并发出提示音"</string>
<string name="notification_importance_max" msgid="5236987171904756134">"在屏幕上持续显示,并发出提示音"</string>
- <!-- no translation found for notification_more_settings (816306283396553571) -->
- <skip />
- <!-- no translation found for notification_done (5279426047273930175) -->
- <skip />
+ <string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
+ <string name="notification_done" msgid="5279426047273930175">"完成"</string>
<string name="color_matrix_none" msgid="2121957926040543148">"常规颜色"</string>
<string name="color_matrix_night" msgid="5943817622105307072">"夜间颜色"</string>
<string name="color_matrix_custom" msgid="3655576492322298713">"自定义颜色"</string>
@@ -474,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"应用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"确认设置"</string>
<string name="color_revert_message" msgid="9116001069397996691">"部分颜色设置可能会导致此设备无法使用。请点击“确定”确认这些颜色设置,否则,系统将在 10 秒后重置这些设置。"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"电池 (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 0782354..0f0ac69 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"套用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"確認設定"</string>
<string name="color_revert_message" msgid="9116001069397996691">"部分顏色設定會令此裝置無法使用。請按一下 [確定] 加以確認,否則這些顏色設定將於 10 秒後重設。"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"電池電量 (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 29520f6..3139e41 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"套用"</string>
<string name="color_revert_title" msgid="4746666545480534663">"確認設定"</string>
<string name="color_revert_message" msgid="9116001069397996691">"部分顏色設定可能會造成這部裝置無法使用。請按一下 [確定] 來確認您要使用這類顏色設定,否則系統將在 10 秒後重設這些設定。"</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"電池 (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</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>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 3ee46ea..b93596a 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -472,4 +472,8 @@
<string name="color_apply" msgid="9212602012641034283">"Sebenzisa"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Qinisekisa izilungiselelo"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Ezinye izilungiselelo zombala zingenza le divayisi ingasebenziseki. Chofoza ku-KULUNGILE ukuze uqinisekise lezi zilungiselelo zombala, uma kungenjalo lezi zilungiselelo zizosethwa kabusha ngemuva kwamasekhondi angu-10."</string>
+ <string name="battery_panel_title" msgid="3476715163685592453">"Ibhethri (<xliff:g id="ID_1">%1$d</xliff:g>%%)"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Isilondolozi sebhethri asitholakali ngesikhathi sokushaja"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Isilondolozi sebhethri"</string>
+ <string name="battery_detail_switch_summary" msgid="9049111149407626804">"Sehlisa ukusebenza nedatha yasemuva"</string>
</resources>
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index 6102aa6..bf0cba2 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -37,4 +37,18 @@
<item>157</item><item>334</item>
<item>0</item> <item>334</item>
</array>
+ <array name="batterymeter_plus_points">
+ <item>3</item><item>0</item>
+ <item>5</item><item>0</item>
+ <item>5</item><item>3</item>
+ <item>8</item><item>3</item>
+ <item>8</item><item>5</item>
+ <item>5</item><item>5</item>
+ <item>5</item><item>8</item>
+ <item>3</item><item>8</item>
+ <item>3</item><item>5</item>
+ <item>0</item><item>5</item>
+ <item>0</item><item>3</item>
+ <item>3</item><item>3</item>
+ </array>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0ccc236..0a56f92 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -62,8 +62,6 @@
<color name="recents_task_bar_light_icon_color">#ffeeeeee</color>
<!-- The recents task bar dark dismiss icon color to be drawn on top of light backgrounds. -->
<color name="recents_task_bar_dark_icon_color">#99000000</color>
- <!-- The recents task bar highlight color. -->
- <color name="recents_task_bar_highlight_color">#28ffffff</color>
<!-- The lock to task button background color. -->
<color name="recents_task_view_lock_to_app_button_background_color">#ffe6e6e6</color>
<!-- The lock to task button foreground color. -->
@@ -149,4 +147,8 @@
<color name="default_remote_input_background">@*android:color/notification_default_color</color>
<color name="remote_input_hint">#4dffffff</color>
+
+ <color name="qs_tile_tint_unavailable">#40ffffff</color>
+ <color name="qs_tile_tint_inactive">#4dffffff</color>
+ <color name="qs_tile_tint_active">#ffffffff</color>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 035f564..097c352 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -198,16 +198,16 @@
<dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
<!-- The min translation in the Z index for the last task. -->
- <dimen name="recents_task_view_z_min">20dp</dimen>
+ <dimen name="recents_task_view_z_min">16dp</dimen>
<!-- The max translation in the Z index for the last task. -->
- <dimen name="recents_task_view_z_max">80dp</dimen>
+ <dimen name="recents_task_view_z_max">48dp</dimen>
<!-- The amount to translate when animating the removal of a task. -->
<dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
<!-- The amount of highlight to make on each task view. -->
- <dimen name="recents_task_view_highlight">1.5dp</dimen>
+ <dimen name="recents_task_view_highlight">1dp</dimen>
<!-- The amount to offset when animating into an affiliate group. -->
<dimen name="recents_task_view_affiliate_group_enter_offset">64dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 876c21e..0e4f98f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1269,4 +1269,25 @@
<string name="color_modification_g" translatable="false">G</string>
<string name="color_modification_b" translatable="false">B</string>
+ <!-- Title of the battery settings detail panel [CHAR LIMIT=20] -->
+ <string name="battery_panel_title">Battery (<xliff:g name="pattery_percent" example="52">%1$d</xliff:g>%%)</string>
+
+ <!-- Summary of battery saver not available [CHAR LIMIT=NONE] -->
+ <string name="battery_detail_charging_summary">Battery Saver not available during charging</string>
+
+ <!-- Title of switch for battery saver [CHAR LIMIT=NONE] -->
+ <string name="battery_detail_switch_title">Battery Saver</string>
+
+ <!-- Summary of switch for battery saver [CHAR LIMIT=NONE] -->
+ <string name="battery_detail_switch_summary">Reduces performance and background data</string>
+
+ <!-- User visible title for the system-wide keyboard shortcuts list. -->
+ <string name="keyboard_shortcut_group_system">System</string>
+ <!-- User visible title for the keyboard shortcut that takes the user to the home screen. -->
+ <string name="keyboard_shortcut_group_system_home">Home</string>
+ <!-- User visible title for the the keyboard shortcut that takes the user to the recents screen. -->
+ <string name="keyboard_shortcut_group_system_recents">Recents</string>
+ <!-- User visible title for the the keyboard shortcut that triggers the back action. -->
+ <string name="keyboard_shortcut_group_system_back">Back</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
index 3eb1271..38ae345 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -49,7 +49,8 @@
private float mButtonHeightFraction;
private float mSubpixelSmoothingLeft;
private float mSubpixelSmoothingRight;
- private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
+ private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint,
+ mPlusPaint;
private float mTextHeight, mWarningTextHeight;
private int mIconTint = Color.WHITE;
@@ -60,10 +61,13 @@
private int mChargeColor;
private final float[] mBoltPoints;
private final Path mBoltPath = new Path();
+ private final float[] mPlusPoints;
+ private final Path mPlusPath = new Path();
private final RectF mFrame = new RectF();
private final RectF mButtonFrame = new RectF();
private final RectF mBoltFrame = new RectF();
+ private final RectF mPlusFrame = new RectF();
private final Path mShapePath = new Path();
private final Path mClipPath = new Path();
@@ -141,6 +145,9 @@
mBoltPaint.setColor(context.getColor(R.color.batterymeter_bolt_color));
mBoltPoints = loadBoltPoints(res);
+ mPlusPaint = new Paint(mBoltPaint);
+ mPlusPoints = loadPlusPoints(res);
+
mDarkModeBackgroundColor =
context.getColor(R.color.dark_mode_icon_color_dual_tone_background);
mDarkModeFillColor = context.getColor(R.color.dark_mode_icon_color_dual_tone_fill);
@@ -187,8 +194,8 @@
}
@Override
- public void onPowerSaveChanged() {
- mPowerSaveEnabled = mBatteryController.isPowerSave();
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ mPowerSaveEnabled = isPowerSave;
invalidateSelf();
}
@@ -207,6 +214,21 @@
return ptsF;
}
+ private static float[] loadPlusPoints(Resources res) {
+ final int[] pts = res.getIntArray(R.array.batterymeter_plus_points);
+ int maxX = 0, maxY = 0;
+ for (int i = 0; i < pts.length; i += 2) {
+ maxX = Math.max(maxX, pts[i]);
+ maxY = Math.max(maxY, pts[i + 1]);
+ }
+ final float[] ptsF = new float[pts.length];
+ for (int i = 0; i < pts.length; i += 2) {
+ ptsF[i] = (float)pts[i] / maxX;
+ ptsF[i + 1] = (float)pts[i + 1] / maxY;
+ }
+ return ptsF;
+ }
+
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
@@ -328,9 +350,9 @@
if (mPluggedIn) {
// define the bolt shape
- final float bl = mFrame.left + mFrame.width() / 4.5f;
+ final float bl = mFrame.left + mFrame.width() / 4f;
final float bt = mFrame.top + mFrame.height() / 6f;
- final float br = mFrame.right - mFrame.width() / 7f;
+ final float br = mFrame.right - mFrame.width() / 4f;
final float bb = mFrame.bottom - mFrame.height() / 10f;
if (mBoltFrame.left != bl || mBoltFrame.top != bt
|| mBoltFrame.right != br || mBoltFrame.bottom != bb) {
@@ -358,6 +380,39 @@
// otherwise cut the bolt out of the overall shape
mShapePath.op(mBoltPath, Path.Op.DIFFERENCE);
}
+ } else if (mPowerSaveEnabled) {
+ // define the plus shape
+ final float pw = mFrame.width() * 2 / 3;
+ final float pl = mFrame.left + (mFrame.width() - pw) / 2;
+ final float pt = mFrame.top + (mFrame.height() - pw) / 2;
+ final float pr = mFrame.right - (mFrame.width() - pw) / 2;
+ final float pb = mFrame.bottom - (mFrame.height() - pw) / 2;
+ if (mPlusFrame.left != pl || mPlusFrame.top != pt
+ || mPlusFrame.right != pr || mPlusFrame.bottom != pb) {
+ mPlusFrame.set(pl, pt, pr, pb);
+ mPlusPath.reset();
+ mPlusPath.moveTo(
+ mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
+ mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
+ for (int i = 2; i < mPlusPoints.length; i += 2) {
+ mPlusPath.lineTo(
+ mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(),
+ mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height());
+ }
+ mPlusPath.lineTo(
+ mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(),
+ mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
+ }
+
+ float boltPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
+ boltPct = Math.min(Math.max(boltPct, 0), 1);
+ if (boltPct <= BOLT_LEVEL_THRESHOLD) {
+ // draw the bolt if opaque
+ c.drawPath(mPlusPath, mPlusPaint);
+ } else {
+ // otherwise cut the bolt out of the overall shape
+ mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
+ }
}
// compute percentage text
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 6cb8da4..cdbdc22 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -74,7 +74,7 @@
}
@Override
- public void onPowerSaveChanged() {
+ public void onPowerSaveChanged(boolean isPowerSave) {
}
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 7f6cda0..99028a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -32,7 +32,7 @@
/**
* Docks the top-most task and opens recents.
*/
- void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds);
+ boolean dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds);
/**
* Called during a drag-from-navbar-in gesture.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 443778e..ed29a8f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -474,10 +474,12 @@
ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+ @Override
public void userActivity() {
KeyguardViewMediator.this.userActivity();
}
+ @Override
public void keyguardDone(boolean strongAuth) {
if (!mKeyguardDonePending) {
KeyguardViewMediator.this.keyguardDone(true /* authenticated */);
@@ -487,6 +489,7 @@
}
}
+ @Override
public void keyguardDoneDrawing() {
mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
}
@@ -741,8 +744,7 @@
long timeout;
- UserInfo user = UserManager.get(mContext).getUserInfo(userId);
- if ((!user.isManagedProfile() && LockPatternUtils.isSeparateWorkChallengeEnabled())
+ if ((mLockPatternUtils.isSeparateProfileChallengeEnabled(userId))
|| policyTimeout <= 0) {
timeout = lockAfterTimeout;
} else {
@@ -782,9 +784,9 @@
private void doKeyguardLaterLockedForChildProfiles() {
UserManager um = UserManager.get(mContext);
List<UserInfo> profiles = um.getEnabledProfiles(UserHandle.myUserId());
- if (LockPatternUtils.isSeparateWorkChallengeEnabled() && profiles.size() > 1) {
+ if (profiles.size() > 1) {
for (UserInfo info : profiles) {
- if (info.id != UserHandle.myUserId() && info.isManagedProfile()) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
long userTimeout = getLockTimeout(info.id);
long userWhen = SystemClock.elapsedRealtime() + userTimeout;
Intent lockIntent = new Intent(DELAYED_LOCK_PROFILE_ACTION);
@@ -1248,7 +1250,9 @@
if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
+ sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
synchronized (KeyguardViewMediator.this) {
- doKeyguardLocked(null);
+ if (mDelayedShowingSequence == sequence) {
+ doKeyguardLocked(null);
+ }
}
} else if (DELAYED_LOCK_PROFILE_ACTION.equals(intent.getAction())) {
int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, 0);
@@ -1698,6 +1702,7 @@
mHandler.removeMessages(KEYGUARD_DONE_PENDING_TIMEOUT);
}
+ @Override
public void onBootCompleted() {
mUpdateMonitor.dispatchBootCompleted();
synchronized (this) {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 19b65f7..ea1c9bf 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -52,7 +52,6 @@
private static final int SHOWING_NOTHING = 0;
private static final int SHOWING_WARNING = 1;
- private static final int SHOWING_SAVER = 2;
private static final int SHOWING_INVALID_CHARGER = 3;
private static final String[] SHOWING_STRINGS = {
"SHOWING_NOTHING",
@@ -63,7 +62,6 @@
private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings";
private static final String ACTION_START_SAVER = "PNW.startSaver";
- private static final String ACTION_STOP_SAVER = "PNW.stopSaver";
private static final String ACTION_DISMISSED_WARNING = "PNW.dismissedWarning";
private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
@@ -77,7 +75,6 @@
private final Handler mHandler = new Handler();
private final Receiver mReceiver = new Receiver();
private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
- private final Intent mOpenSaverSettings = settings(Settings.ACTION_BATTERY_SAVER_SETTINGS);
private int mBatteryLevel;
private int mBucket;
@@ -86,7 +83,6 @@
private long mBucketDroppedNegativeTimeMs;
- private boolean mSaver;
private boolean mWarning;
private boolean mPlaySound;
private boolean mInvalidCharger;
@@ -101,7 +97,6 @@
@Override
public void dump(PrintWriter pw) {
- pw.print("mSaver="); pw.println(mSaver);
pw.print("mWarning="); pw.println(mWarning);
pw.print("mPlaySound="); pw.println(mPlaySound);
pw.print("mInvalidCharger="); pw.println(mInvalidCharger);
@@ -121,27 +116,15 @@
mScreenOffTime = screenOffTime;
}
- @Override
- public void showSaverMode(boolean mode) {
- mSaver = mode;
- if (mSaver && mSaverConfirmation != null) {
- mSaverConfirmation.dismiss();
- }
- updateNotification();
- }
-
private void updateNotification() {
if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning + " mPlaySound="
- + mPlaySound + " mSaver=" + mSaver + " mInvalidCharger=" + mInvalidCharger);
+ + mPlaySound + " mInvalidCharger=" + mInvalidCharger);
if (mInvalidCharger) {
showInvalidChargerNotification();
mShowing = SHOWING_INVALID_CHARGER;
} else if (mWarning) {
showWarningNotification();
mShowing = SHOWING_WARNING;
- } else if (mSaver) {
- showSaverNotification();
- mShowing = SHOWING_SAVER;
} else {
mNoMan.cancelAsUser(TAG_NOTIFICATION, R.id.notification_power, UserHandle.ALL);
mShowing = SHOWING_NOTHING;
@@ -165,8 +148,7 @@
}
private void showWarningNotification() {
- final int textRes = mSaver ? R.string.battery_low_percent_format_saver_started
- : R.string.battery_low_percent_format;
+ final int textRes = R.string.battery_low_percent_format;
final String percentage = NumberFormat.getPercentInstance().format((double) mBatteryLevel / 100.0);
final Notification.Builder nb = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_power_low)
@@ -184,13 +166,9 @@
if (hasBatterySettings()) {
nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
}
- if (!mSaver) {
- nb.addAction(0,
- mContext.getString(R.string.battery_saver_start_action),
- pendingBroadcast(ACTION_START_SAVER));
- } else {
- addStopSaverAction(nb);
- }
+ nb.addAction(0,
+ mContext.getString(R.string.battery_saver_start_action),
+ pendingBroadcast(ACTION_START_SAVER));
if (mPlaySound) {
attachLowBatterySound(nb);
mPlaySound = false;
@@ -199,35 +177,6 @@
mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
}
- private void showSaverNotification() {
- final Notification.Builder nb = new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_power_saver)
- .setContentTitle(mContext.getString(R.string.battery_saver_notification_title))
- .setContentText(mContext.getString(R.string.battery_saver_notification_text))
- .setOngoing(true)
- .setShowWhen(false)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(
- com.android.internal.R.color.battery_saver_mode_color));
- addStopSaverAction(nb);
- if (hasSaverSettings()) {
- nb.setContentIntent(pendingActivity(mOpenSaverSettings));
- }
- mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, nb.build(), UserHandle.ALL);
- }
-
- private void addStopSaverAction(Notification.Builder nb) {
- nb.addAction(0,
- mContext.getString(R.string.battery_saver_notification_action_text),
- pendingBroadcast(ACTION_STOP_SAVER));
- }
-
- private void dismissSaverNotification() {
- if (mSaver) Slog.i(TAG, "dismissing saver notification");
- mSaver = false;
- updateNotification();
- }
-
private PendingIntent pendingActivity(Intent intent) {
return PendingIntent.getActivityAsUser(mContext,
0, intent, 0, null, UserHandle.CURRENT);
@@ -272,10 +221,6 @@
return mOpenBatterySettings.resolveActivity(mContext.getPackageManager()) != null;
}
- private boolean hasSaverSettings() {
- return mOpenSaverSettings.resolveActivity(mContext.getPackageManager()) != null;
- }
-
@Override
public void showLowBatteryWarning(boolean playSound) {
Slog.i(TAG,
@@ -367,7 +312,6 @@
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
filter.addAction(ACTION_START_SAVER);
- filter.addAction(ACTION_STOP_SAVER);
filter.addAction(ACTION_DISMISSED_WARNING);
mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,
android.Manifest.permission.STATUS_BAR_SERVICE, mHandler);
@@ -383,10 +327,6 @@
} else if (action.equals(ACTION_START_SAVER)) {
dismissLowBatteryNotification();
showStartSaverConfirmation();
- } else if (action.equals(ACTION_STOP_SAVER)) {
- dismissSaverNotification();
- dismissLowBatteryNotification();
- setSaverMode(false);
} else if (action.equals(ACTION_DISMISSED_WARNING)) {
dismissLowBatteryWarning();
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 9459740..522d533 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -76,10 +76,6 @@
mReceiver.init();
}
- private void setSaverMode(boolean mode) {
- mWarnings.showSaverMode(mode);
- }
-
void updateBatteryWarningLevels() {
int critLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
@@ -141,11 +137,6 @@
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
mContext.registerReceiver(this, filter, null, mHandler);
- updateSaverMode();
- }
-
- private void updateSaverMode() {
- setSaverMode(mPowerManager.isPowerSaveMode());
}
@Override
@@ -210,10 +201,6 @@
mScreenOffTime = -1;
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
mWarnings.userSwitched();
- } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
- updateSaverMode();
- } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGING.equals(action)) {
- setSaverMode(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
} else {
Slog.w(TAG, "unknown intent: " + intent);
}
@@ -251,7 +238,6 @@
public interface WarningsUI {
void update(int batteryLevel, int bucket, long screenOffTime);
- void showSaverMode(boolean mode);
void dismissLowBatteryWarning();
void showLowBatteryWarning(boolean playSound);
void dismissInvalidChargerWarning();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 16fd9eb..fd07e50 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -329,16 +329,19 @@
drawTile(r, state);
}
}
+
@Override
public void onShowDetail(boolean show) {
QSPanel.this.showDetail(show, r);
}
+
@Override
public void onToggleStateChanged(boolean state) {
if (mDetailRecord == r) {
fireToggleStateChanged(state);
}
}
+
@Override
public void onScanStateChanged(boolean state) {
r.scanState = state;
@@ -352,7 +355,7 @@
announceForAccessibility(announcement);
}
};
- r.tile.setCallback(callback);
+ r.tile.addCallback(callback);
final View.OnClickListener click = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -415,6 +418,9 @@
}
protected void handleShowDetail(Record r, boolean show) {
+ if (show && !mExpanded) {
+ mHost.animateExpandQS();
+ }
if (r instanceof TileRecord) {
handleShowDetailTile((TileRecord) r, show);
} else {
@@ -466,7 +472,7 @@
MetricsLogger.visible(mContext, detailAdapter.getMetricsCategory());
announceForAccessibility(mContext.getString(
R.string.accessibility_quick_settings_detail,
- mContext.getString(detailAdapter.getTitle())));
+ detailAdapter.getTitle()));
setDetailRecord(r);
listener = mHideGridContentWhenDone;
if (r instanceof TileRecord && visibleDiff) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index b6776bb..2d9d105 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
@@ -62,7 +63,7 @@
protected final H mHandler;
protected final Handler mUiHandler = new Handler(Looper.getMainLooper());
- private Callback mCallback;
+ private final ArrayList<Callback> mCallbacks = new ArrayList<>();
protected TState mState = newTileState();
private TState mTmpState = newTileState();
private boolean mAnnounceNextStateChange;
@@ -109,7 +110,7 @@
}
public interface DetailAdapter {
- int getTitle();
+ CharSequence getTitle();
Boolean getToggleState();
View createDetailView(Context context, View convertView, ViewGroup parent);
Intent getSettingsIntent();
@@ -119,8 +120,8 @@
// safe to call from any thread
- public void setCallback(Callback callback) {
- mHandler.obtainMessage(H.SET_CALLBACK, callback).sendToTarget();
+ public void addCallback(Callback callback) {
+ mHandler.obtainMessage(H.ADD_CALLBACK, callback).sendToTarget();
}
public void click() {
@@ -177,8 +178,8 @@
// call only on tile worker looper
- private void handleSetCallback(Callback callback) {
- mCallback = callback;
+ private void handleAddCallback(Callback callback) {
+ mCallbacks.add(callback);
handleRefreshState(null);
}
@@ -206,12 +207,14 @@
private void handleStateChanged() {
boolean delayAnnouncement = shouldAnnouncementBeDelayed();
- if (mCallback != null) {
- mCallback.onStateChanged(mState);
+ if (mCallbacks.size() != 0) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onStateChanged(mState);
+ }
if (mAnnounceNextStateChange && !delayAnnouncement) {
String announcement = composeChangeAnnouncement();
if (announcement != null) {
- mCallback.onAnnouncementRequested(announcement);
+ mCallbacks.get(0).onAnnouncementRequested(announcement);
}
}
}
@@ -227,20 +230,20 @@
}
private void handleShowDetail(boolean show) {
- if (mCallback != null) {
- mCallback.onShowDetail(show);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onShowDetail(show);
}
}
private void handleToggleStateChanged(boolean state) {
- if (mCallback != null) {
- mCallback.onToggleStateChanged(state);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onToggleStateChanged(state);
}
}
private void handleScanStateChanged(boolean state) {
- if (mCallback != null) {
- mCallback.onScanStateChanged(state);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onScanStateChanged(state);
}
}
@@ -250,11 +253,11 @@
protected void handleDestroy() {
setListening(false);
- mCallback = null;
+ mCallbacks.clear();
}
protected final class H extends Handler {
- private static final int SET_CALLBACK = 1;
+ private static final int ADD_CALLBACK = 1;
private static final int CLICK = 2;
private static final int SECONDARY_CLICK = 3;
private static final int LONG_CLICK = 4;
@@ -274,9 +277,9 @@
public void handleMessage(Message msg) {
String name = null;
try {
- if (msg.what == SET_CALLBACK) {
- name = "handleSetCallback";
- handleSetCallback((QSTile.Callback)msg.obj);
+ if (msg.what == ADD_CALLBACK) {
+ name = "handleAddCallback";
+ handleAddCallback((QSTile.Callback)msg.obj);
} else if (msg.what == CLICK) {
name = "handleClick";
mAnnounceNextStateChange = true;
@@ -333,6 +336,7 @@
void startRunnableDismissingKeyguard(Runnable runnable);
void warn(String message, Throwable t);
void collapsePanels();
+ void animateExpandQS();
void openPanels();
Looper getLooper();
Context getContext();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 5fa38c6..5782800 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -60,14 +60,8 @@
}
@Override
- protected void handleShowDetail(QSPanel.Record r, boolean show) {
- if (show) {
- mHeader.performClick();
- mFullPanel.showDetail(show, r);
- } else {
- // Not sure how we would end up here...
- super.handleShowDetail(r, show);
- }
+ protected void showDetail(boolean show, Record r) {
+ // Do nothing, will be handled by the QSPanel.
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
index 95ff611..ac4f05f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
@@ -19,8 +19,9 @@
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
-
+import android.graphics.drawable.Drawable;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
public class BlankCustomTile extends QSTile<QSTile.State> {
@@ -72,7 +73,9 @@
try {
PackageManager pm = mContext.getPackageManager();
ServiceInfo info = pm.getServiceInfo(mComponent, 0);
- state.icon = new DrawableIcon(info.loadIcon(pm));
+ Drawable drawable = info.loadIcon(pm);
+ drawable.setTint(mContext.getColor(R.color.qs_tile_tint_active));
+ state.icon = new DrawableIcon(drawable);
state.label = info.loadLabel(pm).toString();
state.contentDescription = state.label;
} catch (Exception e) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java
index 7448493..eab4dca 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java
@@ -69,6 +69,11 @@
}
@Override
+ protected void showDetail(boolean show, Record r) {
+ // No detail here.
+ }
+
+ @Override
protected void onDetachedFromWindow() {
// Don't allow the super to unregister the tunable.
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index eefff30..d398b64 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -25,11 +25,14 @@
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.IWindowManager;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -88,6 +91,7 @@
mTile.setIcon(tile.getIcon());
mTile.setLabel(tile.getLabel());
mTile.setContentDescription(tile.getContentDescription());
+ mTile.setState(tile.getState());
}
public void onDialogShown() {
@@ -147,6 +151,9 @@
@Override
protected void handleClick() {
+ if (mTile.getState() == Tile.STATE_UNAVAILABLE) {
+ return;
+ }
try {
if (DEBUG) Log.d(TAG, "Adding token");
mWindowManager.addWindowToken(mToken, WindowManager.LayoutParams.TYPE_QS_DIALOG);
@@ -172,9 +179,15 @@
@Override
protected void handleUpdateState(State state, Object arg) {
Drawable drawable = mTile.getIcon().loadDrawable(mContext);
- drawable.setTint(mContext.getColor(android.R.color.white));
+ int color = mContext.getColor(getColor(mTile.getState()));
+ drawable.setTint(color);
state.icon = new DrawableIcon(drawable);
state.label = mTile.getLabel();
+ if (mTile.getState() == Tile.STATE_UNAVAILABLE) {
+ state.label = new SpannableStringBuilder().append(state.label,
+ new ForegroundColorSpan(color),
+ SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
+ }
if (mTile.getContentDescription() != null) {
state.contentDescription = mTile.getContentDescription();
} else {
@@ -187,6 +200,30 @@
return MetricsLogger.QS_CUSTOM;
}
+ public void startUnlockAndRun() {
+ mHost.startRunnableDismissingKeyguard(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mService.onUnlockComplete();
+ } catch (RemoteException e) {
+ }
+ }
+ });
+ }
+
+ private static int getColor(int state) {
+ switch (state) {
+ case Tile.STATE_UNAVAILABLE:
+ return R.color.qs_tile_tint_unavailable;
+ case Tile.STATE_INACTIVE:
+ return R.color.qs_tile_tint_inactive;
+ case Tile.STATE_ACTIVE:
+ return R.color.qs_tile_tint_active;
+ }
+ return 0;
+ }
+
public static ComponentName getComponentFromSpec(String spec) {
final String action = spec.substring(PREFIX.length(), spec.length() - 1);
if (action.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index d41cdde..3830ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -104,4 +104,14 @@
return false;
}
}
+
+ public boolean onUnlockComplete() {
+ try {
+ mService.onUnlockComplete();
+ return true;
+ } catch (Exception e) {
+ Log.d(TAG, "Caught exception from TileService", e);
+ return false;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 8c5e87e..4977d80 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -55,6 +55,7 @@
private static final int MSG_ON_ADDED = 0;
private static final int MSG_ON_REMOVED = 1;
private static final int MSG_ON_CLICK = 2;
+ private static final int MSG_ON_UNLOCK_COMPLETE = 3;
// Bind retry control.
private static final int MAX_BIND_RETRIES = 5;
@@ -174,6 +175,15 @@
onClick(mClickBinder);
}
}
+ if (queue.contains(MSG_ON_UNLOCK_COMPLETE)) {
+ if (DEBUG) Log.d(TAG, "Handling pending onUnlockComplete");
+ if (!mListening) {
+ Log.w(TAG, "Managed to get unlock on non-listening state...");
+ // Skipping unlock since lost click privileges.
+ } else {
+ onUnlockComplete();
+ }
+ }
if (queue.contains(MSG_ON_REMOVED)) {
if (DEBUG) Log.d(TAG, "Handling pending onRemoved");
if (mListening) {
@@ -348,6 +358,15 @@
}
@Override
+ public void onUnlockComplete() {
+ if (DEBUG) Log.d(TAG, "onUnlockComplete");
+ if (mWrapper == null || !mWrapper.onUnlockComplete()) {
+ queueMessage(MSG_ON_UNLOCK_COMPLETE);
+ handleDeath();
+ }
+ }
+
+ @Override
public IBinder asBinder() {
return mWrapper != null ? mWrapper.asBinder() : null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index a831c87..44d8776 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -36,6 +36,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import java.util.ArrayList;
import java.util.Collections;
@@ -199,6 +200,16 @@
}
@Override
+ public void onStartActivity(Tile tile) {
+ ComponentName componentName = tile.getComponentName();
+ verifyCaller(componentName.getPackageName());
+ CustomTile customTile = getTileForComponent(componentName);
+ if (customTile != null) {
+ mHost.collapsePanels();
+ }
+ }
+
+ @Override
public void updateStatusIcon(Tile tile, Icon icon, String contentDescription) {
final ComponentName componentName = tile.getComponentName();
String packageName = componentName.getPackageName();
@@ -228,6 +239,28 @@
}
}
+ @Override
+ public void startUnlockAndRun(Tile tile) {
+ ComponentName componentName = tile.getComponentName();
+ verifyCaller(componentName.getPackageName());
+ CustomTile customTile = getTileForComponent(componentName);
+ if (customTile != null) {
+ customTile.startUnlockAndRun();
+ }
+ }
+
+ @Override
+ public boolean isLocked() {
+ KeyguardMonitor keyguardMonitor = mHost.getKeyguardMonitor();
+ return keyguardMonitor.isShowing();
+ }
+
+ @Override
+ public boolean isSecure() {
+ KeyguardMonitor keyguardMonitor = mHost.getKeyguardMonitor();
+ return keyguardMonitor.isSecure() && keyguardMonitor.isShowing();
+ }
+
private CustomTile getTileForComponent(ComponentName component) {
synchronized (mServices) {
return mTiles.get(component);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 84eac65..60238fc3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -19,7 +19,14 @@
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Checkable;
+import android.widget.ImageView;
+import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+import com.android.settingslib.BatteryInfo;
import com.android.systemui.BatteryMeterDrawable;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -31,8 +38,11 @@
private final BatteryMeterDrawable mDrawable;
private final BatteryController mBatteryController;
+ private final BatteryDetail mBatteryDetail = new BatteryDetail();
private int mLevel;
+ private boolean mPowerSave;
+ private boolean mCharging;
public BatteryTile(Host host) {
super(host);
@@ -48,6 +58,11 @@
}
@Override
+ public DetailAdapter getDetailAdapter() {
+ return mBatteryDetail;
+ }
+
+ @Override
public int getMetricsCategory() {
return MetricsLogger.QS_BATTERY_TILE;
}
@@ -64,8 +79,16 @@
}
@Override
+ public void setDetailListening(boolean listening) {
+ super.setDetailListening(listening);
+ if (!listening) {
+ mBatteryDetail.mCurrentView = null;
+ }
+ }
+
+ @Override
protected void handleClick() {
- mHost.startActivityDismissingKeyguard(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY));
+ showDetail(true);
}
@Override
@@ -85,11 +108,98 @@
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
mLevel = level;
+ mCharging = charging;
refreshState((Integer) level);
+ if (mBatteryDetail.mCurrentView != null) {
+ mBatteryDetail.bindView();
+ }
}
@Override
- public void onPowerSaveChanged() {
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ mPowerSave = isPowerSave;
+ if (mBatteryDetail.mCurrentView != null) {
+ mBatteryDetail.bindView();
+ }
+ }
+ private final class BatteryDetail implements DetailAdapter, View.OnClickListener {
+ private final BatteryMeterDrawable mDrawable = new BatteryMeterDrawable(mHost.getContext(),
+ new Handler(), mHost.getContext().getColor(R.color.batterymeter_frame_color));
+ private View mCurrentView;
+
+ @Override
+ public CharSequence getTitle() {
+ return mContext.getString(R.string.battery_panel_title, mLevel);
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = LayoutInflater.from(mContext).inflate(R.layout.battery_detail, parent,
+ false);
+ }
+ mCurrentView = convertView;
+ bindView();
+ return convertView;
+ }
+
+ private void bindView() {
+ mDrawable.onBatteryLevelChanged(100, false, false);
+ mDrawable.onPowerSaveChanged(true);
+ ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
+ Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
+ checkbox.setChecked(mPowerSave);
+ if (mCharging) {
+ BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
+ @Override
+ public void onBatteryInfoLoaded(BatteryInfo info) {
+ if (mCurrentView != null && mCharging) {
+ ((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
+ info.mChargeLabelString);
+ }
+ }
+ });
+ ((TextView) mCurrentView.findViewById(android.R.id.summary)).setText(
+ R.string.battery_detail_charging_summary);
+ mCurrentView.setClickable(false);
+ mCurrentView.findViewById(android.R.id.icon).setVisibility(View.INVISIBLE);
+ mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.INVISIBLE);
+ } else {
+ ((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
+ R.string.battery_detail_switch_title);
+ ((TextView) mCurrentView.findViewById(android.R.id.summary)).setText(
+ R.string.battery_detail_switch_summary);
+ mCurrentView.setClickable(true);
+ mCurrentView.findViewById(android.R.id.icon).setVisibility(View.VISIBLE);
+ mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.VISIBLE);
+ mCurrentView.setOnClickListener(this);
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ mBatteryController.setPowerSaveMode(!mPowerSave);
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ // No toggle state.
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsLogger.QS_BATTERY_DETAIL;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index cfc09a0..3750290 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -165,8 +165,8 @@
private QSDetailItems mItems;
@Override
- public int getTitle() {
- return R.string.quick_settings_bluetooth_label;
+ public CharSequence getTitle() {
+ return mContext.getString(R.string.quick_settings_bluetooth_label);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index a8e139c..de4c21c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -160,8 +160,8 @@
private QSDetailItems mItems;
@Override
- public int getTitle() {
- return R.string.quick_settings_cast_title;
+ public CharSequence getTitle() {
+ return mContext.getString(R.string.quick_settings_cast_title);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 6c7b337..c1dcfea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -223,8 +223,8 @@
private final class CellularDetailAdapter implements DetailAdapter {
@Override
- public int getTitle() {
- return R.string.quick_settings_cellular_detail_title;
+ public CharSequence getTitle() {
+ return mContext.getString(R.string.quick_settings_cellular_detail_title);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 4f9f46d..4d9b266 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -218,8 +218,8 @@
private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
@Override
- public int getTitle() {
- return R.string.quick_settings_dnd_label;
+ public CharSequence getTitle() {
+ return mContext.getString(R.string.quick_settings_dnd_label);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 48b4096..95ea3f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -240,8 +240,8 @@
private AccessPoint[] mAccessPoints;
@Override
- public int getTitle() {
- return R.string.quick_settings_wifi_label;
+ public CharSequence getTitle() {
+ return mContext.getString(R.string.quick_settings_wifi_label);
}
public Intent getSettingsIntent() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index b81c23a..2baefd5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
@@ -205,7 +206,7 @@
public void showRecents(boolean triggeredFromAltTab, View statusBarView) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
- if (!isDeviceProvisioned()) {
+ if (!isUserSetup()) {
return;
}
@@ -242,7 +243,7 @@
public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
- if (!isDeviceProvisioned()) {
+ if (!isUserSetup()) {
return;
}
@@ -277,7 +278,7 @@
public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
- if (!isDeviceProvisioned()) {
+ if (!isUserSetup()) {
return;
}
@@ -312,7 +313,7 @@
public void preloadRecents() {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
- if (!isDeviceProvisioned()) {
+ if (!isUserSetup()) {
return;
}
@@ -340,7 +341,7 @@
public void cancelPreloadingRecents() {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
- if (!isDeviceProvisioned()) {
+ if (!isUserSetup()) {
return;
}
@@ -365,11 +366,20 @@
}
@Override
- public void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
- mImpl.dockTopTask(draggingInRecents, stackCreateMode,initialBounds);
- if (draggingInRecents) {
- mDraggingInRecentsCurrentUser = sSystemServicesProxy.getCurrentUser();
+ public boolean dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
+ // Ensure the device has been provisioned before allowing the user to interact with
+ // recents
+ if (!isUserSetup()) {
+ return false;
}
+
+ if (mImpl.dockTopTask(draggingInRecents, stackCreateMode,initialBounds)) {
+ if (draggingInRecents) {
+ mDraggingInRecentsCurrentUser = sSystemServicesProxy.getCurrentUser();
+ }
+ return true;
+ }
+ return false;
}
@Override
@@ -422,7 +432,7 @@
public void showNextAffiliatedTask() {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
- if (!isDeviceProvisioned()) {
+ if (!isUserSetup()) {
return;
}
@@ -433,7 +443,7 @@
public void showPrevAffiliatedTask() {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
- if (!isDeviceProvisioned()) {
+ if (!isUserSetup()) {
return;
}
@@ -559,11 +569,12 @@
}
/**
- * @return whether this device is provisioned.
+ * @return whether this device is provisioned and the current user is set up.
*/
- private boolean isDeviceProvisioned() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+ private boolean isUserSetup() {
+ ContentResolver cr = mContext.getContentResolver();
+ return (Settings.Global.getInt(cr, Settings.Global.DEVICE_PROVISIONED, 0) != 0) &&
+ (Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 213018a..ddeb8dc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -76,8 +76,6 @@
ActivityOptions.OnAnimationFinishedListener {
private final static String TAG = "RecentsImpl";
- private final static boolean DEBUG = false;
-
// The minimum amount of time between each recents button press that we will handle
private final static int MIN_TOGGLE_DELAY_MS = 350;
// The duration within which the user releasing the alt tab (from when they pressed alt tab)
@@ -186,8 +184,6 @@
mContext = context;
mHandler = new Handler();
mAppWidgetHost = new RecentsAppWidgetHost(mContext, RecentsAppWidgetHost.HOST_ID);
- Resources res = mContext.getResources();
- LayoutInflater inflater = LayoutInflater.from(mContext);
// Initialize the static foreground thread
ForegroundThread.get();
@@ -198,14 +194,8 @@
ssp.registerTaskStackListener(mTaskStackListener);
// Initialize the static configuration resources
- mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- mNavBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
- mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
- mTaskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
- mDummyStackView = new TaskStackView(mContext, new TaskStack());
- mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
- null, false);
- reloadHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
+ reloadHeaderBarLayout();
+ updateHeaderBarLayout(true /* tryAndBindSearchWidget */, 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.
@@ -221,11 +211,12 @@
public void onBootCompleted() {
mBootCompleted = true;
- reloadHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
+ updateHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
}
- @Override
public void onConfigurationChanged() {
+ reloadHeaderBarLayout();
+ updateHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
// Don't reuse task stack views if the configuration changes
mCanReuseTaskStackViews = false;
Recents.getConfiguration().updateOnConfigurationChange();
@@ -257,7 +248,6 @@
}
}
- @Override
public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents,
boolean animate, boolean reloadTasks) {
mTriggeredFromAltTab = triggeredFromAltTab;
@@ -300,7 +290,6 @@
}
}
- @Override
public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
if (mBootCompleted) {
if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) {
@@ -321,7 +310,6 @@
}
}
- @Override
public void toggleRecents() {
// Skip this toggle if we are already waiting to trigger recents via alt-tab
if (mFastAltTabTrigger.isDozing()) {
@@ -375,7 +363,6 @@
}
}
- @Override
public void preloadRecents() {
// Preload only the raw task list into a new load plan (which will be consumed by the
// RecentsActivity) only if there is a task to animate to.
@@ -396,17 +383,14 @@
}
}
- @Override
public void cancelPreloadingRecents() {
// Do nothing
}
- @Override
public void onDraggingInRecents(float distanceFromTop) {
EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEvent(distanceFromTop));
}
- @Override
public void onDraggingInRecentsEnded(float velocity) {
EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEndedEvent(velocity));
}
@@ -547,14 +531,18 @@
showRelativeAffiliatedTask(false);
}
- public void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
+ public boolean dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
- if (topTask != null && !SystemServicesProxy.isHomeStack(topTask.stackId)) {
+ boolean screenPinningActive = ssp.isScreenPinningActive();
+ boolean isTopTaskHome = SystemServicesProxy.isHomeStack(topTask.stackId);
+ if (topTask != null && !isTopTaskHome && !screenPinningActive) {
ssp.moveTaskToDockedStack(topTask.id, stackCreateMode, initialBounds);
showRecents(false /* triggeredFromAltTab */, draggingInRecents, false /* animate */,
true /* reloadTasks*/);
+ return true;
}
+ return false;
}
/**
@@ -567,6 +555,26 @@
}
/**
+ * Reloads all the layouts for the header bar transition.
+ */
+ private void reloadHeaderBarLayout() {
+ Resources res = mContext.getResources();
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+
+ mStatusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ mNavBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height);
+ mNavBarWidth = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_width);
+ mTaskBarHeight = res.getDimensionPixelSize(
+ R.dimen.recents_task_bar_height);
+ mDummyStackView = new TaskStackView(mContext, new TaskStack());
+ mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
+ null, false);
+ }
+
+ /**
* Prepares the header bar layout for the next transition, if the task view bounds has changed
* since the last call, it will attempt to re-measure and layout the header bar to the new size.
*
@@ -574,7 +582,8 @@
* is not already bound (can be expensive)
* @param stack the stack to initialize the stack layout with
*/
- private void reloadHeaderBarLayout(boolean tryAndBindSearchWidget, TaskStack stack) {
+ private void updateHeaderBarLayout(boolean tryAndBindSearchWidget,
+ TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
SystemServicesProxy ssp = Recents.getSystemServices();
Rect windowRect = ssp.getWindowRect();
@@ -639,7 +648,7 @@
preloadIcon(topTask);
// Update the header bar if necessary
- reloadHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
+ updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
// Update the destination rect
mDummyStackView.updateLayoutForStack(stack);
@@ -825,7 +834,7 @@
TaskStack stack = sInstanceLoadPlan.getTaskStack();
// Update the header bar if necessary
- reloadHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
+ updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
// Prepare the dummy stack for the transition
mDummyStackView.updateLayoutForStack(stack);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index dfcf41bc..f9e825a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -60,6 +60,7 @@
import android.view.Display;
import android.view.IDockedStackListener;
import android.view.WindowManager;
+import android.view.WindowManager.KeyboardShortcutsReceiver;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.app.AssistUtils;
@@ -506,7 +507,7 @@
public void sendCloseSystemWindows(String reason) {
if (ActivityManagerNative.isSystemReady()) {
try {
- ActivityManagerNative.getDefault().closeSystemDialogs(reason);
+ mIam.closeSystemDialogs(reason);
} catch (RemoteException e) {
}
}
@@ -779,6 +780,19 @@
}
/**
+ * Returns whether the current task is in screen-pinning mode.
+ */
+ public boolean isScreenPinningActive() {
+ if (mIam == null) return false;
+
+ try {
+ return mIam.isInLockTaskMode();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
* Returns a global setting.
*/
public int getGlobalSetting(Context context, String setting) {
@@ -902,4 +916,8 @@
e.printStackTrace();
}
}
+
+ public void requestKeyboardShortcuts(Context context, KeyboardShortcutsReceiver receiver) {
+ mWm.requestAppKeyboardShortcuts(receiver);
+ }
}
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 086fb58..2bf2ccb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -88,15 +88,6 @@
}
/**
- * Cancels an animation.
- */
- public static void cancelAnimation(Animator animator) {
- if (animator != null) {
- animator.cancel();
- }
- }
-
- /**
* Cancels an animation ensuring that if it has listeners, onCancel and onEnd
* are not called.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index fce916b..890713e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -147,27 +147,11 @@
public TaskViewTransform getTransform(Task task, TaskViewTransform transformOut,
TaskStackLayoutAlgorithm stackLayout) {
if (mTaskRectMap.containsKey(task.key)) {
- final Rect taskRect = stackLayout.mTaskRect;
final RectF ffRect = mTaskRectMap.get(task.key);
transformOut.scale = 1f;
transformOut.alpha = 1f;
transformOut.translationZ = stackLayout.mMaxTranslationZ;
- if (task.thumbnail != null) {
- if (task.bounds == null) {
- // This is a stack task that has no freeform thumbnail, so keep the same bitmap
- // scale as it had in the stack
- transformOut.thumbnailScale = (float) taskRect.width() /
- task.thumbnail.getWidth();
- } else {
- // This is a freeform rect so fit the bitmap to the task bounds
- transformOut.thumbnailScale = Math.min(
- ffRect.width() / task.thumbnail.getWidth(),
- ffRect.height() / task.thumbnail.getHeight());
- }
- } else {
- transformOut.thumbnailScale = 1f;
- }
transformOut.rect.set(ffRect);
transformOut.rect.offset(stackLayout.mFreeformRect.left, stackLayout.mFreeformRect.top);
transformOut.visible = true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 51cae86..fdb0d32 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -289,7 +289,7 @@
// never happen)
specs.add(composeOffscreenAnimationSpec(t, offscreenTaskRect));
} else {
- layoutAlgorithm.getStackTransform(task, stackScroll, mTmpTransform, null);
+ layoutAlgorithm.getStackTransform(t, stackScroll, mTmpTransform, null);
specs.add(composeAnimationSpec(tv, mTmpTransform, true /* addHeaderBitmap */));
}
}
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 726e453..c2bb745 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -592,12 +592,8 @@
transformOut.reset();
return transformOut;
}
- getStackTransform(mTaskIndexMap.get(task.key), stackScroll, transformOut,
+ return getStackTransform(mTaskIndexMap.get(task.key), stackScroll, transformOut,
frontTransform);
- if (task.thumbnail != null) {
- transformOut.thumbnailScale = (float) mTaskRect.width() / task.thumbnail.getWidth();
- }
- return transformOut;
}
}
@@ -661,7 +657,6 @@
Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
transformOut.visible = (transformOut.rect.top < mStackRect.bottom) &&
(frontTransform == null || transformOut.rect.top != frontTransform.rect.top);
- transformOut.thumbnailScale = 1f;
transformOut.p = relP;
return transformOut;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index e8652f5..bc441b2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -200,8 +200,15 @@
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
- mHeaderView.onTaskViewSizeChanged(w, h);
- mThumbnailView.onTaskViewSizeChanged(w, h);
+ if (w > 0 && h > 0) {
+ mHeaderView.onTaskViewSizeChanged(w, h);
+ mThumbnailView.onTaskViewSizeChanged(w, h);
+ }
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
}
@Override
@@ -244,24 +251,17 @@
void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform,
TaskViewAnimation toAnimation, ValueAnimator.AnimatorUpdateListener updateCallback) {
RecentsConfiguration config = Recents.getConfiguration();
- Utilities.cancelAnimation(mTransformAnimation);
+ Utilities.cancelAnimationWithoutCallbacks(mTransformAnimation);
// Compose the animations for the transform
mTmpAnimators.clear();
- boolean requiresHwLayers = toTransform.applyToTaskView(this, mTmpAnimators, toAnimation,
- !config.fakeShadows);
+ toTransform.applyToTaskView(this, mTmpAnimators, toAnimation, !config.fakeShadows);
if (toAnimation.isImmediate()) {
- mThumbnailView.setBitmapScale(toTransform.thumbnailScale);
setTaskProgress(toTransform.p);
if (toAnimation.listener != null) {
toAnimation.listener.onAnimationEnd(null);
}
} else {
- if (Float.compare(mThumbnailView.getBitmapScale(), toTransform.thumbnailScale) != 0) {
- mTmpAnimators.add(ObjectAnimator.ofFloat(mThumbnailView,
- TaskViewThumbnail.BITMAP_SCALE, mThumbnailView.getBitmapScale(),
- toTransform.thumbnailScale));
- }
if (Float.compare(getTaskProgress(), toTransform.p) != 0) {
mTmpAnimators.add(ObjectAnimator.ofFloat(this, TASK_PROGRESS, getTaskProgress(),
toTransform.p));
@@ -272,22 +272,13 @@
// Create the animator
mTransformAnimation = toAnimation.createAnimator(mTmpAnimators);
- if (requiresHwLayers) {
- setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mTransformAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- setLayerType(View.LAYER_TYPE_NONE, null);
- }
- });
- }
mTransformAnimation.start();
}
}
/** Resets this view's properties */
void resetViewProperties() {
- Utilities.cancelAnimation(mTransformAnimation);
+ Utilities.cancelAnimationWithoutCallbacks(mTransformAnimation);
setDim(0);
setVisibility(View.VISIBLE);
getViewBounds().reset();
@@ -303,7 +294,7 @@
* Cancels any current transform animations.
*/
public void cancelTransformAnimation() {
- Utilities.cancelAnimation(mTransformAnimation);
+ Utilities.cancelAnimationWithoutCallbacks(mTransformAnimation);
}
/** Enables/disables handling touch on this task view. */
@@ -389,7 +380,7 @@
} else {
float dimAlpha = mDimAlpha / 255.0f;
mThumbnailView.setDimAlpha(dimAlpha);
- mHeaderView.setDimAlpha(dim);
+ mHeaderView.setDimAlpha(dimAlpha);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index e8b7574..6a47424 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -16,18 +16,18 @@
package com.android.systemui.recents.views;
+import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.ColorStateList;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.ColorFilter;
import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
+import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AnimationUtils;
@@ -36,6 +36,7 @@
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
@@ -55,6 +56,66 @@
public class TaskViewHeader extends FrameLayout
implements View.OnClickListener, View.OnLongClickListener {
+ private static final float HIGHLIGHT_LIGHTNESS_INCREMENT = 0.125f;
+
+ /**
+ * A color drawable that draws a slight highlight at the top to help it stand out.
+ */
+ private class HighlightColorDrawable extends Drawable {
+
+ private Paint mHighlightPaint = new Paint();
+ private Paint mBackgroundPaint = new Paint();
+
+ private float[] mTmpHSL = new float[3];
+
+ public HighlightColorDrawable() {
+ mBackgroundPaint.setColor(Color.argb(255, 0, 0, 0));
+ mBackgroundPaint.setAntiAlias(true);
+ mHighlightPaint.setColor(Color.argb(255, 255, 255, 255));
+ mHighlightPaint.setAntiAlias(true);
+ }
+
+ public void setColorAndDim(int color, float dimAlpha) {
+ mBackgroundPaint.setColor(color);
+
+ ColorUtils.colorToHSL(color, mTmpHSL);
+ // TODO: Consider using the saturation of the color to adjust the lightness as well
+ mTmpHSL[2] = Math.min(1f,
+ mTmpHSL[2] + HIGHLIGHT_LIGHTNESS_INCREMENT * (1.0f - dimAlpha));
+ mHighlightPaint.setColor(ColorUtils.HSLToColor(mTmpHSL));
+
+ invalidateSelf();
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+ // Do nothing
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // Do nothing
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ // Draw the highlight at the top edge (but put the bottom edge just out of view)
+ canvas.drawRoundRect(0, 0, mTaskViewRect.width(),
+ 2 * Math.max(mHighlightHeight, mCornerRadius),
+ mCornerRadius, mCornerRadius, mHighlightPaint);
+
+ // Draw the background with the rounded corners
+ canvas.drawRoundRect(0, mHighlightHeight, mTaskViewRect.width(),
+ getHeight() + mCornerRadius,
+ mCornerRadius, mCornerRadius, mBackgroundPaint);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.OPAQUE;
+ }
+ }
+
Task mTask;
// Header views
@@ -68,17 +129,18 @@
Rect mTaskViewRect = new Rect();
int mCornerRadius;
int mHighlightHeight;
+ float mDimAlpha;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
- RippleDrawable mBackground;
- GradientDrawable mBackgroundColorDrawable;
+ int mTaskBarViewLightTextColor;
+ int mTaskBarViewDarkTextColor;
String mDismissContentDescription;
- // Static highlight that we draw at the top of each view
- static Paint sHighlightPaint;
+ // Header background
+ private HighlightColorDrawable mBackground;
// Header dim, which is only used when task view hardware layers are not used
- Paint mDimLayerPaint = new Paint();
+ private Paint mDimLayerPaint = new Paint();
Interpolator mFastOutSlowInInterpolator;
Interpolator mFastOutLinearInInterpolator;
@@ -100,29 +162,26 @@
setWillNotDraw(false);
// Load the dismiss resources
- mDimLayerPaint.setColor(Color.argb(0, 0, 0, 0));
+ Resources res = context.getResources();
mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
- mDismissContentDescription =
- context.getString(R.string.accessibility_recents_item_will_be_dismissed);
- mCornerRadius = getResources().getDimensionPixelSize(
- R.dimen.recents_task_view_rounded_corners_radius);
- mHighlightHeight = getResources().getDimensionPixelSize(
- R.dimen.recents_task_view_highlight);
+ mDismissContentDescription = context.getString(
+ R.string.accessibility_recents_item_will_be_dismissed);
+ mCornerRadius = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
+ mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
+ mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
+ mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
- // Configure the highlight paint
- if (sHighlightPaint == null) {
- sHighlightPaint = new Paint();
- sHighlightPaint.setStyle(Paint.Style.STROKE);
- sHighlightPaint.setStrokeWidth(mHighlightHeight);
- sHighlightPaint.setColor(context.getColor(R.color.recents_task_bar_highlight_color));
- sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
- sHighlightPaint.setAntiAlias(true);
- }
+ // Configure the background and dim
+ mBackground = new HighlightColorDrawable();
+ mBackground.setColorAndDim(Color.argb(255, 0, 0, 0), 0f);
+ setBackground(mBackground);
+ mDimLayerPaint.setColor(Color.argb(255, 0, 0, 0));
+ mDimLayerPaint.setAntiAlias(true);
}
@Override
@@ -139,16 +198,6 @@
if (mIconView.getBackground() instanceof RippleDrawable) {
mIconView.setBackground(null);
}
-
- mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(
- R.drawable.recents_task_view_header_bg_color);
- // Copy the ripple drawable since we are going to be manipulating it
- mBackground = (RippleDrawable)
- getContext().getDrawable(R.drawable.recents_task_view_header_bg);
- mBackground = (RippleDrawable) mBackground.mutate().getConstantState().newDrawable();
- mBackground.setColor(ColorStateList.valueOf(0));
- mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColorDrawable);
- setBackground(mBackground);
}
/**
@@ -156,6 +205,11 @@
* to match the frame changes.
*/
public void onTaskViewSizeChanged(int width, int height) {
+ // Return early if the bounds have not changed
+ if (mTaskViewRect.width() == width && mTaskViewRect.height() == height) {
+ return;
+ }
+
mTaskViewRect.set(0, 0, width, height);
boolean updateMoveTaskButton = mMoveTaskButton.getVisibility() != View.GONE;
int appIconWidth = mIconView.getMeasuredWidth();
@@ -201,31 +255,39 @@
}
@Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- onTaskViewSizeChanged(mTaskViewRect.width(), mTaskViewRect.height());
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || (who == mBackground);
}
@Override
- protected void onDraw(Canvas canvas) {
- // Draw the highlight at the top edge (but put the bottom edge just out of view)
- float offset = (float) Math.ceil(mHighlightHeight / 2f);
- float radius = mCornerRadius;
- int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipRect(0, 0, mTaskViewRect.width(), getMeasuredHeight());
- canvas.drawRoundRect(-offset, 0f, (float) mTaskViewRect.width() + offset,
- getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
- canvas.restoreToCount(count);
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+
+ // Draw the dim layer with the rounded corners
+ canvas.drawRoundRect(0, 0, mTaskViewRect.width(), getHeight() + mCornerRadius,
+ mCornerRadius, mCornerRadius, mDimLayerPaint);
}
/**
* Sets the dim alpha, only used when we are not using hardware layers.
* (see RecentsConfiguration.useHardwareLayers)
*/
- void setDimAlpha(int alpha) {
- mDimLayerPaint.setColor(Color.argb(alpha, 0, 0, 0));
+ void setDimAlpha(float dimAlpha) {
+ mDimAlpha = dimAlpha;
+ updateBackgroundColor(dimAlpha);
invalidate();
}
+ /**
+ * Updates the background and highlight colors for this header.
+ */
+ private void updateBackgroundColor(float dimAlpha) {
+ if (mTask != null) {
+ mBackground.setColorAndDim(mTask.colorPrimary, dimAlpha);
+ mDimLayerPaint.setAlpha((int) (dimAlpha * 255));
+ }
+ }
+
/** Binds the bar view to the task */
public void rebindToTask(Task t) {
SystemServicesProxy ssp = Recents.getSystemServices();
@@ -233,6 +295,7 @@
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
+ updateBackgroundColor(mDimAlpha);
if (t.icon != null) {
mIconView.setImageDrawable(t.icon);
}
@@ -240,20 +303,8 @@
mTitleView.setText(t.title);
}
mTitleView.setContentDescription(t.contentDescription);
-
- // Try and apply the system ui tint
- int existingBgColor = (getBackground() instanceof ColorDrawable) ?
- ((ColorDrawable) getBackground()).getColor() : 0;
- if (existingBgColor != t.colorPrimary) {
- mBackgroundColorDrawable.setColor(t.colorPrimary);
- }
-
- int taskBarViewLightTextColor = getResources().getColor(
- R.color.recents_task_bar_light_text_color);
- int taskBarViewDarkTextColor = getResources().getColor(
- R.color.recents_task_bar_dark_text_color);
mTitleView.setTextColor(t.useLightOnPrimaryColor ?
- taskBarViewLightTextColor : taskBarViewDarkTextColor);
+ mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
mLightDismissDrawable : mDarkDismissDrawable);
mDismissButton.setContentDescription(String.format(mDismissContentDescription,
@@ -273,7 +324,9 @@
? R.drawable.recents_move_task_freeform_light
: R.drawable.recents_move_task_freeform_dark);
}
- mMoveTaskButton.setVisibility(View.VISIBLE);
+ if (mMoveTaskButton.getVisibility() != View.VISIBLE) {
+ mMoveTaskButton.setVisibility(View.VISIBLE);
+ }
mMoveTaskButton.setOnClickListener(this);
}
@@ -329,15 +382,6 @@
}
@Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
-
- // Draw the dim layer with the rounded corners
- canvas.drawRoundRect(0, 0, mTaskViewRect.width(), getHeight(),
- mCornerRadius, mCornerRadius, mDimLayerPaint);
- }
-
- @Override
public void onClick(View v) {
if (v == mIconView) {
// In accessibility, a single click on the focused app info button will show it
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 8edfae0..39d0604 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -42,26 +42,15 @@
*/
public class TaskViewThumbnail extends View {
- public static final Property<TaskViewThumbnail, Float> BITMAP_SCALE =
- new FloatProperty<TaskViewThumbnail>("bitmapScale") {
- @Override
- public void setValue(TaskViewThumbnail object, float scale) {
- object.setBitmapScale(scale);
- }
-
- @Override
- public Float get(TaskViewThumbnail object) {
- return object.getBitmapScale();
- }
- };
+ private Task mTask;
// Drawing
+ Rect mThumbnailRect = new Rect();
Rect mTaskViewRect = new Rect();
int mCornerRadius;
float mDimAlpha;
Matrix mScaleMatrix = new Matrix();
Paint mDrawPaint = new Paint();
- float mBitmapScale = 1f;
BitmapShader mBitmapShader;
LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
@@ -104,7 +93,13 @@
* to match the frame changes.
*/
public void onTaskViewSizeChanged(int width, int height) {
+ // Return early if the bounds have not changed
+ if (mTaskViewRect.width() == width && mTaskViewRect.height() == height) {
+ return;
+ }
+
mTaskViewRect.set(0, 0, width, height);
+ updateThumbnailScale();
invalidate();
}
@@ -125,9 +120,12 @@
mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
mDrawPaint.setShader(mBitmapShader);
+ mThumbnailRect.set(0, 0, bm.getWidth(), bm.getHeight());
+ updateThumbnailScale();
} else {
mBitmapShader = null;
mDrawPaint.setShader(null);
+ mThumbnailRect.setEmpty();
}
invalidate();
}
@@ -151,12 +149,23 @@
}
/**
- * Sets the scale of the bitmap relative to this view.
+ * Updates the scale of the bitmap relative to this view.
*/
- public void setBitmapScale(float scale) {
+ public void updateThumbnailScale() {
if (mBitmapShader != null) {
- mBitmapScale = scale;
- mScaleMatrix.setScale(mBitmapScale, mBitmapScale);
+ float thumbnailScale;
+ if (!mTask.isFreeformTask() || mTask.bounds == null) {
+ // If this is a stack task, or a stack task moved into the freeform workspace, then
+ // just scale this thumbnail to fit the width of the view
+ thumbnailScale = (float) mTaskViewRect.width() / mThumbnailRect.width();
+ } else {
+ // Otherwise, if this is a freeform task with task bounds, then scale the thumbnail
+ // to fit the entire bitmap into the task bounds
+ thumbnailScale = Math.min(
+ (float) mTaskViewRect.width() / mThumbnailRect.width(),
+ (float) mTaskViewRect.height() / mThumbnailRect.height());
+ }
+ mScaleMatrix.setScale(thumbnailScale, thumbnailScale);
mBitmapShader.setLocalMatrix(mScaleMatrix);
}
if (!mInvisible) {
@@ -164,10 +173,6 @@
}
}
- public float getBitmapScale() {
- return mBitmapScale;
- }
-
/** Updates the clip rect based on the given task bar. */
void updateClipToTaskBar(View taskBar) {
mTaskBar = taskBar;
@@ -200,6 +205,7 @@
/** Binds the thumbnail view to the task */
void rebindToTask(Task t) {
+ mTask = t;
if (t.thumbnail != null) {
setThumbnail(t.thumbnail);
} else {
@@ -209,6 +215,7 @@
/** Unbinds the thumbnail view from the task */
void unbindFromTask() {
+ mTask = null;
setThumbnail(null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 14bab64..538c248 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -86,7 +86,6 @@
public float translationZ = 0;
public float scale = 1f;
public float alpha = 1f;
- public float thumbnailScale = 1f;
public boolean visible = false;
float p = 0f;
@@ -101,7 +100,6 @@
translationZ = 0;
scale = 1f;
alpha = 1f;
- thumbnailScale = 1f;
visible = false;
rect.setEmpty();
p = 0f;
@@ -127,15 +125,12 @@
/**
* Applies this transform to a view.
- *
- * @return whether hardware layers are required for this animation.
*/
- public boolean applyToTaskView(TaskView v, ArrayList<Animator> animators,
+ public void applyToTaskView(TaskView v, ArrayList<Animator> animators,
TaskViewAnimation taskAnimation, boolean allowShadows) {
// Return early if not visible
- boolean requiresHwLayers = false;
if (!visible) {
- return requiresHwLayers;
+ return;
}
if (taskAnimation.isImmediate()) {
@@ -165,7 +160,6 @@
}
if (hasAlphaChangedFrom(v.getAlpha())) {
animators.add(ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha));
- requiresHwLayers = true;
}
if (hasRectChangedFrom(v)) {
animators.add(ObjectAnimator.ofPropertyValuesHolder(v,
@@ -175,7 +169,6 @@
PropertyValuesHolder.ofInt(BOTTOM, v.getBottom(), (int) rect.bottom)));
}
}
- return requiresHwLayers;
}
/** Reset the transform on a view. */
@@ -188,6 +181,5 @@
v.setAlpha(1f);
v.getViewBounds().setClipBottom(0);
v.setLeftTopRightBottom(0, 0, 0, 0);
- v.mThumbnailView.setBitmapScale(1f);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 109cf47..824d10a 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -28,7 +28,6 @@
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
import android.util.AttributeSet;
-import android.util.MathUtils;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.MotionEvent;
@@ -39,7 +38,6 @@
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver.InternalInsetsInfo;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
-import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
@@ -48,8 +46,10 @@
import android.widget.FrameLayout;
import android.widget.ImageButton;
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.R;
-import com.android.systemui.stackdivider.DividerSnapAlgorithm.SnapTarget;
+import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.systemui.statusbar.FlingAnimationUtils;
import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
@@ -167,7 +167,8 @@
public boolean startDragging(boolean animate) {
mHandle.setTouching(true, animate);
mDockSide = mWindowManagerProxy.getDockSide();
- mSnapAlgorithm = new DividerSnapAlgorithm(getContext(), mFlingAnimationUtils, mDisplayWidth,
+ mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(),
+ mFlingAnimationUtils.getMinVelocityPxPerSecond(), mDisplayWidth,
mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets);
if (mDockSide != WindowManager.DOCKED_INVALID) {
mWindowManagerProxy.setResizing(true);
@@ -362,36 +363,6 @@
return mStartPosition + touchY - mStartY;
}
- public void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
- outRect.set(0, 0, mDisplayWidth, mDisplayHeight);
- switch (dockSide) {
- case WindowManager.DOCKED_LEFT:
- outRect.right = position;
- break;
- case WindowManager.DOCKED_TOP:
- outRect.bottom = position;
- break;
- case WindowManager.DOCKED_RIGHT:
- outRect.left = position + mDividerWindowWidth - 2 * mDividerInsets;
- break;
- case WindowManager.DOCKED_BOTTOM:
- outRect.top = position + mDividerWindowWidth - 2 * mDividerInsets;
- break;
- }
- if (outRect.left > outRect.right) {
- outRect.left = outRect.right;
- }
- if (outRect.top > outRect.bottom) {
- outRect.top = outRect.bottom;
- }
- if (outRect.right < outRect.left) {
- outRect.right = outRect.left;
- }
- if (outRect.bottom < outRect.top) {
- outRect.bottom = outRect.top;
- }
- }
-
private int invertDockSide(int dockSide) {
switch (dockSide) {
case WindowManager.DOCKED_LEFT:
@@ -421,6 +392,11 @@
containingRect.right, containingRect.bottom);
}
+ public void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
+ DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect, mDisplayWidth,
+ mDisplayHeight, mDividerSize);
+ }
+
public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
calculateBoundsForPosition(position, mDockSide, mDockedRect);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 3e0ea90..b36fb7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -20,50 +20,92 @@
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
-import android.view.Gravity;
+import android.os.Handler;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
+import android.view.KeyboardShortcutInfo;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.view.WindowManager.KeyboardShortcutsReceiver;
import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
+
+import java.util.List;
+
+import static android.content.Context.LAYOUT_INFLATER_SERVICE;
+import static android.graphics.Color.TRANSPARENT;
+import static android.view.Gravity.TOP;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
/**
* Contains functionality for handling keyboard shortcuts.
*/
public class KeyboardShortcuts {
+ private static final String TAG = "KeyboardShortcuts";
+
private Dialog mKeyboardShortcutsDialog;
public KeyboardShortcuts() {}
- public void toggleKeyboardShortcuts(Context context) {
+ public void toggleKeyboardShortcuts(final Context context) {
if (mKeyboardShortcutsDialog == null) {
- // Create dialog.
- AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- final View keyboardShortcutsView = inflater.inflate(
- R.layout.keyboard_shortcuts_view, null);
-
- populateKeyboardShortcuts(keyboardShortcutsView.findViewById(
- R.id.keyboard_shortcuts_wrapper));
- dialogBuilder.setView(keyboardShortcutsView);
- mKeyboardShortcutsDialog = dialogBuilder.create();
- mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
-
- // Setup window.
- Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
- keyboardShortcutsWindow.setType(
- WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
- keyboardShortcutsWindow.setBackgroundDrawable(
- new ColorDrawable(android.graphics.Color.TRANSPARENT));
- keyboardShortcutsWindow.setGravity(Gravity.TOP);
- mKeyboardShortcutsDialog.show();
+ Recents.getSystemServices().requestKeyboardShortcuts(context,
+ new KeyboardShortcutsReceiver() {
+ @Override
+ public void onKeyboardShortcutsReceived(
+ final List<KeyboardShortcutGroup> result) {
+ KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
+ context.getString(R.string.keyboard_shortcut_group_system));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ context.getString(R.string.keyboard_shortcut_group_system_home),
+ '\u2386', KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ context.getString(R.string.keyboard_shortcut_group_system_back),
+ '\u007F', KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ context.getString(R.string.keyboard_shortcut_group_system_recents),
+ '\u0009', KeyEvent.META_ALT_ON));
+ result.add(systemGroup);
+ Log.i(TAG, "Keyboard shortcuts received: " + String.valueOf(result));
+ showKeyboardShortcutsDialog(context);
+ }
+ });
} else {
dismissKeyboardShortcutsDialog();
}
}
+ private void showKeyboardShortcutsDialog(Context context) {
+ // Create dialog.
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(
+ LAYOUT_INFLATER_SERVICE);
+ final View keyboardShortcutsView = inflater.inflate(
+ R.layout.keyboard_shortcuts_view, null);
+
+ populateKeyboardShortcuts(keyboardShortcutsView.findViewById(
+ R.id.keyboard_shortcuts_wrapper));
+ dialogBuilder.setView(keyboardShortcutsView);
+ mKeyboardShortcutsDialog = dialogBuilder.create();
+ mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
+
+ // Setup window.
+ Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
+ keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
+ keyboardShortcutsWindow.setBackgroundDrawable(
+ new ColorDrawable(TRANSPARENT));
+ keyboardShortcutsWindow.setGravity(TOP);
+ keyboardShortcutsView.post(new Runnable() {
+ public void run() {
+ mKeyboardShortcutsDialog.show();
+ }
+ });
+ }
+
public void dismissKeyboardShortcutsDialog() {
if (mKeyboardShortcutsDialog != null) {
mKeyboardShortcutsDialog.dismiss();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index b93fc76..f41e47b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -166,7 +166,7 @@
}
@Override
- public void onPowerSaveChanged() {
+ public void onPowerSaveChanged(boolean isPowerSave) {
// could not care less
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index cc85d0f..e5b4f4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -29,8 +29,7 @@
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.stackdivider.DividerSnapAlgorithm.SnapTarget;
-import com.android.systemui.stackdivider.DividerView;
+import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.systemui.tuner.TunerService;
import static android.view.WindowManager.*;
@@ -166,16 +165,19 @@
int y = (int) event.getY();
int xDiff = Math.abs(x - mTouchDownX);
int yDiff = Math.abs(y - mTouchDownY);
+ if (mDivider == null || mRecentsComponent == null) {
+ return false;
+ }
if (!mDockWindowTouchSlopExceeded) {
boolean touchSlopExceeded = !mIsVertical
? yDiff > mScrollTouchSlop && yDiff > xDiff
: xDiff > mScrollTouchSlop && xDiff > yDiff;
if (touchSlopExceeded && mDivider.getView().getWindowManagerProxy().getDockSide()
== DOCKED_INVALID) {
- mDragMode = calculateDragMode();
Rect initialBounds = null;
+ int dragMode = calculateDragMode();
int createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
- if (mDragMode == DRAG_MODE_DIVIDER) {
+ if (dragMode == DRAG_MODE_DIVIDER) {
initialBounds = new Rect();
mDivider.getView().calculateBoundsForPosition(mIsVertical
? (int) event.getRawX()
@@ -184,19 +186,23 @@
? DOCKED_TOP
: DOCKED_LEFT,
initialBounds);
- } else if (mDragMode == DRAG_MODE_RECENTS && mTouchDownX
+ } else if (dragMode == DRAG_MODE_RECENTS && mTouchDownX
< mContext.getResources().getDisplayMetrics().widthPixels / 2) {
createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
}
- mRecentsComponent.dockTopTask(mDragMode == DRAG_MODE_RECENTS, createMode,
- initialBounds);
- if (mDragMode == DRAG_MODE_DIVIDER) {
- mDivider.getView().startDragging(false /* animate */);
+ boolean docked = mRecentsComponent.dockTopTask(dragMode == DRAG_MODE_RECENTS,
+ createMode, initialBounds);
+ if (docked) {
+ mDragMode = dragMode;
+ if (mDragMode == DRAG_MODE_DIVIDER) {
+ mDivider.getView().startDragging(false /* animate */);
+ }
+ mDockWindowTouchSlopExceeded = true;
+ MetricsLogger.action(mContext,
+ MetricsLogger.ACTION_WINDOW_DOCK_SWIPE);
+
+ return true;
}
- mDockWindowTouchSlopExceeded = true;
- MetricsLogger.action(mContext,
- MetricsLogger.ACTION_WINDOW_DOCK_SWIPE);
- return true;
}
} else {
if (mDragMode == DRAG_MODE_DIVIDER) {
@@ -214,7 +220,7 @@
private void handleDragActionUpEvent(MotionEvent event) {
mVelocityTracker.addMovement(event);
mVelocityTracker.computeCurrentVelocity(1000);
- if (mDockWindowTouchSlopExceeded) {
+ if (mDockWindowTouchSlopExceeded && mDivider != null && mRecentsComponent != null) {
if (mDragMode == DRAG_MODE_DIVIDER) {
mDivider.getView().stopDragging(mIsVertical
? (int) event.getRawX()
@@ -254,7 +260,7 @@
float absVelY = Math.abs(velocityY);
boolean isValidFling = absVelX > mMinFlingVelocity &&
mIsVertical ? (absVelY > absVelX) : (absVelX > absVelY);
- if (isValidFling) {
+ if (isValidFling && mRecentsComponent != null) {
boolean showNext;
if (!mIsRTL) {
showNext = mIsVertical ? (velocityY < 0) : (velocityX < 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 6aa072f..f2c57e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -23,8 +23,6 @@
import android.view.View;
import android.widget.FrameLayout;
-import java.util.ArrayList;
-
public abstract class PanelBar extends FrameLayout {
public static final boolean DEBUG = false;
public static final String TAG = PanelBar.class.getSimpleName();
@@ -39,14 +37,10 @@
public static final int STATE_OPENING = 1;
public static final int STATE_OPEN = 2;
- PanelHolder mPanelHolder;
- ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
- PanelView mTouchingPanel;
+ PanelView mPanel;
private int mState = STATE_CLOSED;
private boolean mTracking;
- float mPanelExpandedFractionSum;
-
public void go(int state) {
if (DEBUG) LOG("go state: %d -> %d", mState, state);
mState = state;
@@ -61,54 +55,28 @@
super.onFinishInflate();
}
- public void addPanel(PanelView pv) {
- mPanels.add(pv);
+ public void setPanel(PanelView pv) {
+ mPanel = pv;
pv.setBar(this);
}
- public void setPanelHolder(PanelHolder ph) {
- if (ph == null) {
- Log.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
- return;
- }
- mPanelHolder = ph;
- final int N = ph.getChildCount();
- for (int i=0; i<N; i++) {
- final View v = ph.getChildAt(i);
- if (v != null && v instanceof PanelView) {
- addPanel((PanelView) v);
- }
- }
- }
-
public void setBouncerShowing(boolean showing) {
int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: IMPORTANT_FOR_ACCESSIBILITY_AUTO;
setImportantForAccessibility(important);
- if (mPanelHolder != null) {
- mPanelHolder.setImportantForAccessibility(important);
- }
+ if (mPanel != null) mPanel.setImportantForAccessibility(important);
}
- public float getBarHeight() {
- return getMeasuredHeight();
- }
-
- public PanelView selectPanelForTouch(MotionEvent touch) {
- final int N = mPanels.size();
- return mPanels.get((int)(N * touch.getX() / getMeasuredWidth()));
- }
-
- public boolean panelsEnabled() {
+ public boolean panelEnabled() {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Allow subclasses to implement enable/disable semantics
- if (!panelsEnabled()) {
+ if (!panelEnabled()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
(int) event.getX(), (int) event.getY()));
@@ -116,14 +84,12 @@
return false;
}
- // figure out which panel needs to be talked to here
if (event.getAction() == MotionEvent.ACTION_DOWN) {
- final PanelView panel = selectPanelForTouch(event);
+ final PanelView panel = mPanel;
if (panel == null) {
// panel is not there, so we'll eat the gesture
Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
(int) event.getX(), (int) event.getY()));
- mTouchingPanel = null;
return true;
}
boolean enabled = panel.isEnabled();
@@ -134,90 +100,65 @@
Log.v(TAG, String.format(
"onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",
panel, (int) event.getX(), (int) event.getY()));
- mTouchingPanel = null;
return true;
}
- startOpeningPanel(panel);
}
- final boolean result = mTouchingPanel != null
- ? mTouchingPanel.onTouchEvent(event)
- : true;
- return result;
- }
-
- // called from PanelView when self-expanding, too
- public void startOpeningPanel(PanelView panel) {
- if (DEBUG) LOG("startOpeningPanel: " + panel);
- mTouchingPanel = panel;
- mPanelHolder.setSelectedPanel(mTouchingPanel);
- for (PanelView pv : mPanels) {
- if (pv != panel) {
- pv.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
- }
- }
+ return mPanel == null || mPanel.onTouchEvent(event);
}
public abstract void panelScrimMinFractionChanged(float minFraction);
/**
- * @param panel the panel which changed its expansion state
* @param frac the fraction from the expansion in [0, 1]
* @param expanded whether the panel is currently expanded; this is independent from the
* fraction as the panel also might be expanded if the fraction is 0
*/
- public void panelExpansionChanged(PanelView panel, float frac, boolean expanded) {
+ public void panelExpansionChanged(float frac, boolean expanded) {
boolean fullyClosed = true;
- PanelView fullyOpenedPanel = null;
- if (SPEW) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
- mPanelExpandedFractionSum = 0f;
- for (PanelView pv : mPanels) {
- pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
- // adjust any other panels that may be partially visible
- if (expanded) {
- if (mState == STATE_CLOSED) {
- go(STATE_OPENING);
- onPanelPeeked();
- }
- fullyClosed = false;
- final float thisFrac = pv.getExpandedFraction();
- mPanelExpandedFractionSum += thisFrac;
- if (SPEW) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac);
- if (panel == pv) {
- if (thisFrac == 1f) fullyOpenedPanel = panel;
- }
+ boolean fullyOpened = false;
+ if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
+ PanelView pv = mPanel;
+ pv.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
+ // adjust any other panels that may be partially visible
+ if (expanded) {
+ if (mState == STATE_CLOSED) {
+ go(STATE_OPENING);
+ onPanelPeeked();
}
+ fullyClosed = false;
+ final float thisFrac = pv.getExpandedFraction();
+ if (SPEW) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac);
+ fullyOpened = thisFrac >= 1f;
}
- mPanelExpandedFractionSum /= mPanels.size();
- if (fullyOpenedPanel != null && !mTracking) {
+ if (fullyOpened && !mTracking) {
go(STATE_OPEN);
- onPanelFullyOpened(fullyOpenedPanel);
+ onPanelFullyOpened();
} else if (fullyClosed && !mTracking && mState != STATE_CLOSED) {
go(STATE_CLOSED);
- onAllPanelsCollapsed();
+ onPanelCollapsed();
}
if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState,
- (fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
+ fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
}
- public void collapseAllPanels(boolean animate, boolean delayed, float speedUpFactor) {
+ public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
boolean waiting = false;
- for (PanelView pv : mPanels) {
- if (animate && !pv.isFullyCollapsed()) {
- pv.collapse(delayed, speedUpFactor);
- waiting = true;
- } else {
- pv.resetViews();
- pv.setExpandedFraction(0); // just in case
- pv.cancelPeek();
- }
+ PanelView pv = mPanel;
+ if (animate && !pv.isFullyCollapsed()) {
+ pv.collapse(delayed, speedUpFactor);
+ waiting = true;
+ } else {
+ pv.resetViews();
+ pv.setExpandedFraction(0); // just in case
+ pv.cancelPeek();
}
- if (DEBUG) LOG("collapseAllPanels: animate=%s waiting=%s", animate, waiting);
+ if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);
if (!waiting && mState != STATE_CLOSED) {
// it's possible that nothing animated, so we replicate the termination
// conditions of panelExpansionChanged here
go(STATE_CLOSED);
- onAllPanelsCollapsed();
+ onPanelCollapsed();
}
}
@@ -225,19 +166,19 @@
if (DEBUG) LOG("onPanelPeeked");
}
- public void onAllPanelsCollapsed() {
- if (DEBUG) LOG("onAllPanelsCollapsed");
+ public void onPanelCollapsed() {
+ if (DEBUG) LOG("onPanelCollapsed");
}
- public void onPanelFullyOpened(PanelView openPanel) {
+ public void onPanelFullyOpened() {
if (DEBUG) LOG("onPanelFullyOpened");
}
- public void onTrackingStarted(PanelView panel) {
+ public void onTrackingStarted() {
mTracking = true;
}
- public void onTrackingStopped(PanelView panel, boolean expand) {
+ public void onTrackingStopped(boolean expand) {
mTracking = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java
deleted file mode 100644
index 5095ebb..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.EventLog;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-import com.android.systemui.EventLogTags;
-
-public class PanelHolder extends FrameLayout {
- public static final boolean DEBUG_GESTURES = true;
-
- private int mSelectedPanelIndex = -1;
-
- public PanelHolder(Context context, AttributeSet attrs) {
- super(context, attrs);
- setChildrenDrawingOrderEnabled(true);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- setChildrenDrawingOrderEnabled(true);
- }
-
- public int getPanelIndex(PanelView pv) {
- final int N = getChildCount();
- for (int i=0; i<N; i++) {
- final PanelView v = (PanelView) getChildAt(i);
- if (pv == v) return i;
- }
- return -1;
- }
-
- public void setSelectedPanel(PanelView pv) {
- mSelectedPanelIndex = getPanelIndex(pv);
- }
-
- @Override
- protected int getChildDrawingOrder(int childCount, int i) {
- if (mSelectedPanelIndex == -1) {
- return i;
- } else {
- if (i == childCount - 1) {
- return mSelectedPanelIndex;
- } else if (i >= mSelectedPanelIndex) {
- return i + 1;
- } else {
- return i;
- }
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (DEBUG_GESTURES) {
- if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
- EventLog.writeEvent(EventLogTags.SYSUI_PANELHOLDER_TOUCH,
- event.getActionMasked(), (int) event.getX(), (int) event.getY());
- }
- }
- return false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 7b2498f..aa01bf2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -432,7 +432,7 @@
protected void onTrackingStopped(boolean expand) {
mTracking = false;
- mBar.onTrackingStopped(PanelView.this, expand);
+ mBar.onTrackingStopped(expand);
notifyBarPanelExpansionChanged();
}
@@ -440,7 +440,7 @@
endClosing();
mTracking = true;
mCollapseAfterPeek = false;
- mBar.onTrackingStarted(PanelView.this);
+ mBar.onTrackingStarted();
notifyExpandingStarted();
notifyBarPanelExpansionChanged();
}
@@ -893,7 +893,6 @@
!= mStatusBar.getStatusBarHeight()) {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
if (animate) {
- mBar.startOpeningPanel(PanelView.this);
notifyExpandingStarted();
fling(0, true /* expand */);
} else {
@@ -1025,7 +1024,7 @@
}
protected void notifyBarPanelExpansionChanged() {
- mBar.panelExpansionChanged(this, mExpandedFraction, mExpandedFraction > 0f || mPeekPending
+ mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f || mPeekPending
|| mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp()
|| mTracking || mHeightAnimator != null);
}
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 d721a77..50e88d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -81,7 +81,6 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ThreadedRenderer;
-import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewStub;
@@ -342,7 +341,6 @@
// Tracking finger for opening/closing.
boolean mTracking;
- VelocityTracker mVelocityTracker;
int[] mAbsPos = new int[2];
ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
@@ -692,16 +690,14 @@
}
});
- mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
- mStatusBarView.setBar(this);
-
- PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
- mStatusBarView.setPanelHolder(holder);
-
mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
+ mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
+ mStatusBarView.setBar(this);
+ mStatusBarView.setPanel(mNotificationPanel);
+
if (!ActivityManager.isHighEndGfx()) {
mStatusBarWindow.setBackground(null);
mNotificationPanel.setBackground(new FastColorDrawable(context.getColor(
@@ -814,10 +810,10 @@
mBatteryController = new BatteryController(mContext);
mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
@Override
- public void onPowerSaveChanged() {
+ public void onPowerSaveChanged(boolean isPowerSave) {
mHandler.post(mCheckBarModes);
if (mDozeServiceHost != null) {
- mDozeServiceHost.firePowerSaveChanged(mBatteryController.isPowerSave());
+ mDozeServiceHost.firePowerSaveChanged(isPowerSave);
}
}
@Override
@@ -1128,12 +1124,14 @@
@Override
public boolean onLongClick(View v) {
if (mRecents != null) {
- mRecents.dockTopTask(false /* draggingInRecents */,
+ boolean docked = mRecents.dockTopTask(false /* draggingInRecents */,
ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
null /* initialBounds */);
- MetricsLogger.action(mContext,
- MetricsLogger.ACTION_WINDOW_DOCK_LONGPRESS);
- return true;
+ if (docked) {
+ MetricsLogger.action(mContext,
+ MetricsLogger.ACTION_WINDOW_DOCK_LONGPRESS);
+ return true;
+ }
}
return false;
}
@@ -2275,7 +2273,7 @@
mStatusBarWindowManager.setStatusBarFocusable(false);
mStatusBarWindow.cancelExpandHelper();
- mStatusBarView.collapseAllPanels(true /* animate */, delayed, speedUpFactor);
+ mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
}
}
@@ -2324,7 +2322,7 @@
public void animateCollapseQuickSettings() {
if (mState == StatusBarState.SHADE) {
- mStatusBarView.collapseAllPanels(true, false /* delayed */, 1.0f /* speedUpFactor */);
+ mStatusBarView.collapsePanel(true, false /* delayed */, 1.0f /* speedUpFactor */);
}
}
@@ -2337,7 +2335,7 @@
}
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
- mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/,
+ mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/,
1.0f /* speedUpFactor */);
mNotificationPanel.closeQs();
@@ -2429,7 +2427,7 @@
mStatusBarWindowState = state;
if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state));
if (!showing && mState == StatusBarState.SHADE) {
- mStatusBarView.collapseAllPanels(false /* animate */, false /* delayed */,
+ mStatusBarView.collapsePanel(false /* animate */, false /* delayed */,
1.0f /* speedUpFactor */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index ab37e6a..813a167 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
-import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.EventLog;
import android.view.MotionEvent;
@@ -26,7 +25,6 @@
import com.android.systemui.DejankUtils;
import com.android.systemui.EventLogTags;
-import com.android.systemui.R;
public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView";
@@ -35,8 +33,7 @@
PhoneStatusBar mBar;
- PanelView mLastFullyOpenedPanel = null;
- PanelView mNotificationPanel;
+ boolean mIsFullyOpenedPanel = false;
private final PhoneStatusBarTransitions mBarTransitions;
private ScrimController mScrimController;
private float mMinFraction;
@@ -72,15 +69,7 @@
}
@Override
- public void addPanel(PanelView pv) {
- super.addPanel(pv);
- if (pv.getId() == R.id.notification_panel) {
- mNotificationPanel = pv;
- }
- }
-
- @Override
- public boolean panelsEnabled() {
+ public boolean panelEnabled() {
return mBar.panelsEnabled();
}
@@ -100,24 +89,17 @@
}
@Override
- public PanelView selectPanelForTouch(MotionEvent touch) {
- return mNotificationPanel.getExpandedHeight() > 0
- ? null
- : mNotificationPanel;
- }
-
- @Override
public void onPanelPeeked() {
super.onPanelPeeked();
mBar.makeExpandedVisible(false);
}
@Override
- public void onAllPanelsCollapsed() {
- super.onAllPanelsCollapsed();
+ public void onPanelCollapsed() {
+ super.onPanelCollapsed();
// Close the status bar in the next frame so we can show the end of the animation.
DejankUtils.postAfterTraversal(mHideExpandedRunnable);
- mLastFullyOpenedPanel = null;
+ mIsFullyOpenedPanel = false;
}
public void removePendingHideExpandedRunnables() {
@@ -125,12 +107,12 @@
}
@Override
- public void onPanelFullyOpened(PanelView openPanel) {
- super.onPanelFullyOpened(openPanel);
- if (openPanel != mLastFullyOpenedPanel) {
- openPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ public void onPanelFullyOpened() {
+ super.onPanelFullyOpened();
+ if (!mIsFullyOpenedPanel) {
+ mPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
- mLastFullyOpenedPanel = openPanel;
+ mIsFullyOpenedPanel = true;
}
@Override
@@ -149,8 +131,8 @@
}
@Override
- public void onTrackingStarted(PanelView panel) {
- super.onTrackingStarted(panel);
+ public void onTrackingStarted() {
+ super.onTrackingStarted();
mBar.onTrackingStarted();
mScrimController.onTrackingStarted();
}
@@ -162,8 +144,8 @@
}
@Override
- public void onTrackingStopped(PanelView panel, boolean expand) {
- super.onTrackingStopped(panel, expand);
+ public void onTrackingStopped(boolean expand) {
+ super.onTrackingStopped(expand);
mBar.onTrackingStopped(expand);
}
@@ -187,8 +169,8 @@
}
@Override
- public void panelExpansionChanged(PanelView panel, float frac, boolean expanded) {
- super.panelExpansionChanged(panel, frac, expanded);
+ public void panelExpansionChanged(float frac, boolean expanded) {
+ super.panelExpansionChanged(frac, expanded);
mPanelFraction = frac;
updateScrimFraction();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 336b208..29ad5d1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -27,6 +27,7 @@
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import android.view.View;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.external.CustomTile;
@@ -99,6 +100,7 @@
private final TileServices mServices;
private final List<Callback> mCallbacks = new ArrayList<>();
+ private View mHeader;
public QSTileHost(Context context, PhoneStatusBar statusBar,
BluetoothController bluetooth, LocationController location,
@@ -135,6 +137,10 @@
TunerService.get(mContext).addTunable(this, TILES_SETTING);
}
+ public void setHeaderView(View view) {
+ mHeader = view;
+ }
+
public PhoneStatusBar getPhoneStatusBar() {
return mStatusBar;
}
@@ -173,6 +179,11 @@
// already logged
}
+ public void animateExpandQS() {
+ // TODO: Better path to animated panel expansion.
+ mHeader.performClick();
+ }
+
@Override
public void collapsePanels() {
mStatusBar.postAnimateCollapsePanels();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 3692aee..5b44f0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -197,23 +197,16 @@
}
}
- public void setupHost(QSTileHost host) {
- final QSTileHost myHost = new QSTileHost(host.getContext(), host.getPhoneStatusBar(),
- host.getBluetoothController(), host.getLocationController(),
- host.getRotationLockController(), host.getNetworkController(),
- host.getZenModeController(), host.getHotspotController(),
- host.getCastController(), host.getFlashlightController(),
- host.getUserSwitcherController(), host.getUserInfoController(),
- host.getKeyguardMonitor(), host.getSecurityController(),
- host.getBatteryController(), host.getIconController());
+ public void setupHost(final QSTileHost host) {
+ host.setHeaderView(this);
mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
- mHeaderQsPanel.setHost(myHost);
+ mHeaderQsPanel.setHost(host);
mHeaderQsPanel.setMaxTiles(5);
- mHeaderQsPanel.setTiles(myHost.getTiles());
- myHost.addCallback(new QSTile.Host.Callback() {
+ mHeaderQsPanel.setTiles(host.getTiles());
+ host.addCallback(new QSTile.Host.Callback() {
@Override
public void onTilesChanged() {
- mHeaderQsPanel.setTiles(myHost.getTiles());
+ mHeaderQsPanel.setTiles(host.getTiles());
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 3d21f44..d2f1ca9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -419,7 +419,7 @@
}
@Override
- public void onPowerSaveChanged() {
+ public void onPowerSaveChanged(boolean isPowerSave) {
// could not care less
}
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 9d2f0de..382de19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -134,6 +134,12 @@
mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
+
+ if (state.remoteInputActive) {
+ mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
+ } else {
+ mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+ }
}
private void applyHeight(State state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 5071df0..bb3e116 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -70,9 +70,14 @@
pw.print(" mPowerSave="); pw.println(mPowerSave);
}
+ public void setPowerSaveMode(boolean powerSave) {
+ mPowerManager.setPowerSaveMode(powerSave);
+ }
+
public void addStateChangedCallback(BatteryStateChangeCallback cb) {
mChangeCallbacks.add(cb);
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ cb.onPowerSaveChanged(mPowerSave);
}
public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
@@ -158,12 +163,12 @@
private void firePowerSaveChanged() {
final int N = mChangeCallbacks.size();
for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onPowerSaveChanged();
+ mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
}
}
public interface BatteryStateChangeCallback {
void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
- void onPowerSaveChanged();
+ void onPowerSaveChanged(boolean isPowerSave);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 03409846..4ae0321 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -35,25 +35,25 @@
private final ScrimView mScrimBehind;
private final View mBrightnessMirror;
- private final View mPanelHolder;
+ private final View mNotificationPanel;
private final int[] mInt2Cache = new int[2];
public BrightnessMirrorController(StatusBarWindowView statusBarWindow) {
mScrimBehind = (ScrimView) statusBarWindow.findViewById(R.id.scrim_behind);
mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror);
- mPanelHolder = statusBarWindow.findViewById(R.id.panel_holder);
+ mNotificationPanel = statusBarWindow.findViewById(R.id.notification_panel);
}
public void showMirror() {
mBrightnessMirror.setVisibility(View.VISIBLE);
mScrimBehind.animateViewAlpha(0.0f, TRANSITION_DURATION_OUT, PhoneStatusBar.ALPHA_OUT);
- outAnimation(mPanelHolder.animate())
+ outAnimation(mNotificationPanel.animate())
.withLayer();
}
public void hideMirror() {
mScrimBehind.animateViewAlpha(1.0f, TRANSITION_DURATION_IN, PhoneStatusBar.ALPHA_IN);
- inAnimation(mPanelHolder.animate())
+ inAnimation(mNotificationPanel.animate())
.withLayer()
.withEndAction(new Runnable() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index b65bf43..ad8e3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -440,6 +440,7 @@
+ " dataState=" + state.getDataRegState());
}
mServiceState = state;
+ mDataNetType = state.getDataNetworkType();
updateTelephony();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 65053f3..61a9851 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -26,6 +26,7 @@
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
@@ -174,8 +175,8 @@
}
public void focus() {
- mEditText.setInnerFocusable(true);
mController.addRemoteInput(mEntry);
+ mEditText.setInnerFocusable(true);
mEditText.mShowImeOnInputConnection = true;
mEditText.setText(mEntry.remoteInputText);
mEditText.setSelection(mEditText.getText().length());
@@ -257,6 +258,20 @@
}
@Override
+ public boolean requestRectangleOnScreen(Rect r) {
+ r.top = mScrollY;
+ r.bottom = mScrollY + (mBottom - mTop);
+ return super.requestRectangleOnScreen(r);
+ }
+
+ @Override
+ public void getFocusedRect(Rect r) {
+ super.getFocusedRect(r);
+ r.top = mScrollY;
+ r.bottom = mScrollY + (mBottom - mTop);
+ }
+
+ @Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
defocusIfNeeded();
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 b010761..f3a3554 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -643,8 +643,8 @@
private final Intent USER_SETTINGS_INTENT = new Intent("android.settings.USER_SETTINGS");
@Override
- public int getTitle() {
- return R.string.quick_settings_user_title;
+ public CharSequence getTitle() {
+ return mContext.getString(R.string.quick_settings_user_title);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 3c63aae..0901015 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -27,6 +27,7 @@
import android.app.Dialog;
import android.app.KeyguardManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
@@ -559,7 +560,13 @@
: R.drawable.ic_volume_expand_animation;
if (res == mExpandButtonRes) return;
mExpandButtonRes = res;
- mExpandButton.setImageResource(res);
+ if (hasTouchFeature()) {
+ mExpandButton.setImageResource(res);
+ } else {
+ // if there is no touch feature, show the volume ringer instead
+ mExpandButton.setImageResource(R.drawable.ic_volume_ringer);
+ mExpandButton.setBackgroundResource(0); // remove gray background emphasis
+ }
mExpandButton.setContentDescription(mContext.getString(mExpanded ?
R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand));
}
@@ -837,6 +844,11 @@
rescheduleTimeoutH();
}
+ private boolean hasTouchFeature() {
+ final PackageManager pm = mContext.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
+ }
+
private final VolumeDialogController.Callbacks mControllerCallbackH
= new VolumeDialogController.Callbacks() {
@Override
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 6ebf488..f86c6a4 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
@@ -283,6 +283,11 @@
public void onClick(IBinder iBinder) throws RemoteException {
sendCallback("onClick");
}
+
+ @Override
+ public void onUnlockComplete() throws RemoteException {
+ sendCallback("onUnlockComplete");
+ }
};
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 13fc47d..b64fbea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -60,8 +60,8 @@
protected NetworkControllerImpl mNetworkController;
protected MobileSignalController mMobileSignalController;
protected PhoneStateListener mPhoneStateListener;
- private SignalStrength mSignalStrength;
- private ServiceState mServiceState;
+ protected SignalStrength mSignalStrength;
+ protected ServiceState mServiceState;
protected ConnectivityManager mMockCm;
protected WifiManager mMockWm;
protected SubscriptionManager mMockSm;
@@ -235,7 +235,7 @@
mPhoneStateListener.onSignalStrengthsChanged(mSignalStrength);
}
- private void updateServiceState() {
+ protected void updateServiceState() {
Log.d(TAG, "Sending Service State: " + mServiceState);
mPhoneStateListener.onServiceStateChanged(mServiceState);
}
@@ -246,6 +246,7 @@
}
public void updateDataConnectionState(int dataState, int dataNetType) {
+ when(mServiceState.getDataNetworkType()).thenReturn(dataNetType);
mPhoneStateListener.onDataConnectionStateChanged(dataState, dataNetType);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 587e2b5..e4f858b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -115,6 +115,21 @@
TelephonyIcons.QS_DATA_4G);
}
+ public void testDataChangeWithoutConnectionState() {
+ setupDefaultSignal();
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */],
+ TelephonyIcons.QS_DATA_LTE);
+
+ Mockito.when(mServiceState.getDataNetworkType())
+ .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
+ updateServiceState();
+ verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */],
+ TelephonyIcons.QS_DATA_H);
+ }
+
public void testDataActivity() {
setupDefaultSignal();
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
index 28121b4..e3108015 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
@@ -64,6 +64,14 @@
// Indicates that motion events are being collected to match a gesture.
private boolean mRecognizingGesture;
+ // Indicates that motion events from the second pointer are being checked
+ // for a double tap.
+ private boolean mSecondFingerDoubleTap;
+
+ // Tracks the most recent time where ACTION_POINTER_DOWN was sent for the
+ // second pointer.
+ private long mSecondPointerDownTime;
+
// Policy flags of the previous event.
private int mPolicyFlags;
@@ -102,6 +110,7 @@
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mDoubleTapDetected = false;
+ mSecondFingerDoubleTap = false;
mRecognizingGesture = true;
mPreviousX = x;
mPreviousY = y;
@@ -133,6 +142,43 @@
}
}
break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ // Once a second finger is used, we're definitely not
+ // recognizing a gesture.
+ cancelGesture();
+
+ if (event.getPointerCount() == 2) {
+ // If this was the second finger, attempt to recognize double
+ // taps on it.
+ mSecondFingerDoubleTap = true;
+ mSecondPointerDownTime = event.getEventTime();
+ } else {
+ // If there are more than two fingers down, stop watching
+ // for a double tap.
+ mSecondFingerDoubleTap = false;
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ // If we're detecting taps on the second finger, see if we
+ // should finish the double tap.
+ if (mSecondFingerDoubleTap && maybeFinishDoubleTap(event, policyFlags)) {
+ return true;
+ }
+ break;
+ }
+
+ // If we're detecting taps on the second finger, map events from the
+ // finger to the first finger.
+ if (mSecondFingerDoubleTap) {
+ MotionEvent newEvent = mapSecondPointerToFirstPointer(event);
+ if (newEvent == null) {
+ return false;
+ }
+ boolean handled = mGestureDetector.onTouchEvent(newEvent);
+ newEvent.recycle();
+ return handled;
}
if (!mRecognizingGesture) {
@@ -146,6 +192,7 @@
public void clear() {
mFirstTapDetected = false;
mDoubleTapDetected = false;
+ mSecondFingerDoubleTap = false;
cancelGesture();
mStrokeBuffer.clear();
}
@@ -229,4 +276,28 @@
return false;
}
+
+ private MotionEvent mapSecondPointerToFirstPointer(MotionEvent event) {
+ // Only map basic events when two fingers are down.
+ if (event.getPointerCount() != 2 ||
+ (event.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN &&
+ event.getActionMasked() != MotionEvent.ACTION_POINTER_UP &&
+ event.getActionMasked() != MotionEvent.ACTION_MOVE)) {
+ return null;
+ }
+
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ action = MotionEvent.ACTION_DOWN;
+ } else if (action == MotionEvent.ACTION_POINTER_UP) {
+ action = MotionEvent.ACTION_UP;
+ }
+
+ // Map the information from the second pointer to the first.
+ return MotionEvent.obtain(mSecondPointerDownTime, event.getEventTime(), action,
+ event.getX(1), event.getY(1), event.getPressure(1), event.getSize(1),
+ event.getMetaState(), event.getXPrecision(), event.getYPrecision(),
+ event.getDeviceId(), event.getEdgeFlags());
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 5f6cbf9..232c080 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -69,6 +69,13 @@
*/
static final int FLAG_FEATURE_AUTOCLICK = 0x00000008;
+ /**
+ * Flag for enabling motion event injectsion
+ *
+ * @see #setUserAndEnabledFeatures(int, int)
+ */
+ static final int FLAG_FEATURE_INJECT_MOTION_EVENTS = 0x00000010;
+
private final Runnable mProcessBatchedEventsRunnable = new Runnable() {
@Override
public void run() {
@@ -104,6 +111,8 @@
private MagnificationGestureHandler mMagnificationGestureHandler;
+ private MotionEventInjector mMotionEventInjector;
+
private AutoclickController mAutoclickController;
private KeyboardInterceptor mKeyboardInterceptor;
@@ -191,6 +200,10 @@
}
}
+ public MotionEventInjector getMotionEventInjector() {
+ return mMotionEventInjector;
+ }
+
/**
* Gets current event stream state associated with an input event.
* @return The event stream state that should be used for the event. Null if the event should
@@ -351,6 +364,12 @@
private void enableFeatures() {
resetStreamState();
+ if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
+ mMotionEventInjector = new MotionEventInjector(mContext.getMainLooper());
+ addFirstEventHandler(mMotionEventInjector);
+ mAms.setMotionEventInjector(mMotionEventInjector);
+ }
+
if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
mAutoclickController = new AutoclickController(mContext, mUserId);
addFirstEventHandler(mAutoclickController);
@@ -388,6 +407,11 @@
}
private void disableFeatures() {
+ if (mMotionEventInjector != null) {
+ mAms.setMotionEventInjector(null);
+ mMotionEventInjector.onDestroy();
+ mMotionEventInjector = null;
+ }
if (mAutoclickController != null) {
mAutoclickController.onDestroy();
mAutoclickController = null;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 8cf25b3..39d5952 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -37,6 +37,7 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -72,6 +73,7 @@
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
+import android.view.MotionEvent;
import android.view.WindowInfo;
import android.view.WindowManager;
import android.view.WindowManagerInternal;
@@ -186,6 +188,8 @@
private KeyEventDispatcher mKeyEventDispatcher;
+ private MotionEventInjector mMotionEventInjector;
+
private final Set<ComponentName> mTempComponentNameSet = new HashSet<>();
private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
@@ -779,6 +783,18 @@
}
/**
+ * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector.
+ * Not using a getter because the AccessibilityInputFilter isn't thread-safe
+ *
+ * @param motionEventInjector The new value of the motionEventInjector. May be null.
+ */
+ void setMotionEventInjector(MotionEventInjector motionEventInjector) {
+ synchronized (mLock) {
+ mMotionEventInjector = motionEventInjector;
+ }
+ }
+
+ /**
* Gets a point within the accessibility focused node where we can send down
* and up events to perform a click.
*
@@ -1273,6 +1289,9 @@
if (userState.mIsAutoclickEnabled) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK;
}
+ if (userState.mIsPerformGesturesEnabled) {
+ flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
+ }
if (flags != 0) {
if (!mHasInputFilter) {
mHasInputFilter = true;
@@ -1363,6 +1382,7 @@
updateAccessibilityFocusBehaviorLocked(userState);
updateFilterKeyEventsLocked(userState);
updateTouchExplorationLocked(userState);
+ updatePerformGesturesLocked(userState);
updateEnhancedWebAccessibilityLocked(userState);
updateDisplayColorAdjustmentSettingsLocked(userState);
updateMagnificationLocked(userState);
@@ -1451,6 +1471,19 @@
}
}
+ private void updatePerformGesturesLocked(UserState userState) {
+ final int serviceCount = userState.mBoundServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ Service service = userState.mBoundServices.get(i);
+ if ((service.mAccessibilityServiceInfo.getCapabilities()
+ & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) {
+ userState.mIsPerformGesturesEnabled = true;
+ return;
+ }
+ }
+ userState.mIsPerformGesturesEnabled = false;
+ }
+
private void updateFilterKeyEventsLocked(UserState userState) {
final int serviceCount = userState.mBoundServices.size();
for (int i = 0; i < serviceCount; i++) {
@@ -2564,6 +2597,23 @@
}
@Override
+ public void sendMotionEvents(int sequence, ParceledListSlice events) {
+ synchronized (mLock) {
+ if (mSecurityPolicy.canPerformGestures(this) && (mMotionEventInjector != null)) {
+ mMotionEventInjector.injectEvents((List<MotionEvent>) events.getList(),
+ mServiceInterface, sequence);
+ return;
+ }
+ }
+ try {
+ mServiceInterface.onPerformGestureResult(sequence, false);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error sending motion event injection failure to "
+ + mServiceInterface, re);
+ }
+ }
+
+ @Override
public boolean performAccessibilityAction(int accessibilityWindowId,
long accessibilityNodeId, int action, Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
@@ -3734,6 +3784,11 @@
& AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0;
}
+ public boolean canPerformGestures(Service service) {
+ return (service.mAccessibilityServiceInfo.getCapabilities()
+ & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0;
+ }
+
private int resolveProfileParentLocked(int userId) {
if (userId != mCurrentUserId) {
final long identity = Binder.clearCallingIdentity();
@@ -3878,6 +3933,7 @@
public boolean mIsEnhancedWebAccessibilityEnabled;
public boolean mIsDisplayMagnificationEnabled;
public boolean mIsAutoclickEnabled;
+ public boolean mIsPerformGesturesEnabled;
public boolean mIsFilterKeyEventsEnabled;
public boolean mHasDisplayColorAdjustment;
public boolean mAccessibilityFocusOnlyInActiveWindow;
diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
new file mode 100644
index 0000000..800f0e1
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import android.accessibilityservice.IAccessibilityServiceClient;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.WindowManagerPolicy;
+import android.view.accessibility.AccessibilityEvent;
+import com.android.internal.os.SomeArgs;
+import com.android.server.accessibility.AccessibilityManagerService.Service;
+
+import java.util.List;
+
+/**
+ * Injects MotionEvents to permit {@code AccessibilityService}s to touch the screen on behalf of
+ * users.
+ *
+ * All methods except {@code injectEvents} must be called only from the main thread.
+ */
+public class MotionEventInjector implements EventStreamTransformation {
+ private static final String LOG_TAG = "MotionEventInjector";
+ private static final int MESSAGE_SEND_MOTION_EVENT = 1;
+ private static final int MESSAGE_INJECT_EVENTS = 2;
+ private static final int MAX_POINTERS = 11; // Non-binding maximum
+
+ private final Handler mHandler;
+ private final SparseArray<Boolean> mOpenGesturesInProgress = new SparseArray<>();
+
+ // These two arrays must be the same length
+ private MotionEvent.PointerProperties[] mPointerProperties =
+ new MotionEvent.PointerProperties[MAX_POINTERS];
+ private MotionEvent.PointerCoords[] mPointerCoords =
+ new MotionEvent.PointerCoords[MAX_POINTERS];
+ private EventStreamTransformation mNext;
+ private IAccessibilityServiceClient mServiceInterfaceForCurrentGesture;
+ private int mSequenceForCurrentGesture;
+ private int mSourceOfInjectedGesture = InputDevice.SOURCE_UNKNOWN;
+ private boolean mIsDestroyed = false;
+
+ /**
+ * @param looper A looper on the main thread to use for dispatching new events
+ */
+ public MotionEventInjector(Looper looper) {
+ mHandler = new Handler(looper, new Callback());
+ }
+
+ /**
+ * Schedule a series of events for injection. These events must comprise a complete, valid
+ * sequence. All gestures currently in progress will be cancelled, and all {@code downTime}
+ * and {@code eventTime} fields will be offset by the current time.
+ *
+ * @param events The events to inject. Must all be from the same source.
+ * @param serviceInterface The interface to call back with a result when the gesture is
+ * either complete or cancelled.
+ */
+ public void injectEvents(List<MotionEvent> events,
+ IAccessibilityServiceClient serviceInterface, int sequence) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = events;
+ args.arg2 = serviceInterface;
+ args.argi1 = sequence;
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_INJECT_EVENTS, args));
+ }
+
+ @Override
+ public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ cancelAnyPendingInjectedEvents();
+ sendMotionEventToNext(event, rawEvent, policyFlags);
+ }
+
+ @Override
+ public void onKeyEvent(KeyEvent event, int policyFlags) {
+ if (mNext != null) {
+ mNext.onKeyEvent(event, policyFlags);
+ }
+ }
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ if (mNext != null) {
+ mNext.onAccessibilityEvent(event);
+ }
+ }
+
+ @Override
+ public void setNext(EventStreamTransformation next) {
+ mNext = next;
+ }
+
+ @Override
+ public void clearEvents(int inputSource) {
+ /*
+ * Reset state for motion events passing through so we won't send a cancel event for
+ * them.
+ */
+ if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
+ mOpenGesturesInProgress.put(inputSource, false);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ cancelAnyPendingInjectedEvents();
+ mIsDestroyed = true;
+ }
+
+ private void injectEventsMainThread(List<MotionEvent> events,
+ IAccessibilityServiceClient serviceInterface, int sequence) {
+ if (mIsDestroyed) {
+ try {
+ serviceInterface.onPerformGestureResult(sequence, false);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error sending status with mIsDestroyed to " + serviceInterface,
+ re);
+ }
+ return;
+ }
+ cancelAnyPendingInjectedEvents();
+ mSourceOfInjectedGesture = events.get(0).getSource();
+ cancelAnyGestureInProgress(mSourceOfInjectedGesture);
+ mServiceInterfaceForCurrentGesture = serviceInterface;
+ mSequenceForCurrentGesture = sequence;
+ if (mNext == null) {
+ notifyService(false);
+ return;
+ }
+
+ long startTime = SystemClock.uptimeMillis();
+ for (int i = 0; i < events.size(); i++) {
+ MotionEvent event = events.get(i);
+ int numPointers = event.getPointerCount();
+ if (numPointers > mPointerCoords.length) {
+ mPointerCoords = new MotionEvent.PointerCoords[numPointers];
+ mPointerProperties = new MotionEvent.PointerProperties[numPointers];
+ }
+ for (int j = 0; j < numPointers; j++) {
+ if (mPointerCoords[j] == null) {
+ mPointerCoords[j] = new MotionEvent.PointerCoords();
+ mPointerProperties[j] = new MotionEvent.PointerProperties();
+ }
+ event.getPointerCoords(j, mPointerCoords[j]);
+ event.getPointerProperties(j, mPointerProperties[j]);
+ }
+
+ /*
+ * MotionEvent doesn't have a setEventTime() method (it carries around history data,
+ * which could become inconsistent), so we need to obtain a new one.
+ */
+ MotionEvent offsetEvent = MotionEvent.obtain(startTime + event.getDownTime(),
+ startTime + event.getEventTime(), event.getAction(), numPointers,
+ mPointerProperties, mPointerCoords, event.getMetaState(),
+ event.getButtonState(), event.getXPrecision(), event.getYPrecision(),
+ event.getDeviceId(), event.getEdgeFlags(), event.getSource(),
+ event.getFlags());
+ Message message = mHandler.obtainMessage(MESSAGE_SEND_MOTION_EVENT, offsetEvent);
+ mHandler.sendMessageDelayed(message, event.getEventTime());
+ }
+ }
+
+ private void sendMotionEventToNext(MotionEvent event, MotionEvent rawEvent,
+ int policyFlags) {
+ if (mNext != null) {
+ mNext.onMotionEvent(event, rawEvent, policyFlags);
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mOpenGesturesInProgress.put(event.getSource(), true);
+ }
+ if ((event.getActionMasked() == MotionEvent.ACTION_UP)
+ || (event.getActionMasked() == MotionEvent.ACTION_CANCEL)) {
+ mOpenGesturesInProgress.put(event.getSource(), false);
+ }
+ }
+ }
+
+ private void cancelAnyGestureInProgress(int source) {
+ if ((mNext != null) && mOpenGesturesInProgress.get(source, false)) {
+ long now = SystemClock.uptimeMillis();
+ MotionEvent cancelEvent =
+ MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+ sendMotionEventToNext(cancelEvent, cancelEvent,
+ WindowManagerPolicy.FLAG_PASS_TO_USER);
+ }
+ }
+
+ private void cancelAnyPendingInjectedEvents() {
+ if (mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
+ cancelAnyGestureInProgress(mSourceOfInjectedGesture);
+ mHandler.removeMessages(MESSAGE_SEND_MOTION_EVENT);
+ notifyService(false);
+ }
+
+ }
+
+ private void notifyService(boolean success) {
+ try {
+ mServiceInterfaceForCurrentGesture.onPerformGestureResult(
+ mSequenceForCurrentGesture, success);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error sending motion event injection status to "
+ + mServiceInterfaceForCurrentGesture, re);
+ }
+ }
+
+ private class Callback implements Handler.Callback {
+ @Override
+ public boolean handleMessage(Message message) {
+ if (message.what == MESSAGE_INJECT_EVENTS) {
+ SomeArgs args = (SomeArgs) message.obj;
+ injectEventsMainThread((List<MotionEvent>) args.arg1,
+ (IAccessibilityServiceClient) args.arg2, args.argi1);
+ args.recycle();
+ return true;
+ }
+ if (message.what != MESSAGE_SEND_MOTION_EVENT) {
+ throw new IllegalArgumentException("Unknown message: " + message.what);
+ }
+ MotionEvent motionEvent = (MotionEvent) message.obj;
+ sendMotionEventToNext(motionEvent, motionEvent,
+ WindowManagerPolicy.FLAG_PASS_TO_USER);
+ // If the message queue is now empty, then this gesture is complete
+ if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) {
+ notifyService(true);
+ }
+ return true;
+ }
+ }
+}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 6f8f8eb..db901aa 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -16,7 +16,6 @@
package com.android.server.appwidget;
-import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -2206,9 +2205,11 @@
final Resources resources;
final long identity = Binder.clearCallingIdentity();
try {
- resources = mContext.getPackageManager()
- .getResourcesForApplicationAsUser(activityInfo.packageName,
- UserHandle.getUserId(providerId.uid));
+ final PackageManager pm = mContext.getPackageManager();
+ final int userId = UserHandle.getUserId(providerId.uid);
+ final ApplicationInfo app = pm.getApplicationInfoAsUser(activityInfo.packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
+ resources = pm.getResourcesForApplication(app);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2309,6 +2310,10 @@
try {
int flags = PackageManager.GET_META_DATA;
+ // We really need packages to be around and parsed to know if they
+ // provide widgets, and we only load widgets after user is unlocked.
+ flags |= PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+
// Widgets referencing shared libraries need to have their
// dependencies loaded.
flags |= PackageManager.GET_SHARED_LIBRARY_FILES;
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 353b404..e6e69b1 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -265,8 +265,8 @@
Ops ops = it.next();
int curUid = -1;
try {
- curUid = AppGlobals.getPackageManager().getPackageUidEtc(ops.packageName,
- PackageManager.GET_UNINSTALLED_PACKAGES,
+ curUid = AppGlobals.getPackageManager().getPackageUid(ops.packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES,
UserHandle.getUserId(ops.uidState.uid));
} catch (RemoteException ignored) {
}
@@ -691,7 +691,7 @@
if (reqPackageName != null) {
try {
reqUid = AppGlobals.getPackageManager().getPackageUid(
- reqPackageName, reqUserId);
+ reqPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, reqUserId);
} catch (RemoteException e) {
/* ignore - local call */
}
@@ -1167,7 +1167,9 @@
int pkgUid = -1;
try {
ApplicationInfo appInfo = ActivityThread.getPackageManager()
- .getApplicationInfo(packageName, 0, UserHandle.getUserId(uid));
+ .getApplicationInfo(packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.getUserId(uid));
if (appInfo != null) {
pkgUid = appInfo.uid;
isPrivileged = (appInfo.privateFlags
@@ -1647,7 +1649,8 @@
if ("root".equals(packageName)) {
packageUid = 0;
} else {
- packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, userId);
+ packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
}
if (packageUid < 0) {
err.println("Error: No UID for " + packageName + " in user " + userId);
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index 4569dae..b5ea641 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -176,7 +176,8 @@
private static String queryVersionName(Context context) {
try {
String packageName = context.getPackageName();
- PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
+ PackageInfo info = context.getPackageManager().getPackageInfo(packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
return info.versionName;
} catch (PackageManager.NameNotFoundException e) {
Log.w(LOG_TAG, "Could not get package info", e);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 3c91423..c1a082b 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -269,7 +269,7 @@
int sysUiUid = -1;
try {
sysUiUid = mContext.getPackageManager().getPackageUidAsUser("com.android.systemui",
- UserHandle.USER_SYSTEM);
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
} catch (PackageManager.NameNotFoundException e) {
// Some platforms, such as wearables do not have a system ui.
Log.w(TAG, "Unable to resolve SystemUI's UID.", e);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 65a27c8..37a6c02 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4848,6 +4848,11 @@
}
@Override
+ public String getCaptivePortalServerUrl() {
+ return NetworkMonitor.getCaptivePortalServerUrl(mContext);
+ }
+
+ @Override
public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger,
IBinder binder, String srcAddr, int srcPort, String dstAddr) {
enforceKeepalivePermission();
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 8d707d6..bd95892 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1052,12 +1052,11 @@
for (int i=0; i<allowPowerExceptIdle.size(); i++) {
String pkg = allowPowerExceptIdle.valueAt(i);
try {
- ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
- if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
- int appid = UserHandle.getAppId(ai.uid);
- mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
- mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
- }
+ ApplicationInfo ai = pm.getApplicationInfo(pkg,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ int appid = UserHandle.getAppId(ai.uid);
+ mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
+ mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
} catch (PackageManager.NameNotFoundException e) {
}
}
@@ -1065,16 +1064,15 @@
for (int i=0; i<allowPower.size(); i++) {
String pkg = allowPower.valueAt(i);
try {
- ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
- if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
- int appid = UserHandle.getAppId(ai.uid);
- // These apps are on both the whitelist-except-idle as well
- // as the full whitelist, so they apply in all cases.
- mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
- mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
- mPowerSaveWhitelistApps.put(ai.packageName, appid);
- mPowerSaveWhitelistSystemAppIds.put(appid, true);
- }
+ ApplicationInfo ai = pm.getApplicationInfo(pkg,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ int appid = UserHandle.getAppId(ai.uid);
+ // These apps are on both the whitelist-except-idle as well
+ // as the full whitelist, so they apply in all cases.
+ mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
+ mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
+ mPowerSaveWhitelistApps.put(ai.packageName, appid);
+ mPowerSaveWhitelistSystemAppIds.put(appid, true);
} catch (PackageManager.NameNotFoundException e) {
}
}
@@ -1182,9 +1180,7 @@
synchronized (this) {
try {
ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
- PackageManager.GET_UNINSTALLED_PACKAGES
- | PackageManager.GET_DISABLED_COMPONENTS
- | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
+ PackageManager.MATCH_UNINSTALLED_PACKAGES);
if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
reportPowerSaveWhitelistChangedLocked();
updateWhitelistAppIdsLocked();
@@ -2010,9 +2006,7 @@
if (name != null) {
try {
ApplicationInfo ai = pm.getApplicationInfo(name,
- PackageManager.GET_UNINSTALLED_PACKAGES
- | PackageManager.GET_DISABLED_COMPONENTS
- | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
+ PackageManager.MATCH_UNINSTALLED_PACKAGES);
mPowerSaveWhitelistUserApps.put(ai.packageName,
UserHandle.getAppId(ai.uid));
} catch (PackageManager.NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/GraphicsStatsService.java b/services/core/java/com/android/server/GraphicsStatsService.java
index 3fdef1d..044bb04 100644
--- a/services/core/java/com/android/server/GraphicsStatsService.java
+++ b/services/core/java/com/android/server/GraphicsStatsService.java
@@ -16,9 +16,8 @@
package com.android.server;
+import android.app.AppOpsManager;
import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Binder;
import android.os.IBinder;
import android.os.MemoryFile;
@@ -66,6 +65,7 @@
private static final int HISTORY_SIZE = 20;
private final Context mContext;
+ private final AppOpsManager mAppOps;
private final Object mLock = new Object();
private ArrayList<ActiveBuffer> mActive = new ArrayList<>();
private HistoricalData[] mHistoricalLog = new HistoricalData[HISTORY_SIZE];
@@ -74,15 +74,7 @@
public GraphicsStatsService(Context context) {
mContext = context;
- }
-
- private boolean isValid(int uid, String packageName) {
- try {
- PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
- return info.applicationInfo.uid == uid;
- } catch (NameNotFoundException e) {
- }
- return false;
+ mAppOps = context.getSystemService(AppOpsManager.class);
}
@Override
@@ -93,9 +85,7 @@
ParcelFileDescriptor pfd = null;
long callingIdentity = Binder.clearCallingIdentity();
try {
- if (!isValid(uid, packageName)) {
- throw new RemoteException("Invalid package name");
- }
+ mAppOps.checkPackage(uid, packageName);
synchronized (mLock) {
pfd = requestBufferForProcessLocked(token, uid, pid, packageName);
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 1a21f5c..377d52f 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -695,7 +695,7 @@
unlockUser(userId, token);
UserInfo info = UserManager.get(mContext).getUserInfo(userId);
- if (LockPatternUtils.isSeparateWorkChallengeEnabled() && info.isManagedProfile()) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
TrustManager trustManager =
(TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
trustManager.setDeviceLockedForUser(userId, false);
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index 137fa27..816c791 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -71,6 +71,7 @@
private final Object mFileWriteLock = new Object();
private int mStoredCredentialType;
+ private LockPatternUtils mLockPatternUtils;
class CredentialHash {
static final int TYPE_NONE = -1;
@@ -100,6 +101,7 @@
public LockSettingsStorage(Context context, Callback callback) {
mContext = context;
mOpenHelper = new DatabaseHelper(context, callback);
+ mLockPatternUtils = new LockPatternUtils(context);
}
public void writeKeyValue(String key, String value, int userId) {
@@ -388,7 +390,7 @@
private int getUserParentOrSelfId(int userId) {
// Device supports per user encryption, so lock is applied to the given user.
- if (LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
return userId;
}
// Device uses Block Based Encryption, and the parent user's lock is used for the whole
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 6cccf38..4a186a6 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2355,7 +2355,8 @@
return false;
}
- final int packageUid = mPms.getPackageUid(packageName, UserHandle.getUserId(callerUid));
+ final int packageUid = mPms.getPackageUid(packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callerUid));
if (DEBUG_OBB) {
Slog.d(TAG, "packageName = " + packageName + ", packageUid = " +
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 1249c8c..a291cc7 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -94,7 +94,8 @@
PackageManager pm = mContext.getPackageManager();
int allowedUid = -1;
try {
- allowedUid = pm.getPackageUidAsUser(allowedPackage, userHandle);
+ allowedUid = pm.getPackageUidAsUser(allowedPackage,
+ PackageManager.MATCH_SYSTEM_ONLY, userHandle);
} catch (PackageManager.NameNotFoundException e) {
// not expected
Slog.e(TAG, "not able to find package " + allowedPackage, e);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 2d8d6f2..f345d7e 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3200,7 +3200,8 @@
int packageUid = -1;
try {
packageUid = AppGlobals.getPackageManager().getPackageUid(
- packageName, UserHandle.getCallingUserId());
+ packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+ UserHandle.getCallingUserId());
} catch (RemoteException re) {
Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re);
return new Account[0];
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 9dda321..7ba6338 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -61,6 +61,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -326,7 +327,7 @@
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
- callingPid, callingUid, userId, true, callerFg);
+ callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
}
@@ -549,7 +550,7 @@
// If this service is active, make sure it is stopped.
ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
- Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false);
+ Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false);
if (r != null) {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
@@ -598,7 +599,7 @@
IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(),
- UserHandle.getCallingUserId(), false, false);
+ UserHandle.getCallingUserId(), false, false, false);
IBinder ret = null;
if (r != null) {
@@ -831,10 +832,11 @@
}
final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType, callingPackage,
- Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
+ retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
if (res == null) {
return 0;
}
@@ -1192,7 +1194,7 @@
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
- boolean createIfNeeded, boolean callingFromFg) {
+ boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
ServiceRecord r = null;
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
+ " type=" + resolvedType + " callingUid=" + callingUid);
@@ -1205,16 +1207,23 @@
if (comp != null) {
r = smap.mServicesByName.get(comp);
}
- if (r == null) {
+ if (r == null && !isBindExternal) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
r = smap.mServicesByIntent.get(filter);
}
+ if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
+ && !callingPackage.equals(r.packageName)) {
+ // If an external service is running within its own package, other packages
+ // should not bind to that instance.
+ r = null;
+ }
if (r == null) {
try {
- ResolveInfo rInfo =
- AppGlobals.getPackageManager().resolveService(
- service, resolvedType,
- ActivityManagerService.STOCK_PM_FLAGS, userId);
+ // TODO: come back and remove this assumption to triage all services
+ ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
+ resolvedType, ActivityManagerService.STOCK_PM_FLAGS
+ | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
@@ -1224,6 +1233,37 @@
}
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
+ if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {
+ if (isBindExternal) {
+ if (!sInfo.exported) {
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
+ " is not exported");
+ }
+ if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
+ " is not an isolatedProcess");
+ }
+ // Run the service under the calling package's application.
+ ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
+ callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId);
+ if (aInfo == null) {
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " +
+ "could not resolve client package " + callingPackage);
+ }
+ sInfo = new ServiceInfo(sInfo);
+ sInfo.applicationInfo = new ApplicationInfo(sInfo.applicationInfo);
+ sInfo.applicationInfo.packageName = aInfo.packageName;
+ sInfo.applicationInfo.uid = aInfo.uid;
+ name = new ComponentName(aInfo.packageName, name.getClassName());
+ service.setComponent(name);
+ } else {
+ throw new SecurityException("BIND_EXTERNAL_SERVICE required for " +
+ name);
+ }
+ } else if (isBindExternal) {
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
+ " is not an externalService");
+ }
if (userId > 0) {
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
sInfo.name, sInfo.flags)
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4946599..093a33d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -35,6 +35,7 @@
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
import com.android.internal.os.Zygote;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
@@ -255,6 +256,11 @@
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+import static android.content.pm.PackageManager.GET_PROVIDERS;
+import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
@@ -512,9 +518,9 @@
private Installer mInstaller;
/** Run all ActivityStacks through this */
- ActivityStackSupervisor mStackSupervisor;
+ final ActivityStackSupervisor mStackSupervisor;
- ActivityStarter mActivityStarter;
+ final ActivityStarter mActivityStarter;
/** Task stack change listeners. */
private RemoteCallbackList<ITaskStackListener> mTaskStackListeners =
@@ -1303,7 +1309,7 @@
int mMemWatchDumpUid;
String mTrackAllocationApp = null;
- final long[] mTmpLong = new long[1];
+ final long[] mTmpLong = new long[2];
static final class ProcessChangeItem {
static final int CHANGE_ACTIVITIES = 1<<0;
@@ -1951,7 +1957,10 @@
break;
}
case SYSTEM_USER_UNLOCK_MSG: {
- mSystemServiceManager.unlockUser(msg.arg1);
+ final int userId = msg.arg1;
+ mSystemServiceManager.unlockUser(userId);
+ mRecentTasks.cleanupLocked(userId);
+ installEncryptionUnawareProviders(userId);
break;
}
case SYSTEM_USER_CURRENT_MSG: {
@@ -2233,7 +2242,7 @@
}
int num = 0;
- long[] tmp = new long[1];
+ long[] tmp = new long[2];
do {
ProcessRecord proc;
int procState;
@@ -2265,7 +2274,7 @@
if (pss != 0 && proc.thread != null && proc.setProcState == procState
&& proc.pid == pid && proc.lastPssTime == lastPssTime) {
num++;
- recordPssSampleLocked(proc, procState, pss, tmp[0],
+ recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1],
SystemClock.uptimeMillis());
}
}
@@ -2290,7 +2299,7 @@
ServiceManager.addService("processinfo", new ProcessInfoService(this));
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
- "android", STOCK_PM_FLAGS);
+ "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
synchronized (this) {
@@ -3442,7 +3451,8 @@
try {
checkTime(startTime, "startProcess: getting gids from package manager");
final IPackageManager pm = AppGlobals.getPackageManager();
- permGids = pm.getPackageGids(app.info.packageName, app.userId);
+ permGids = pm.getPackageGids(app.info.packageName,
+ MATCH_DEBUG_TRIAGED_MISSING, app.userId);
MountServiceInternal mountServiceInternal = LocalServices.getService(
MountServiceInternal.class);
mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
@@ -3638,11 +3648,9 @@
return false;
}
Intent intent = getHomeIntent();
- ActivityInfo aInfo =
- resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
+ ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
- intent.setComponent(new ComponentName(
- aInfo.applicationInfo.packageName, aInfo.name));
+ intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
@@ -3701,21 +3709,11 @@
mCheckedForSetup = true;
// See if we should be showing the platform update setup UI.
- Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
- List<ResolveInfo> ris = mContext.getPackageManager()
- .queryIntentActivities(intent, PackageManager.GET_META_DATA);
-
- // We don't allow third party apps to replace this.
- ResolveInfo ri = null;
- for (int i=0; ris != null && i<ris.size(); i++) {
- if ((ris.get(i).activityInfo.applicationInfo.flags
- & ApplicationInfo.FLAG_SYSTEM) != 0) {
- ri = ris.get(i);
- break;
- }
- }
-
- if (ri != null) {
+ final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
+ final List<ResolveInfo> ris = mContext.getPackageManager().queryIntentActivities(intent,
+ PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA);
+ if (!ris.isEmpty()) {
+ final ResolveInfo ri = ris.get(0);
String vers = ri.activityInfo.metaData != null
? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
: null;
@@ -5383,7 +5381,7 @@
int pkgUid = -1;
synchronized(this) {
try {
- pkgUid = pm.getPackageUid(packageName, userId);
+ pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -5468,7 +5466,8 @@
synchronized(this) {
int appId = -1;
try {
- appId = UserHandle.getAppId(pm.getPackageUid(packageName, 0));
+ appId = UserHandle.getAppId(
+ pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId));
} catch (RemoteException e) {
}
if (appId == -1) {
@@ -5554,7 +5553,8 @@
for (int user : users) {
int pkgUid = -1;
try {
- pkgUid = pm.getPackageUid(packageName, user);
+ pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING,
+ user);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
@@ -5948,8 +5948,8 @@
if (appId < 0 && packageName != null) {
try {
- appId = UserHandle.getAppId(
- AppGlobals.getPackageManager().getPackageUid(packageName, 0));
+ appId = UserHandle.getAppId(AppGlobals.getPackageManager()
+ .getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId));
} catch (RemoteException e) {
}
}
@@ -6591,8 +6591,10 @@
Process.establishZygoteConnectionForAbi(abi);
final String instructionSet = VMRuntime.getInstructionSet(abi);
if (!completedIsas.contains(instructionSet)) {
- if (mInstaller.markBootComplete(VMRuntime.getInstructionSet(abi)) != 0) {
- Slog.e(TAG, "Unable to mark boot complete for abi: " + abi);
+ try {
+ mInstaller.markBootComplete(VMRuntime.getInstructionSet(abi));
+ } catch (InstallerException e) {
+ Slog.e(TAG, "Unable to mark boot complete for abi: " + abi, e);
}
completedIsas.add(instructionSet);
}
@@ -6929,8 +6931,8 @@
}
try {
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
- int uid = AppGlobals.getPackageManager()
- .getPackageUid(packageName, UserHandle.getUserId(callingUid));
+ final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
+ MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
if (!UserHandle.isSameApp(callingUid, uid)) {
String msg = "Permission Denial: getIntentSender() from pid="
+ Binder.getCallingPid()
@@ -7025,8 +7027,8 @@
synchronized(this) {
PendingIntentRecord rec = (PendingIntentRecord)sender;
try {
- int uid = AppGlobals.getPackageManager()
- .getPackageUid(rec.key.packageName, UserHandle.getCallingUserId());
+ final int uid = AppGlobals.getPackageManager().getPackageUid(rec.key.packageName,
+ MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getCallingUserId());
if (!UserHandle.isSameApp(uid, Binder.getCallingUid())) {
String msg = "Permission Denial: cancelIntentSender() from pid="
+ Binder.getCallingPid()
@@ -7773,7 +7775,8 @@
int targetUid = lastTargetUid;
if (targetUid < 0 && targetPkg != null) {
try {
- targetUid = pm.getPackageUid(targetPkg, UserHandle.getUserId(callingUid));
+ targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.getUserId(callingUid));
if (targetUid < 0) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,
"Can't grant URI permission no uid for: " + targetPkg);
@@ -7911,7 +7914,7 @@
int targetUid;
final IPackageManager pm = AppGlobals.getPackageManager();
try {
- targetUid = pm.getPackageUid(targetPkg, targetUserId);
+ targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING, targetUserId);
} catch (RemoteException ex) {
return;
}
@@ -7972,7 +7975,8 @@
targetUid = needed.targetUid;
} else {
try {
- targetUid = pm.getPackageUid(targetPkg, targetUserId);
+ targetUid = pm.getPackageUid(targetPkg, MATCH_DEBUG_TRIAGED_MISSING,
+ targetUserId);
} catch (RemoteException ex) {
return null;
}
@@ -8439,8 +8443,8 @@
if (pi != null && sourcePkg.equals(pi.packageName)) {
int targetUid = -1;
try {
- targetUid = AppGlobals.getPackageManager()
- .getPackageUid(targetPkg, targetUserId);
+ targetUid = AppGlobals.getPackageManager().getPackageUid(
+ targetPkg, MATCH_UNINSTALLED_PACKAGES, targetUserId);
} catch (RemoteException e) {
}
if (targetUid != -1) {
@@ -8596,7 +8600,8 @@
final int callingUid = Binder.getCallingUid();
final IPackageManager pm = AppGlobals.getPackageManager();
try {
- final int packageUid = pm.getPackageUid(packageName, UserHandle.getUserId(callingUid));
+ final int packageUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.getUserId(callingUid));
if (packageUid != callingUid) {
throw new SecurityException(
"Package " + packageName + " does not belong to calling UID " + callingUid);
@@ -9881,7 +9886,7 @@
ParceledListSlice<ProviderInfo> slice = AppGlobals.getPackageManager()
.queryContentProviders(app.processName, app.uid,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
- | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
+ | MATCH_DEBUG_TRIAGED_MISSING);
providers = slice != null ? slice.getList() : null;
} catch (RemoteException ex) {
}
@@ -10826,6 +10831,49 @@
}
/**
+ * When a user is unlocked, we need to install encryption-unaware providers
+ * belonging to any running apps.
+ */
+ private void installEncryptionUnawareProviders(int userId) {
+ if (!StorageManager.isFileBasedEncryptionEnabled()) {
+ // TODO: eventually pivot this back to look at current user state,
+ // similar to the comment in UserManager.isUserUnlocked(), but for
+ // now, if we started apps when "unlocked" then unaware providers
+ // have already been spun up.
+ return;
+ }
+
+ synchronized (this) {
+ final int NP = mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final int NA = apps.size();
+ for (int ia = 0; ia < NA; ia++) {
+ final ProcessRecord app = apps.valueAt(ia);
+ if (app.userId != userId || app.thread == null) continue;
+
+ final int NG = app.pkgList.size();
+ for (int ig = 0; ig < NG; ig++) {
+ try {
+ final String pkgName = app.pkgList.keyAt(ig);
+ final PackageInfo pkgInfo = AppGlobals.getPackageManager()
+ .getPackageInfo(pkgName,
+ GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE, userId);
+ if (pkgInfo != null && !ArrayUtils.isEmpty(pkgInfo.providers)) {
+ for (ProviderInfo provInfo : pkgInfo.providers) {
+ Log.v(TAG, "Installing " + provInfo);
+ app.thread.scheduleInstallProvider(provInfo);
+ }
+ }
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Allows apps to retrieve the MIME type of a URI.
* If an app is in the same user as the ContentProvider, or if it is allowed to interact across
* users, then it does not need permission to access the ContentProvider.
@@ -12222,6 +12270,8 @@
sb.append(proc.processName);
sb.append(" in idle maint: pss=");
sb.append(proc.lastPss);
+ sb.append(", swapPss=");
+ sb.append(proc.lastSwapPss);
sb.append(", initialPss=");
sb.append(proc.initialIdlePss);
sb.append(", period=");
@@ -12455,19 +12505,13 @@
List<ResolveInfo> ris = null;
try {
ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0, UserHandle.USER_SYSTEM);
+ intent, null, MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
}
if (ris == null) {
return false;
}
- for (int i=ris.size()-1; i>=0; i--) {
- if ((ris.get(i).activityInfo.applicationInfo.flags
- &ApplicationInfo.FLAG_SYSTEM) == 0) {
- ris.remove(i);
- }
- }
- intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
+ intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE | Intent.FLAG_DEBUG_TRIAGED_MISSING);
ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
for (int i=0; i<ris.size(); i++) {
@@ -13987,7 +14031,7 @@
if (dumpPackage != null) {
IPackageManager pm = AppGlobals.getPackageManager();
try {
- dumpUid = pm.getPackageUid(dumpPackage, 0);
+ dumpUid = pm.getPackageUid(dumpPackage, MATCH_UNINSTALLED_PACKAGES, 0);
} catch (RemoteException e) {
}
}
@@ -14923,7 +14967,8 @@
int dumpUid = -2;
if (dumpPackage != null) {
try {
- dumpUid = mContext.getPackageManager().getPackageUidAsUser(dumpPackage, 0);
+ dumpUid = mContext.getPackageManager().getPackageUidAsUser(dumpPackage,
+ MATCH_UNINSTALLED_PACKAGES, 0);
} catch (NameNotFoundException e) {
dumpUid = -1;
}
@@ -15134,6 +15179,7 @@
pw.print("state: cur="); pw.print(ProcessList.makeProcStateString(r.curProcState));
pw.print(" set="); pw.print(ProcessList.makeProcStateString(r.setProcState));
pw.print(" lastPss="); DebugUtils.printSizeValue(pw, r.lastPss*1024);
+ pw.print(" lastSwapPss="); DebugUtils.printSizeValue(pw, r.lastSwapPss*1024);
pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, r.lastCachedPss*1024);
pw.println();
pw.print(prefix);
@@ -15287,32 +15333,35 @@
final String label;
final String shortLabel;
final long pss;
+ final long swapPss;
final int id;
final boolean hasActivities;
ArrayList<MemItem> subitems;
- public MemItem(String _label, String _shortLabel, long _pss, int _id,
+ public MemItem(String _label, String _shortLabel, long _pss, long _swapPss, int _id,
boolean _hasActivities) {
isProc = true;
label = _label;
shortLabel = _shortLabel;
pss = _pss;
+ swapPss = _swapPss;
id = _id;
hasActivities = _hasActivities;
}
- public MemItem(String _label, String _shortLabel, long _pss, int _id) {
+ public MemItem(String _label, String _shortLabel, long _pss, long _swapPss, int _id) {
isProc = false;
label = _label;
shortLabel = _shortLabel;
pss = _pss;
+ swapPss = _swapPss;
id = _id;
hasActivities = false;
}
}
static final void dumpMemItems(PrintWriter pw, String prefix, String tag,
- ArrayList<MemItem> items, boolean sort, boolean isCompact) {
+ ArrayList<MemItem> items, boolean sort, boolean isCompact, boolean dumpSwapPss) {
if (sort && !isCompact) {
Collections.sort(items, new Comparator<MemItem>() {
@Override
@@ -15330,18 +15379,24 @@
for (int i=0; i<items.size(); i++) {
MemItem mi = items.get(i);
if (!isCompact) {
- pw.printf("%s%s: %s\n", prefix, stringifyKBSize(mi.pss), mi.label);
+ if (dumpSwapPss) {
+ pw.printf("%s%s: %-60s (%s in swap)\n", prefix, stringifyKBSize(mi.pss),
+ mi.label, stringifyKBSize(mi.swapPss));
+ } else {
+ pw.printf("%s%s: %s\n", prefix, stringifyKBSize(mi.pss), mi.label);
+ }
} else if (mi.isProc) {
pw.print("proc,"); pw.print(tag); pw.print(","); pw.print(mi.shortLabel);
- pw.print(","); pw.print(mi.id); pw.print(","); pw.print(mi.pss);
+ pw.print(","); pw.print(mi.id); pw.print(","); pw.print(mi.pss); pw.print(",");
+ pw.print(dumpSwapPss ? mi.swapPss : "N/A");
pw.println(mi.hasActivities ? ",a" : ",e");
} else {
pw.print(tag); pw.print(","); pw.print(mi.shortLabel); pw.print(",");
- pw.println(mi.pss);
+ pw.println(mi.pss); pw.print(dumpSwapPss ? mi.swapPss : "N/A");
}
if (mi.subitems != null) {
- dumpMemItems(pw, prefix + " ", mi.shortLabel, mi.subitems,
- true, isCompact);
+ dumpMemItems(pw, prefix + " ", mi.shortLabel, mi.subitems,
+ true, isCompact, dumpSwapPss);
}
}
}
@@ -15470,6 +15525,8 @@
boolean isCompact = false;
boolean localOnly = false;
boolean packages = false;
+ boolean isCheckinRequest = false;
+ boolean dumpSwapPss = false;
int opti = 0;
while (opti < args.length) {
@@ -15482,6 +15539,7 @@
dumpDetails = true;
dumpFullDetails = true;
dumpDalvik = true;
+ dumpSwapPss = true;
} else if ("-d".equals(opt)) {
dumpDalvik = true;
} else if ("-c".equals(opt)) {
@@ -15489,22 +15547,29 @@
} else if ("-s".equals(opt)) {
dumpDetails = true;
dumpSummaryOnly = true;
+ } else if ("-S".equals(opt)) {
+ dumpSwapPss = true;
} else if ("--oom".equals(opt)) {
oomOnly = true;
} else if ("--local".equals(opt)) {
localOnly = true;
} else if ("--package".equals(opt)) {
packages = true;
+ } else if ("--checkin".equals(opt)) {
+ isCheckinRequest = true;
+
} else if ("-h".equals(opt)) {
pw.println("meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]");
pw.println(" -a: include all available information for each process.");
pw.println(" -d: include dalvik details.");
pw.println(" -c: dump in a compact machine-parseable representation.");
pw.println(" -s: dump only summary of application memory usage.");
+ pw.println(" -S: dump also SwapPss.");
pw.println(" --oom: only show processes organized by oom adj.");
pw.println(" --local: only collect details locally, don't call process.");
pw.println(" --package: interpret process arg as package, dumping all");
pw.println(" processes that have loaded that package.");
+ pw.println(" --checkin: dump data for a checkin");
pw.println("If [process] is specified it can be the name or ");
pw.println("pid of a specific process to dump.");
return;
@@ -15513,7 +15578,6 @@
}
}
- final boolean isCheckinRequest = scanArgs(args, "--checkin");
long uptime = SystemClock.uptimeMillis();
long realtime = SystemClock.elapsedRealtime();
final long[] tmpLong = new long[1];
@@ -15585,18 +15649,28 @@
ArrayList<MemItem> procMems = new ArrayList<MemItem>();
final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
long nativePss = 0;
+ long nativeSwapPss = 0;
long dalvikPss = 0;
+ long dalvikSwapPss = 0;
long[] dalvikSubitemPss = dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
EmptyArray.LONG;
+ long[] dalvikSubitemSwapPss = dumpDalvik ? new long[Debug.MemoryInfo.NUM_DVK_STATS] :
+ EmptyArray.LONG;
long otherPss = 0;
+ long otherSwapPss = 0;
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
+ long[] miscSwapPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
+ long oomSwapPss[] = new long[DUMP_MEM_OOM_LABEL.length];
ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])
new ArrayList[DUMP_MEM_OOM_LABEL.length];
long totalPss = 0;
+ long totalSwapPss = 0;
long cachedPss = 0;
+ long cachedSwapPss = 0;
+ boolean hasSwapPss = false;
Debug.MemoryInfo mi = null;
for (int i = procs.size() - 1 ; i >= 0 ; i--) {
@@ -15620,6 +15694,7 @@
}
if (dumpDetails || (!brief && !oomOnly)) {
Debug.getMemoryInfo(pid, mi);
+ hasSwapPss = mi.hasSwappedOutPss;
} else {
mi.dalvikPss = (int)Debug.getPss(pid, tmpLong, null);
mi.dalvikPrivateDirty = (int)tmpLong[0];
@@ -15647,6 +15722,7 @@
final long myTotalPss = mi.getTotalPss();
final long myTotalUss = mi.getTotalUss();
+ final long myTotalSwapPss = mi.getTotalSwappedOutPss();
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
@@ -15657,32 +15733,43 @@
if (!isCheckinRequest && mi != null) {
totalPss += myTotalPss;
+ totalSwapPss += myTotalSwapPss;
MemItem pssItem = new MemItem(r.processName + " (pid " + pid +
- (hasActivities ? " / activities)" : ")"),
- r.processName, myTotalPss, pid, hasActivities);
+ (hasActivities ? " / activities)" : ")"), r.processName, myTotalPss,
+ myTotalSwapPss, pid, hasActivities);
procMems.add(pssItem);
procMemsMap.put(pid, pssItem);
nativePss += mi.nativePss;
+ nativeSwapPss += mi.nativeSwappedOutPss;
dalvikPss += mi.dalvikPss;
+ dalvikSwapPss += mi.dalvikSwappedOutPss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemSwapPss[j] +=
+ mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
}
otherPss += mi.otherPss;
+ otherSwapPss += mi.otherSwappedOutPss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
miscPss[j] += mem;
otherPss -= mem;
+ mem = mi.getOtherSwappedOutPss(j);
+ miscSwapPss[j] += mem;
+ otherSwapPss -= mem;
}
if (oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
cachedPss += myTotalPss;
+ cachedSwapPss += myTotalSwapPss;
}
for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) {
if (oomAdj <= DUMP_MEM_OOM_ADJ[oomIndex]
|| oomIndex == (oomPss.length-1)) {
oomPss[oomIndex] += myTotalPss;
+ oomSwapPss[oomIndex] += myTotalSwapPss;
if (oomProcs[oomIndex] == null) {
oomProcs[oomIndex] = new ArrayList<MemItem>();
}
@@ -15717,26 +15804,35 @@
}
final long myTotalPss = mi.getTotalPss();
+ final long myTotalSwapPss = mi.getTotalSwappedOutPss();
totalPss += myTotalPss;
nativeProcTotalPss += myTotalPss;
MemItem pssItem = new MemItem(st.name + " (pid " + st.pid + ")",
- st.name, myTotalPss, st.pid, false);
+ st.name, myTotalPss, mi.getSummaryTotalSwapPss(), st.pid, false);
procMems.add(pssItem);
nativePss += mi.nativePss;
+ nativeSwapPss += mi.nativeSwappedOutPss;
dalvikPss += mi.dalvikPss;
+ dalvikSwapPss += mi.dalvikSwappedOutPss;
for (int j=0; j<dalvikSubitemPss.length; j++) {
- dalvikSubitemPss[j] += mi.getOtherPss(
- Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemPss[j] += mi.getOtherPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
+ dalvikSubitemSwapPss[j] +=
+ mi.getOtherSwappedOutPss(Debug.MemoryInfo.NUM_OTHER_STATS + j);
}
otherPss += mi.otherPss;
+ otherSwapPss += mi.otherSwappedOutPss;
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
long mem = mi.getOtherPss(j);
miscPss[j] += mem;
otherPss -= mem;
+ mem = mi.getOtherSwappedOutPss(j);
+ miscSwapPss[j] += mem;
+ otherSwapPss -= mem;
}
oomPss[0] += myTotalPss;
+ oomSwapPss[0] += myTotalSwapPss;
if (oomProcs[0] == null) {
oomProcs[0] = new ArrayList<MemItem>();
}
@@ -15747,21 +15843,23 @@
ArrayList<MemItem> catMems = new ArrayList<MemItem>();
- catMems.add(new MemItem("Native", "Native", nativePss, -1));
- final MemItem dalvikItem = new MemItem("Dalvik", "Dalvik", dalvikPss, -2);
+ catMems.add(new MemItem("Native", "Native", nativePss, nativeSwapPss, -1));
+ final MemItem dalvikItem =
+ new MemItem("Dalvik", "Dalvik", dalvikPss, dalvikSwapPss, -2);
if (dalvikSubitemPss.length > 0) {
dalvikItem.subitems = new ArrayList<MemItem>();
for (int j=0; j<dalvikSubitemPss.length; j++) {
final String name = Debug.MemoryInfo.getOtherLabel(
Debug.MemoryInfo.NUM_OTHER_STATS + j);
- dalvikItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j], j));
+ dalvikItem.subitems.add(new MemItem(name, name, dalvikSubitemPss[j],
+ dalvikSubitemSwapPss[j], j));
}
}
catMems.add(dalvikItem);
- catMems.add(new MemItem("Unknown", "Unknown", otherPss, -3));
+ catMems.add(new MemItem("Unknown", "Unknown", otherPss, otherSwapPss, -3));
for (int j=0; j<Debug.MemoryInfo.NUM_OTHER_STATS; j++) {
String label = Debug.MemoryInfo.getOtherLabel(j);
- catMems.add(new MemItem(label, label, miscPss[j], j));
+ catMems.add(new MemItem(label, label, miscPss[j], miscSwapPss[j], j));
}
ArrayList<MemItem> oomMems = new ArrayList<MemItem>();
@@ -15769,30 +15867,31 @@
if (oomPss[j] != 0) {
String label = isCompact ? DUMP_MEM_OOM_COMPACT_LABEL[j]
: DUMP_MEM_OOM_LABEL[j];
- MemItem item = new MemItem(label, label, oomPss[j],
+ MemItem item = new MemItem(label, label, oomPss[j], oomSwapPss[j],
DUMP_MEM_OOM_ADJ[j]);
item.subitems = oomProcs[j];
oomMems.add(item);
}
}
+ dumpSwapPss = dumpSwapPss && hasSwapPss && totalSwapPss != 0;
if (!brief && !oomOnly && !isCompact) {
pw.println();
pw.println("Total PSS by process:");
- dumpMemItems(pw, " ", "proc", procMems, true, isCompact);
+ dumpMemItems(pw, " ", "proc", procMems, true, isCompact, dumpSwapPss);
pw.println();
}
if (!isCompact) {
pw.println("Total PSS by OOM adjustment:");
}
- dumpMemItems(pw, " ", "oom", oomMems, false, isCompact);
+ dumpMemItems(pw, " ", "oom", oomMems, false, isCompact, dumpSwapPss);
if (!brief && !oomOnly) {
PrintWriter out = categoryPw != null ? categoryPw : pw;
if (!isCompact) {
out.println();
out.println("Total PSS by category:");
}
- dumpMemItems(out, " ", "cat", catMems, true, isCompact);
+ dumpMemItems(out, " ", "cat", catMems, true, isCompact, dumpSwapPss);
}
if (!isCompact) {
pw.println();
@@ -17121,7 +17220,7 @@
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
int callingUid, int[] users) {
// TODO: come back and remove this assumption to triage all broadcasts
- int pmFlags = STOCK_PM_FLAGS | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+ int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
List<ResolveInfo> receivers = null;
try {
@@ -18298,9 +18397,12 @@
* dialog / global actions also might want different behaviors.
*/
private static final boolean shouldShowDialogs(Configuration config) {
- return !(config.keyboard == Configuration.KEYBOARD_NOKEYS
- && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH
- && config.navigation == Configuration.NAVIGATION_NONAV);
+ final boolean inputMethodExists = !(config.keyboard == Configuration.KEYBOARD_NOKEYS
+ && config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH
+ && config.navigation == Configuration.NAVIGATION_NONAV);
+ final boolean uiIsNotCarType = !((config.uiMode & Configuration.UI_MODE_TYPE_MASK)
+ == Configuration.UI_MODE_TYPE_CAR);
+ return inputMethodExists && uiIsNotCarType;
}
@Override
@@ -19112,8 +19214,10 @@
/**
* Record new PSS sample for a process.
*/
- void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long now) {
- EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024);
+ void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long swapPss,
+ long now) {
+ EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
+ swapPss * 1024);
proc.lastPssTime = now;
proc.baseProcessTracker.addPss(pss, uss, true, proc.pkgList);
if (DEBUG_PSS) Slog.d(TAG_PSS,
@@ -19123,8 +19227,10 @@
proc.initialIdlePss = pss;
}
proc.lastPss = pss;
+ proc.lastSwapPss = swapPss;
if (procState >= ActivityManager.PROCESS_STATE_HOME) {
proc.lastCachedPss = pss;
+ proc.lastCachedSwapPss = swapPss;
}
final SparseArray<Pair<Long, String>> watchUids
@@ -19560,7 +19666,7 @@
// states, which well tend to give noisy data.
long start = SystemClock.uptimeMillis();
long pss = Debug.getPss(app.pid, mTmpLong, null);
- recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], now);
+ recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], mTmpLong[1], now);
mPendingPssProcesses.remove(app);
Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
+ " to " + app.curProcState + ": "
@@ -21076,7 +21182,7 @@
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
try {
- pkgUid = pm.getPackageUid(packageName, userId);
+ pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 4fb87c3..eb0945bf 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -171,7 +171,9 @@
boolean stopped; // is activity pause finished?
boolean delayedResume; // not yet resumed because of stopped app switches?
boolean finishing; // activity in pending finish list?
- boolean configDestroy; // need to destroy due to config change?
+ boolean deferRelaunchUntilPaused; // relaunch of activity is being deferred until pause is
+ // completed
+ boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
int configChangeFlags; // which config values have changed
boolean keysPaused; // has key dispatching been paused for it?
int launchMode; // the launch mode activity attribute.
@@ -184,9 +186,9 @@
boolean immersive; // immersive mode (don't interrupt if possible)
boolean forceNewConfig; // force re-create with new config next time
int launchCount; // count of launches since last state
- long lastLaunchTime; // time of last lauch of this activity
+ long lastLaunchTime; // time of last launch of this activity
boolean isVrActivity; // is the activity running in VR mode?
- ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>();
+ ArrayList<ActivityContainer> mChildContainers = new ArrayList<>();
String stringName; // for caching of toString().
@@ -341,8 +343,8 @@
else TimeUtils.formatDuration(lastVisibleTime, now, pw);
pw.println();
}
- if (configDestroy || configChangeFlags != 0) {
- pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
+ if (deferRelaunchUntilPaused || configChangeFlags != 0) {
+ pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
pw.print(" configChangeFlags=");
pw.println(Integer.toHexString(configChangeFlags));
}
@@ -551,7 +553,7 @@
stopped = false;
delayedResume = false;
finishing = false;
- configDestroy = false;
+ deferRelaunchUntilPaused = false;
keysPaused = false;
inHistory = false;
visible = false;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index e123dbd..c112843 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1088,7 +1088,7 @@
if (r.finishing) {
r.clearOptionsLocked();
} else {
- if (r.configDestroy) {
+ if (r.deferRelaunchUntilPaused) {
destroyActivityLocked(r, true, "stop-config");
mStackSupervisor.resumeFocusedStackTopActivityLocked();
} else {
@@ -1114,14 +1114,11 @@
if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
"Complete pause, no longer waiting: " + prev);
}
- if (prev.configDestroy) {
- // The previous is being paused because the configuration
- // is changing, which means it is actually stopping...
- // To juggle the fact that we are also starting a new
- // instance right now, we need to first completely stop
- // the current instance before starting the new one.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Destroying after pause: " + prev);
- destroyActivityLocked(prev, true, "pause-config");
+ if (prev.deferRelaunchUntilPaused) {
+ // Complete the deferred relaunch that was waiting for pause to complete.
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
+ relaunchActivityLocked(prev, prev.configChangeFlags, false,
+ prev.preserveWindowOnDeferredRelaunch);
} else if (wasStopping) {
// We are also stopping, the stop request must have gone soon after the pause.
// We can't clobber it, because the stop confirmation will not be handled.
@@ -2318,11 +2315,12 @@
ActivityStack lastStack = mStackSupervisor.getLastStack();
final boolean fromHome = lastStack.isHomeStack();
if (!isHomeStack() && (fromHome || topTask() != task)) {
- task.setTaskToReturnTo(fromHome
- ? lastStack.topTask() == null
- ? HOME_ACTIVITY_TYPE
- : lastStack.topTask().taskType
- : APPLICATION_ACTIVITY_TYPE);
+ int returnToType = APPLICATION_ACTIVITY_TYPE;
+ if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
+ returnToType = lastStack.topTask() == null
+ ? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
+ }
+ task.setTaskToReturnTo(returnToType);
}
} else {
task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
@@ -2972,7 +2970,7 @@
r.stopped = true;
if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
r.state = ActivityState.STOPPED;
- if (r.configDestroy) {
+ if (r.deferRelaunchUntilPaused) {
destroyActivityLocked(r, true, "stop-except");
}
}
@@ -3368,9 +3366,9 @@
try {
ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
destIntent.getComponent(), 0, srec.userId);
- int res = mService.mActivityStarter.startActivityLocked(srec.app.thread, destIntent,
- null /*ephemeralIntent*/, null, aInfo, null /*rInfo*/, null, null,
- parent.appToken, null, 0, -1, parent.launchedFromUid,
+ int res = mService.mActivityStarter.startActivityLocked(srec.app.thread,
+ destIntent, null /*ephemeralIntent*/, null, aInfo, null /*rInfo*/, null,
+ null, parent.appToken, null, 0, -1, parent.launchedFromUid,
parent.launchedFromPackage, -1, parent.launchedFromUid, 0, null,
false, true, null, null, null);
foundParentInTask = res == ActivityManager.START_SUCCESS;
@@ -3403,7 +3401,7 @@
}
mService.resetFocusedActivityIfNeededLocked(r);
- r.configDestroy = false;
+ r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
if (setState) {
@@ -4175,38 +4173,33 @@
r.configChangeFlags |= changes;
r.startFreezingScreenLocked(r.app, globalChanges);
r.forceNewConfig = false;
+ preserveWindow &= isResizeOnlyChange(changes);
if (r.app == null || r.app.thread == null) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Config is destroying non-running " + r);
destroyActivityLocked(r, true, "config");
} else if (r.state == ActivityState.PAUSING) {
- // A little annoying: we are waiting for this activity to
- // finish pausing. Let's not do anything now, but just
- // flag that it needs to be restarted when done pausing.
+ // A little annoying: we are waiting for this activity to finish pausing. Let's not
+ // do anything now, but just flag that it needs to be restarted when done pausing.
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Config is skipping already pausing " + r);
- r.configDestroy = true;
+ r.deferRelaunchUntilPaused = true;
+ r.preserveWindowOnDeferredRelaunch = preserveWindow;
return true;
} else if (r.state == ActivityState.RESUMED) {
- // Try to optimize this case: the configuration is changing
- // and we need to restart the top, resumed activity.
- // Instead of doing the normal handshaking, just say
+ // Try to optimize this case: the configuration is changing and we need to restart
+ // the top, resumed activity. Instead of doing the normal handshaking, just say
// "restart!".
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Config is relaunching resumed " + r);
- relaunchActivityLocked(r, r.configChangeFlags, true,
- preserveWindow && isResizeOnlyChange(changes));
- r.configChangeFlags = 0;
+ relaunchActivityLocked(r, r.configChangeFlags, true, preserveWindow);
} else {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Config is relaunching non-resumed " + r);
- relaunchActivityLocked(r, r.configChangeFlags, false,
- preserveWindow && isResizeOnlyChange(changes));
- r.configChangeFlags = 0;
+ relaunchActivityLocked(r, r.configChangeFlags, false, preserveWindow);
}
- // All done... tell the caller we weren't able to keep this
- // activity around.
+ // All done... tell the caller we weren't able to keep this activity around.
return false;
}
@@ -4298,6 +4291,7 @@
private void relaunchActivityLocked(
ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) {
if (mService.mSuppressResizeConfigChanges && preserveWindow) {
+ r.configChangeFlags = 0;
return;
}
@@ -4341,6 +4335,8 @@
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
r.state = ActivityState.PAUSED;
}
+
+ r.configChangeFlags = 0;
}
boolean willActivityBeVisibleLocked(IBinder token) {
@@ -4757,8 +4753,7 @@
}
void addConfigOverride(ActivityRecord r, TaskRecord task) {
- final Rect bounds = task.getLaunchBounds();
- task.updateOverrideConfiguration(bounds);
+ final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
@@ -4814,10 +4809,9 @@
}
private void setAppTask(ActivityRecord r, TaskRecord task) {
- final Rect bounds = task.getLaunchBounds();
- task.updateOverrideConfiguration(bounds);
+ final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
mWindowManager.setAppTask(
- r.appToken, task.taskId, mStackId, task.getLaunchBounds(), task.mOverrideConfig);
+ r.appToken, task.taskId, mStackId, bounds, task.mOverrideConfig);
mWindowManager.setTaskResizeable(task.taskId, task.mResizeable);
r.taskConfigOverride = task.mOverrideConfig;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4672023..022b60b 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1673,7 +1673,7 @@
if (task.mResizeable && options != null) {
int stackId = options.getLaunchStackId();
if (canUseActivityOptionsLaunchBounds(options, stackId)) {
- Rect bounds = options.getLaunchBounds();
+ final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
task.updateOverrideConfiguration(bounds);
if (stackId == INVALID_STACK_ID) {
stackId = task.getLaunchStackId();
@@ -1841,6 +1841,7 @@
// can have the right fullscreen state.
bounds = null;
}
+ bounds = TaskRecord.validateBounds(bounds);
mTmpBounds.clear();
mTmpConfigs.clear();
@@ -1857,8 +1858,8 @@
fitWithinBounds(tempRect2, bounds);
task.updateOverrideConfiguration(tempRect2);
} else {
- task.updateOverrideConfiguration(tempTaskBounds != null
- ? tempTaskBounds : bounds);
+ task.updateOverrideConfiguration(
+ tempTaskBounds != null ? tempTaskBounds : bounds);
}
}
@@ -1973,6 +1974,7 @@
// Nothing to do here...
return true;
}
+ bounds = TaskRecord.validateBounds(bounds);
if (!mWindowManager.isValidTaskId(task.taskId)) {
// Task doesn't exist in window manager yet (e.g. was restored from recents).
@@ -2722,7 +2724,7 @@
for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord s = mStoppingActivities.get(activityNdx);
final boolean waitingVisible = mWaitingVisibleActivities.contains(s);
- if (DEBUG_ALL) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
+ if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
+ " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
if (waitingVisible && nowVisible) {
mWaitingVisibleActivities.remove(s);
@@ -2732,12 +2734,12 @@
// so get rid of it. Otherwise, we need to go through the
// normal flow and hide it once we determine that it is
// hidden by the activities in front of it.
- if (DEBUG_ALL) Slog.v(TAG, "Before stopping, can hide: " + s);
+ if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s);
mWindowManager.setAppVisibility(s.appToken, false);
}
}
if ((!waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
- if (DEBUG_ALL) Slog.v(TAG, "Ready to stop: " + s);
+ if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s);
if (stops == null) {
stops = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index f712613..6fa8950 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -32,12 +32,12 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
-import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
+import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -45,6 +45,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
@@ -63,8 +64,8 @@
import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
+import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AppGlobals;
@@ -529,7 +530,10 @@
// switch... just dismiss the keyguard now, because we
// probably want to see whatever is behind it.
mSupervisor.notifyActivityDrawnForKeyguard();
+ } else {
+ launchRecentsAppIfNeeded(stack);
}
+
return err;
}
@@ -863,6 +867,28 @@
intentActivity.task.setIntent(mStartActivity);
}
+ // This code path leads to delivering a new intent, we want to make sure we schedule it
+ // as the first operation, in case the activity will be resumed as a result of later
+ // operations.
+ if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
+ || mLaunchSingleInstance || mLaunchSingleTask) {
+ // In this situation we want to remove all activities from the task up to the one
+ // being started. In most cases this means we are resetting the task to its initial
+ // state.
+ final ActivityRecord top = intentActivity.task.performClearTaskLocked(
+ mStartActivity, mLaunchFlags);
+ if (top != null) {
+ if (top.frontOfTask) {
+ // Activity aliases may mean we use different intents for the top activity,
+ // so make sure the task now has the identity of the new intent.
+ top.task.setIntent(mStartActivity);
+ }
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
+ top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
+ mStartActivity.launchedFromPackage);
+ }
+ }
+
intentActivity = setTargetStackAndMoveToFrontIfNeeded(intentActivity);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -904,7 +930,7 @@
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
@@ -1006,6 +1032,16 @@
return START_SUCCESS;
}
+ private void launchRecentsAppIfNeeded(ActivityStack topStack) {
+ if (topStack.mStackId == HOME_STACK_ID && mTargetStack.mStackId == DOCKED_STACK_ID) {
+ // We launch an activity while being in home stack, which means either launcher or
+ // recents into docked stack. We don't want the launched activity to be alone in a
+ // docked stack, so we want to immediately launch recents too.
+ if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
+ mWindowManager.showRecentApps();
+ }
+ }
+
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
@@ -1305,20 +1341,9 @@
mReuseTask.setIntent(mStartActivity);
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| mLaunchSingleInstance || mLaunchSingleTask) {
- // In this situation we want to remove all activities from the task up to the one
- // being started. In most cases this means we are resetting the task to its initial
- // state.
ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
mLaunchFlags);
- if (top != null) {
- if (top.frontOfTask) {
- // Activity aliases may mean we use different intents for the top activity,
- // so make sure the task now has the identity of the new intent.
- top.task.setIntent(mStartActivity);
- }
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity, top.task);
- top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
- } else {
+ if (top == null) {
// A special case: we need to start the activity because it is not currently
// running, and the caller has asked to clear the current task to have this
// activity at the top.
@@ -1343,7 +1368,7 @@
// desires.
if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity,
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
intentActivity.task);
if (intentActivity.frontOfTask) {
intentActivity.task.setIntent(mStartActivity);
@@ -1439,7 +1464,7 @@
ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
mKeepCurTransition = true;
if (top != null) {
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// For paranoia, make sure we have correctly resumed the top activity.
mTargetStack.mLastPausedActivity = null;
@@ -1458,7 +1483,7 @@
final TaskRecord task = top.task;
task.moveActivityToFrontLocked(top);
top.updateOptionsLocked(mOptions);
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, mStartActivity, task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
mTargetStack.mLastPausedActivity = null;
if (mDoResume) {
@@ -1495,7 +1520,7 @@
if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask) {
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
+ ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
@@ -1714,7 +1739,7 @@
if (options != null && (r.isResizeable() || (inTask != null && inTask.mResizeable))) {
if (mSupervisor.canUseActivityOptionsLaunchBounds(
options, options.getLaunchStackId())) {
- newBounds = options.getLaunchBounds();
+ newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
}
}
return newBounds;
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 0397553..f2e8d09 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -100,6 +100,6 @@
30045 am_pre_boot (User|1|5),(Package|3)
# Report collection of global memory state
-30046 am_meminfo (CachedKb|2|2),(FreeKb|2|2),(ZramKb|2|2),(KernelKb|2|2),(NativeKb|2|2)
+30046 am_meminfo (Cached|2|2),(Free|2|2),(Zram|2|2),(Kernel|2|2),(Native|2|2)
# Report collection of memory used by a process
-30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(PssKb|2|2),(UssKb|2|2)
+30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2)
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 4bfe300..b4aa4cf 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -82,7 +82,9 @@
long lastStateTime; // Last time setProcState changed
long initialIdlePss; // Initial memory pss of process for idle maintenance.
long lastPss; // Last computed memory pss.
+ long lastSwapPss; // Last computed SwapPss.
long lastCachedPss; // Last computed pss when in cached state.
+ long lastCachedSwapPss; // Last computed SwapPss when in cached state.
int maxAdj; // Maximum OOM adjustment for this process
int curRawAdj; // Current OOM unlimited adjustment for this process
int setRawAdj; // Last set OOM unlimited adjustment for this process
@@ -257,7 +259,9 @@
pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
pw.print(" lruSeq="); pw.print(lruSeq);
pw.print(" lastPss="); DebugUtils.printSizeValue(pw, lastPss*1024);
+ pw.print(" lastSwapPss="); DebugUtils.printSizeValue(pw, lastSwapPss*1024);
pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, lastCachedPss*1024);
+ pw.print(" lastCachedSwapPss="); DebugUtils.printSizeValue(pw, lastCachedSwapPss*1024);
pw.println();
pw.print(prefix); pw.print("cached="); pw.print(cached);
pw.print(" empty="); pw.println(empty);
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index c63eaac..52d23cf 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -130,9 +130,11 @@
ActivityInfo ai = tmpAvailActCache.get(task.realActivity);
if (ai == null) {
try {
+ // At this first cut, we're only interested in
+ // activities that are fully runnable based on
+ // current system state.
ai = pm.getActivityInfo(task.realActivity,
- PackageManager.GET_UNINSTALLED_PACKAGES
- | PackageManager.GET_DISABLED_COMPONENTS, user);
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user);
} catch (RemoteException e) {
// Will never happen.
continue;
@@ -150,8 +152,7 @@
if (app == null) {
try {
app = pm.getApplicationInfo(task.realActivity.getPackageName(),
- PackageManager.GET_UNINSTALLED_PACKAGES
- | PackageManager.GET_DISABLED_COMPONENTS, user);
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, user);
} catch (RemoteException e) {
// Will never happen.
continue;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ae987e6..f7e30c0 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
@@ -1310,6 +1311,20 @@
return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
}
+ Rect updateOverrideConfigurationFromLaunchBounds() {
+ final Rect bounds = validateBounds(getLaunchBounds());
+ updateOverrideConfiguration(bounds);
+ return bounds;
+ }
+
+ static Rect validateBounds(Rect bounds) {
+ if (bounds != null && bounds.isEmpty()) {
+ Slog.wtf(TAG, "Received strange task bounds: " + bounds, new Throwable());
+ return null;
+ }
+ return bounds;
+ }
+
private void reportMultiWindowModeChange() {
for (int i = mActivities.size() - 1; i >= 0; i--) {
final ActivityRecord r = mActivities.get(i);
@@ -1386,17 +1401,20 @@
/** Returns the bounds that should be used to launch this task. */
Rect getLaunchBounds() {
- final int stackId = stack.mStackId;
-
// If we're over lockscreen, forget about stack bounds and use fullscreen.
if (mService.mLockScreenShown == LOCK_SCREEN_SHOWN) {
return null;
}
- if (stack == null
- || stackId == HOME_STACK_ID
- || stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
- return (mResizeable && stack != null) ? stack.mBounds : null;
+ if (stack == null) {
+ return null;
+ }
+
+ final int stackId = stack.mStackId;
+ if (stackId == HOME_STACK_ID
+ || stackId == FULLSCREEN_WORKSPACE_STACK_ID
+ || (stackId == DOCKED_STACK_ID && !mResizeable)) {
+ return mResizeable ? stack.mBounds : null;
} else if (!StackId.persistTaskBounds(stackId)) {
return stack.mBounds;
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 7172859..56757ca 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -143,6 +143,8 @@
private volatile UserManagerService mUserManager;
+ private final LockPatternUtils mLockPatternUtils;
+
UserController(ActivityManagerService service) {
mService = service;
mHandler = mService.mHandler;
@@ -150,6 +152,7 @@
final UserState uss = new UserState(UserHandle.SYSTEM);
mStartedUsers.put(UserHandle.USER_SYSTEM, uss);
mUserLru.add(UserHandle.USER_SYSTEM);
+ mLockPatternUtils = new LockPatternUtils(mService.mContext);
updateStartedUserArrayLocked();
}
@@ -1294,13 +1297,12 @@
* intercept activity launches for work apps when the Work Challenge is present.
*/
boolean shouldConfirmCredentials(int userId) {
- final UserInfo user = getUserInfo(userId);
- if (!user.isManagedProfile() || !LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+ if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
return false;
}
final KeyguardManager km = (KeyguardManager) mService.mContext
.getSystemService(KEYGUARD_SERVICE);
- return km.isDeviceLocked(user.id);
+ return km.isDeviceLocked(userId);
}
void dump(PrintWriter pw, boolean dumpAll) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 40d01e7..9331dd8 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -58,10 +58,12 @@
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioPort;
+import android.media.AudioRecordConfiguration;
import android.media.AudioRoutesInfo;
import android.media.IAudioFocusDispatcher;
import android.media.IAudioRoutesObserver;
import android.media.IAudioService;
+import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
import android.media.IVolumeController;
import android.media.MediaPlayer;
@@ -220,6 +222,7 @@
private static final int MSG_UNMUTE_STREAM = 24;
private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
private static final int MSG_INDICATE_SYSTEM_READY = 26;
+ private static final int MSG_PERSIST_MASTER_MONO = 27;
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -705,6 +708,8 @@
LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
+
+ mRecordMonitor.initMonitor();
}
public void systemReady() {
@@ -820,6 +825,12 @@
streamState.applyAllVolumes();
}
+ // Restore mono mode
+ final boolean masterMono = System.getIntForUser(
+ mContentResolver, System.MASTER_MONO,
+ 0 /* default */, UserHandle.USER_CURRENT) == 1;
+ AudioSystem.setMasterMono(masterMono);
+
// Restore ringer mode
setRingerModeInt(getRingerModeInternal(), false);
@@ -1079,6 +1090,14 @@
}
AudioSystem.muteMicrophone(microphoneMute);
+ final boolean masterMono = System.getIntForUser(
+ cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
+ if (DEBUG_VOL) {
+ Log.d(TAG, String.format("Master mono %b, user=%d", masterMono, currentUser));
+ }
+ AudioSystem.setMasterMono(masterMono);
+ broadcastMasterMonoStatus(masterMono);
+
// Each stream will read its own persisted settings
// Broadcast the sticky intents
@@ -1835,6 +1854,52 @@
userId);
}
+ /** @hide */
+ public boolean isMasterMono() {
+ return AudioSystem.getMasterMono();
+ }
+
+ /** @hide */
+ public void setMasterMono(boolean mono, String callingPackage, int userId) {
+ int callingUid = Binder.getCallingUid();
+ // If we are being called by the system check for user we are going to change
+ // so we handle user restrictions correctly.
+ if (callingUid == android.os.Process.SYSTEM_UID) {
+ callingUid = UserHandle.getUid(userId, UserHandle.getAppId(callingUid));
+ }
+
+ if (userId != UserHandle.getCallingUserId() &&
+ mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+ != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ if (DEBUG_VOL) {
+ Log.d(TAG, String.format("Master mono %b, user=%d", mono, userId));
+ }
+
+ if (getCurrentUserId() == userId) {
+ if (mono != AudioSystem.getMasterMono()) {
+ AudioSystem.setMasterMono(mono);
+ // Post a persist master mono msg
+ sendMsg(mAudioHandler, MSG_PERSIST_MASTER_MONO, SENDMSG_REPLACE, mono ? 1
+ : 0 /* value */, userId, null /* obj */, 0 /* delay */);
+ // notify apps and settings
+ broadcastMasterMonoStatus(mono);
+ }
+ } else {
+ // Post a persist master mono msg
+ sendMsg(mAudioHandler, MSG_PERSIST_MASTER_MONO, SENDMSG_REPLACE, mono ? 1
+ : 0 /* value */, userId, null /* obj */, 0 /* delay */);
+ }
+ }
+
+ private void broadcastMasterMonoStatus(boolean mono) {
+ Intent intent = new Intent(AudioManager.MASTER_MONO_CHANGED_ACTION);
+ intent.putExtra(AudioManager.EXTRA_MASTER_MONO, mono);
+ sendBroadcastToAll(intent);
+ }
+
/** @see AudioManager#getStreamVolume(int) */
public int getStreamVolume(int streamType) {
ensureValidStreamType(streamType);
@@ -4534,6 +4599,13 @@
case MSG_DYN_POLICY_MIX_STATE_UPDATE:
onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
break;
+
+ case MSG_PERSIST_MASTER_MONO:
+ Settings.System.putIntForUser(mContentResolver,
+ Settings.System.MASTER_MONO,
+ msg.arg1 /* value */,
+ msg.arg2 /* userHandle */);
+ break;
}
}
}
@@ -6097,7 +6169,7 @@
}
//======================
- // Audio policy callback from AudioSystem
+ // Audio policy callbacks from AudioSystem for dynamic policies
//======================
private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
new AudioSystem.DynamicPolicyCallback() {
@@ -6126,7 +6198,23 @@
}
}
}
+ }
+ //======================
+ // Audio policy callbacks from AudioSystem for recording configuration updates
+ //======================
+ private final RecordingActivityMonitor mRecordMonitor = new RecordingActivityMonitor();
+
+ public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
+ mRecordMonitor.registerRecordingCallback(rcdb);
+ }
+
+ public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
+ mRecordMonitor.unregisterRecordingCallback(rcdb);
+ }
+
+ public AudioRecordConfiguration[] getActiveRecordConfigurations() {
+ return mRecordMonitor.getActiveRecordConfigurations();
}
//======================
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
new file mode 100644
index 0000000..5806f3f
--- /dev/null
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -0,0 +1,169 @@
+/*
+ * 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.server.audio;
+
+import android.media.AudioManager;
+import android.media.AudioRecordConfiguration;
+import android.media.AudioSystem;
+import android.media.IRecordingConfigDispatcher;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Class to receive and dispatch updates from AudioSystem about recording configurations.
+ */
+public final class RecordingActivityMonitor implements AudioSystem.AudioRecordingCallback {
+
+ public final static String TAG = "AudioService.RecordingActivityMonitor";
+
+ private ArrayList<RecMonitorClient> mClients = new ArrayList<RecMonitorClient>();
+
+ private HashMap<Integer, AudioRecordConfiguration> mRecordConfigs =
+ new HashMap<Integer, AudioRecordConfiguration>();
+
+ RecordingActivityMonitor() {
+ RecMonitorClient.sMonitor = this;
+ }
+
+ /**
+ * Implementation of android.media.AudioSystem.AudioRecordingCallback
+ */
+ public void onRecordingConfigurationChanged(int event, int session, int source) {
+ if (updateSnapshot(event, session, source)) {
+ final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
+ synchronized(mClients) {
+ while (clientIterator.hasNext()) {
+ try {
+ clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e);
+ }
+ }
+ }
+ }
+ }
+
+ void initMonitor() {
+ AudioSystem.setRecordingCallback(this);
+ }
+
+ void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
+ if (rcdb == null) {
+ return;
+ }
+ synchronized(mClients) {
+ final RecMonitorClient rmc = new RecMonitorClient(rcdb);
+ if (rmc.init()) {
+ mClients.add(rmc);
+ }
+ }
+ }
+
+ void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
+ if (rcdb == null) {
+ return;
+ }
+ synchronized(mClients) {
+ final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
+ while (clientIterator.hasNext()) {
+ RecMonitorClient rmc = clientIterator.next();
+ if (rcdb.equals(rmc.mDispatcherCb)) {
+ rmc.release();
+ clientIterator.remove();
+ break;
+ }
+ }
+ }
+ }
+
+ AudioRecordConfiguration[] getActiveRecordConfigurations() {
+ synchronized(mRecordConfigs) {
+ return mRecordConfigs.values().toArray(new AudioRecordConfiguration[0]);
+ }
+ }
+
+ /**
+ * Update the internal "view" of the active recording sessions
+ * @param event
+ * @param session
+ * @param source
+ * @return true if the list of active recording sessions has been modified, false otherwise.
+ */
+ private boolean updateSnapshot(int event, int session, int source) {
+ synchronized(mRecordConfigs) {
+ switch (event) {
+ case AudioManager.RECORD_CONFIG_EVENT_STOP:
+ // return failure if an unknown recording session stopped
+ return (mRecordConfigs.remove(new Integer(session)) != null);
+ case AudioManager.RECORD_CONFIG_EVENT_START:
+ if (mRecordConfigs.containsKey(new Integer(session))) {
+ // start of session that's already tracked, not worth an update
+ // TO DO in the future when tracking record format: there might be a record
+ // format change during a recording that requires reporting
+ return false;
+ } else {
+ mRecordConfigs.put(new Integer(session),
+ new AudioRecordConfiguration(session, source));
+ return true;
+ }
+ default:
+ Log.e(TAG, String.format("Unknown event %d for session %d, source %d",
+ event, session, source));
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Inner class to track clients that want to be notified of recording updates
+ */
+ private final static class RecMonitorClient implements IBinder.DeathRecipient {
+
+ // can afford to be static because only one RecordingActivityMonitor ever instantiated
+ static RecordingActivityMonitor sMonitor;
+
+ final IRecordingConfigDispatcher mDispatcherCb;
+
+ RecMonitorClient(IRecordingConfigDispatcher rcdb) {
+ mDispatcherCb = rcdb;
+ }
+
+ public void binderDied() {
+ Log.w(TAG, "client died");
+ sMonitor.unregisterRecordingCallback(mDispatcherCb);
+ }
+
+ boolean init() {
+ try {
+ mDispatcherCb.asBinder().linkToDeath(this, 0);
+ return true;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not link to client death", e);
+ return false;
+ }
+ }
+
+ void release() {
+ mDispatcherCb.asBinder().unlinkToDeath(this, 0);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 3a10dbe..4504bdb 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -223,7 +223,6 @@
private final AlarmManager mAlarmManager;
private final NetworkRequest mDefaultRequest;
- private String mServer;
private boolean mIsCaptivePortalCheckEnabled = false;
// Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
@@ -265,10 +264,6 @@
addState(mLingeringState, mDefaultState);
setInitialState(mDefaultState);
- mServer = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.CAPTIVE_PORTAL_SERVER);
- if (mServer == null) mServer = DEFAULT_SERVER;
-
mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
mIsCaptivePortalCheckEnabled = Settings.Global.getInt(mContext.getContentResolver(),
@@ -622,6 +617,13 @@
}
}
+ public static String getCaptivePortalServerUrl(Context context) {
+ String server = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.CAPTIVE_PORTAL_SERVER);
+ if (server == null) server = DEFAULT_SERVER;
+ return "http://" + server + "/generate_204";
+ }
+
/**
* Do a URL fetch on a known server to see if we get the data we expect.
* Returns HTTP response code.
@@ -633,9 +635,9 @@
HttpURLConnection urlConnection = null;
int httpResponseCode = 599;
try {
- URL url = new URL("http", mServer, "/generate_204");
+ URL url = new URL(getCaptivePortalServerUrl(mContext));
// On networks with a PAC instead of fetching a URL that should result in a 204
- // reponse, we instead simply fetch the PAC script. This is done for a few reasons:
+ // response, we instead simply fetch the PAC script. This is done for a few reasons:
// 1. At present our PAC code does not yet handle multiple PACs on multiple networks
// until something like https://android-review.googlesource.com/#/c/115180/ lands.
// Network.openConnection() will ignore network-specific PACs and instead fetch
@@ -644,7 +646,8 @@
// 2. To proxy the generate_204 fetch through a PAC would require a number of things
// happen before the fetch can commence, namely:
// a) the PAC script be fetched
- // b) a PAC script resolver service be fired up and resolve mServer
+ // b) a PAC script resolver service be fired up and resolve the captive portal
+ // server.
// Network validation could be delayed until these prerequisities are satisifed or
// could simply be left to race them. Neither is an optimal solution.
// 3. PAC scripts are sometimes used to block or restrict Internet access and may in
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 835ba17..a16fcd2 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -587,16 +587,16 @@
Slog.e(TAG, "Unable to create surface.", ex);
return false;
}
+
+ mSurfaceControl.setLayerStack(mDisplayLayerStack);
+ mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
+ mSurface = new Surface();
+ mSurface.copyFrom(mSurfaceControl);
+
+ mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
+ mDisplayId, mSurfaceControl);
+ mSurfaceLayout.onDisplayTransaction();
}
-
- mSurfaceControl.setLayerStack(mDisplayLayerStack);
- mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
- mSurface = new Surface();
- mSurface.copyFrom(mSurfaceControl);
-
- mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
- mDisplayId, mSurfaceControl);
- mSurfaceLayout.onDisplayTransaction();
} finally {
SurfaceControl.closeTransaction();
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 433d887..b74b0f2 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -673,6 +673,9 @@
slowChange = false;
}
mAppliedDimming = true;
+ } else if (mAppliedDimming) {
+ slowChange = false;
+ mAppliedDimming = false;
}
// If low power mode is enabled, cut the brightness level by half
@@ -685,6 +688,9 @@
slowChange = false;
}
mAppliedLowPower = true;
+ } else if (mAppliedLowPower) {
+ slowChange = false;
+ mAppliedLowPower = false;
}
// Animate the screen brightness when the screen is on or dozing.
diff --git a/services/core/java/com/android/server/firewall/SenderPackageFilter.java b/services/core/java/com/android/server/firewall/SenderPackageFilter.java
index dc3edd9..91c9671 100644
--- a/services/core/java/com/android/server/firewall/SenderPackageFilter.java
+++ b/services/core/java/com/android/server/firewall/SenderPackageFilter.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -46,7 +47,8 @@
try {
// USER_SYSTEM here is not important. Only app id is used and getPackageUid() will
// return a uid whether the app is installed for a user or not.
- packageUid = pm.getPackageUid(mPackageName, UserHandle.USER_SYSTEM);
+ packageUid = pm.getPackageUid(mPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
+ UserHandle.USER_SYSTEM);
} catch (RemoteException ex) {
// handled below
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 4eabe36..3530d80 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -613,9 +613,10 @@
if (periodicToReschedule.hasDeadlineConstraint()) {
runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0L);
}
- long newEarliestRunTimeElapsed = elapsedNow + runEarly;
+ long flex = periodicToReschedule.getJob().getFlexMillis();
long period = periodicToReschedule.getJob().getIntervalMillis();
- long newLatestRuntimeElapsed = newEarliestRunTimeElapsed + period;
+ long newLatestRuntimeElapsed = elapsedNow + runEarly + period;
+ long newEarliestRunTimeElapsed = newLatestRuntimeElapsed - flex;
if (DEBUG) {
Slog.v(TAG, "Rescheduling executed periodic. New execution window [" +
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 472e8f6..b8aa9dd 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -397,6 +397,7 @@
if (jobStatus.getJob().isPeriodic()) {
out.startTag(null, XML_TAG_PERIODIC);
out.attribute(null, "period", Long.toString(job.getIntervalMillis()));
+ out.attribute(null, "flex", Long.toString(job.getFlexMillis()));
} else {
out.startTag(null, XML_TAG_ONEOFF);
}
@@ -594,13 +595,17 @@
String val = parser.getAttributeValue(null, "period");
final long periodMillis = Long.valueOf(val);
jobBuilder.setPeriodic(periodMillis);
- // As a sanity check, cap the recreated run time to be no later than 2 periods
+ val = parser.getAttributeValue(null, "flex");
+ final long flexMillis = (val != null) ? Long.valueOf(val) : periodMillis;
+ // As a sanity check, cap the recreated run time to be no later than flex+period
// from now. This is the latest the periodic could be pushed out. This could
- // happen if the periodic ran early (at the start of its period), and then the
+ // happen if the periodic ran early (at flex time before period), and then the
// device rebooted.
- if (elapsedRuntimes.second > elapsedNow + 2 * periodMillis) {
- final long clampedEarlyRuntimeElapsed = elapsedNow + periodMillis;
- final long clampedLateRuntimeElapsed = elapsedNow + 2 * periodMillis;
+ if (elapsedRuntimes.second > elapsedNow + periodMillis + flexMillis) {
+ final long clampedLateRuntimeElapsed = elapsedNow + flexMillis
+ + periodMillis;
+ final long clampedEarlyRuntimeElapsed = clampedLateRuntimeElapsed
+ - flexMillis;
Slog.w(TAG,
String.format("Periodic job for uid='%d' persisted run-time is" +
" too big [%s, %s]. Clamping to [%s,%s]",
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index c02611f..060a93e 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -96,8 +96,8 @@
final long elapsedNow = SystemClock.elapsedRealtime();
if (job.isPeriodic()) {
- earliestRunTimeElapsedMillis = elapsedNow;
latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis();
+ earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis();
} else {
earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
diff --git a/services/core/java/com/android/server/media/MediaResourceMonitorService.java b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
new file mode 100644
index 0000000..2305d11
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
@@ -0,0 +1,103 @@
+/*
+ * 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.server.media;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.Intent;
+import android.media.IMediaResourceMonitor;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+import com.android.server.SystemService;
+
+import java.util.List;
+
+/** This class provides a system service that monitors media resource usage. */
+public class MediaResourceMonitorService extends SystemService {
+ private static final String TAG = "MediaResourceMonitorService";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final String SERVICE_NAME = "media_resource_monitor";
+
+ /*
+ * Resource types. Should be in sync with:
+ * frameworks/av/media/libmedia/MediaResource.cpp
+ */
+ private static final String RESOURCE_AUDIO_CODEC = "audio-codec";
+ private static final String RESOURCE_VIDEO_CODEC = "video-codec";
+
+ private final MediaResourceMonitorImpl mMediaResourceMonitorImpl;
+
+ public MediaResourceMonitorService(Context context) {
+ super(context);
+ mMediaResourceMonitorImpl = new MediaResourceMonitorImpl();
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(SERVICE_NAME, mMediaResourceMonitorImpl);
+ }
+
+ class MediaResourceMonitorImpl extends IMediaResourceMonitor.Stub {
+ @Override
+ public void notifyResourceGranted(int pid, String type, String subType, long value)
+ throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "notifyResourceGranted(pid=" + pid + ", type=" + type + ", subType="
+ + subType + ", value=" + value + ")");
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ String pkgNames[] = getPackageNamesFromPid(pid);
+ Integer resourceType = null;
+ if (RESOURCE_AUDIO_CODEC.equals(subType)) {
+ resourceType = Intent.EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC;
+ } else if (RESOURCE_VIDEO_CODEC.equals(subType)) {
+ resourceType = Intent.EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC;
+ }
+ if (pkgNames != null && resourceType != null) {
+ Intent intent = new Intent(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
+ intent.putExtra(Intent.EXTRA_PACKAGES, pkgNames);
+ intent.putExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE, resourceType);
+ getContext().sendBroadcastAsUser(intent,
+ new UserHandle(ActivityManager.getCurrentUser()),
+ android.Manifest.permission.RECEIVE_MEDIA_RESOURCE_USAGE);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private String[] getPackageNamesFromPid(int pid) {
+ try {
+ for (ActivityManager.RunningAppProcessInfo proc :
+ ActivityManagerNative.getDefault().getRunningAppProcesses()) {
+ if (proc.pid == pid) {
+ return proc.pkgList;
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "ActivityManager.getRunningAppProcesses() failed");
+ }
+ return null;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 5aaa930..4764300 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2234,9 +2234,11 @@
final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
final int userId = UserHandle.getUserId(uid);
- for (String packageName : packages) {
- if (!mUsageStats.isAppIdle(packageName, uid, userId)) {
- return false;
+ if (!ArrayUtils.isEmpty(packages)) {
+ for (String packageName : packages) {
+ if (!mUsageStats.isAppIdle(packageName, uid, userId)) {
+ return false;
+ }
}
}
return true;
@@ -2333,7 +2335,8 @@
@Override
public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
try {
- int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, userId);
+ final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
synchronized (mRulesLock) {
updateRuleForAppIdleLocked(uid);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e787eda..018bf2d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -28,6 +28,7 @@
import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL_ALL;
import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_BANNED;
import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationAssistantService.REASON_TOPIC_BANNED;
import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
@@ -741,7 +742,7 @@
for (String pkgName : pkgList) {
if (cancelNotifications) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart,
- changeUserId, REASON_PACKAGE_CHANGED, null);
+ changeUserId, REASON_PACKAGE_CHANGED, null, null);
}
}
}
@@ -774,7 +775,7 @@
int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userHandle >= 0) {
cancelAllNotificationsInt(MY_UID, MY_PID, null, 0, 0, true, userHandle,
- REASON_USER_STOPPED, null);
+ REASON_USER_STOPPED, null, null);
}
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
// turn off LED when user passes through lock screen
@@ -1051,7 +1052,7 @@
// Now, cancel any outstanding notifications that are part of a just-disabled app
if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, 0, 0, true, UserHandle.getUserId(uid),
- REASON_PACKAGE_BANNED, null);
+ REASON_PACKAGE_BANNED, null, null);
}
}
@@ -1209,7 +1210,7 @@
// running foreground services.
cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(),
pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId,
- REASON_APP_CANCEL_ALL, null);
+ REASON_APP_CANCEL_ALL, null, null);
}
@Override
@@ -1266,6 +1267,11 @@
public void setTopicImportance(String pkg, int uid, Notification.Topic topic,
int importance) {
enforceSystemOrSystemUI("Caller not system or systemui");
+ if (NotificationListenerService.Ranking.IMPORTANCE_NONE == importance) {
+ cancelAllNotificationsInt(MY_UID, MY_PID, pkg, 0, 0, true,
+ UserHandle.getUserId(uid),
+ REASON_TOPIC_BANNED, topic, null);
+ }
mRankingHelper.setTopicImportance(pkg, uid, topic, importance);
savePolicyFile();
}
@@ -2284,8 +2290,9 @@
mRankingHelper.extractSignals(r);
savePolicyFile();
- // blocked apps
- if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) {
+ // blocked apps/topics
+ if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE
+ || !noteNotificationOp(pkg, callingUid)) {
if (!isSystemNotification) {
Slog.e(TAG, "Suppressing notification from package " + pkg
+ " by user request.");
@@ -3067,11 +3074,11 @@
}
/**
- * Cancels all notifications from a given package that have all of the
+ * Cancels all notifications from a given package or topic that have all of the
* {@code mustHaveFlags}.
*/
boolean cancelAllNotificationsInt(int callingUid, int callingPid, String pkg, int mustHaveFlags,
- int mustNotHaveFlags, boolean doit, int userId, int reason,
+ int mustNotHaveFlags, boolean doit, int userId, int reason, Notification.Topic topic,
ManagedServiceInfo listener) {
String listenerName = listener == null ? null : listener.component.toShortString();
EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
@@ -3099,6 +3106,10 @@
if (pkg != null && !r.sbn.getPackageName().equals(pkg)) {
continue;
}
+ if (topic != null
+ && !topic.getId().equals(r.getNotification().getTopic().getId())) {
+ continue;
+ }
if (canceledNotifications == null) {
canceledNotifications = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index f1fd42c..ce4ecd3 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -423,14 +423,16 @@
/**
* Sets the default importance for all new topics that appear in the future, and resets
- * the importance of all current topics.
+ * the importance of all current topics (unless the app is being blocked).
*/
@Override
public void setAppImportance(String pkgName, int uid, int importance) {
final Record r = getOrCreateRecord(pkgName, uid);
r.importance = importance;
- for (Topic t : r.topics.values()) {
- t.importance = importance;
+ if (Ranking.IMPORTANCE_NONE != importance) {
+ for (Topic t : r.topics.values()) {
+ t.importance = importance;
+ }
}
updateConfig();
}
@@ -483,7 +485,9 @@
pw.print(prefix);
pw.println("per-package config:");
}
+ pw.println("Records:");
dumpRecords(pw, prefix, filter, mRecords);
+ pw.println("Restored without uid:");
dumpRecords(pw, prefix, filter, mRestoredWithoutUids);
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 99a051a..190eca6 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -20,14 +20,14 @@
import android.content.Context;
import android.content.pm.PackageStats;
import android.os.Build;
-import android.text.TextUtils;
import android.util.Slog;
-import dalvik.system.VMRuntime;
-
import com.android.internal.os.InstallerConnection;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.server.SystemService;
+import dalvik.system.VMRuntime;
+
public final class Installer extends SystemService {
private static final String TAG = "Installer";
@@ -46,6 +46,11 @@
/** Run the application with the JIT compiler */
public static final int DEXOPT_USEJIT = 1 << 5;
+ public static final int FLAG_DE_STORAGE = 1 << 0;
+ public static final int FLAG_CE_STORAGE = 1 << 1;
+ public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 2;
+ public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 3;
+
private final InstallerConnection mInstaller;
public Installer(Context context) {
@@ -67,423 +72,137 @@
mInstaller.waitForConnection();
}
- private static String escapeNull(String arg) {
- if (TextUtils.isEmpty(arg)) {
- return "!";
- } else {
- if (arg.indexOf('\0') != -1 || arg.indexOf(' ') != -1) {
- throw new IllegalArgumentException(arg);
- }
- return arg;
- }
+ public void createAppData(String uuid, String pkgname, int userid, int flags, int appid,
+ String seinfo) throws InstallerException {
+ mInstaller.execute("create_app_data", uuid, pkgname, userid, flags, appid, seinfo);
}
- @Deprecated
- public int install(String name, int uid, int gid, String seinfo) {
- return install(null, name, uid, gid, seinfo);
+ public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid,
+ String seinfo) throws InstallerException {
+ mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid,
+ seinfo);
}
- public int install(String uuid, String name, int uid, int gid, String seinfo) {
- StringBuilder builder = new StringBuilder("install");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(gid);
- builder.append(' ');
- builder.append(seinfo != null ? seinfo : "!");
- return mInstaller.execute(builder.toString());
+ public void clearAppData(String uuid, String pkgname, int userid, int flags)
+ throws InstallerException {
+ mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags);
}
- public int dexopt(String apkPath, int uid, String instructionSet,
- int dexoptNeeded, int dexFlags) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- return mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags);
+ public void destroyAppData(String uuid, String pkgname, int userid, int flags)
+ throws InstallerException {
+ mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags);
}
- public int dexopt(String apkPath, int uid, String pkgName, String instructionSet,
- int dexoptNeeded, @Nullable String outputPath, int dexFlags) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
- return mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
- outputPath, dexFlags);
+ public void moveCompleteApp(String from_uuid, String to_uuid, String package_name,
+ String data_app_name, int appid, String seinfo) throws InstallerException {
+ mInstaller.execute("move_complete_app", from_uuid, to_uuid, package_name,
+ data_app_name, appid, seinfo);
}
- public int idmap(String targetApkPath, String overlayApkPath, int uid) {
- StringBuilder builder = new StringBuilder("idmap");
- builder.append(' ');
- builder.append(targetApkPath);
- builder.append(' ');
- builder.append(overlayApkPath);
- builder.append(' ');
- builder.append(uid);
- return mInstaller.execute(builder.toString());
- }
-
- public int movedex(String srcPath, String dstPath, String instructionSet) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- StringBuilder builder = new StringBuilder("movedex");
- builder.append(' ');
- builder.append(srcPath);
- builder.append(' ');
- builder.append(dstPath);
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
- }
-
- public int rmdex(String codePath, String instructionSet) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- StringBuilder builder = new StringBuilder("rmdex");
- builder.append(' ');
- builder.append(codePath);
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
- }
-
- /**
- * Removes packageDir or its subdirectory
- */
- public int rmPackageDir(String packageDir) {
- StringBuilder builder = new StringBuilder("rmpackagedir");
- builder.append(' ');
- builder.append(packageDir);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int remove(String name, int userId) {
- return remove(null, name, userId);
- }
-
- public int remove(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("remove");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int fixUid(String name, int uid, int gid) {
- return fixUid(null, name, uid, gid);
- }
-
- public int fixUid(String uuid, String name, int uid, int gid) {
- StringBuilder builder = new StringBuilder("fixuid");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(gid);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int deleteCacheFiles(String name, int userId) {
- return deleteCacheFiles(null, name, userId);
- }
-
- public int deleteCacheFiles(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("rmcache");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int deleteCodeCacheFiles(String name, int userId) {
- return deleteCodeCacheFiles(null, name, userId);
- }
-
- public int deleteCodeCacheFiles(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("rmcodecache");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int createUserData(String name, int uid, int userId, String seinfo) {
- return createUserData(null, name, uid, userId, seinfo);
- }
-
- public int createUserData(String uuid, String name, int uid, int userId, String seinfo) {
- StringBuilder builder = new StringBuilder("mkuserdata");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(uid);
- builder.append(' ');
- builder.append(userId);
- builder.append(' ');
- builder.append(seinfo != null ? seinfo : "!");
- return mInstaller.execute(builder.toString());
- }
-
- public int createUserConfig(int userId) {
- StringBuilder builder = new StringBuilder("mkuserconfig");
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int removeUserDataDirs(int userId) {
- return removeUserDataDirs(null, userId);
- }
-
- public int removeUserDataDirs(String uuid, int userId) {
- StringBuilder builder = new StringBuilder("rmuser");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- public int copyCompleteApp(String fromUuid, String toUuid, String packageName,
- String dataAppName, int appId, String seinfo) {
- StringBuilder builder = new StringBuilder("cpcompleteapp");
- builder.append(' ');
- builder.append(escapeNull(fromUuid));
- builder.append(' ');
- builder.append(escapeNull(toUuid));
- builder.append(' ');
- builder.append(packageName);
- builder.append(' ');
- builder.append(dataAppName);
- builder.append(' ');
- builder.append(appId);
- builder.append(' ');
- builder.append(seinfo);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int clearUserData(String name, int userId) {
- return clearUserData(null, name, userId);
- }
-
- public int clearUserData(String uuid, String name, int userId) {
- StringBuilder builder = new StringBuilder("rmuserdata");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(name);
- builder.append(' ');
- builder.append(userId);
- return mInstaller.execute(builder.toString());
- }
-
- public int markBootComplete(String instructionSet) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
-
- StringBuilder builder = new StringBuilder("markbootcomplete");
- builder.append(' ');
- builder.append(instructionSet);
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int freeCache(long freeStorageSize) {
- return freeCache(null, freeStorageSize);
- }
-
- public int freeCache(String uuid, long freeStorageSize) {
- StringBuilder builder = new StringBuilder("freecache");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(String.valueOf(freeStorageSize));
- return mInstaller.execute(builder.toString());
- }
-
- @Deprecated
- public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
- String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats) {
- return getSizeInfo(null, pkgName, persona, apkPath, libDirPath, fwdLockApkPath, asecPath,
- instructionSets, pStats);
- }
-
- public int getSizeInfo(String uuid, String pkgName, int persona, String apkPath,
+ public void getAppSize(String uuid, String pkgname, int userid, int flags, String apkPath,
String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets,
- PackageStats pStats) {
+ PackageStats pStats) throws InstallerException {
for (String instructionSet : instructionSets) {
- if (!isValidInstructionSet(instructionSet)) {
- Slog.e(TAG, "Invalid instruction set: " + instructionSet);
- return -1;
- }
+ assertValidInstructionSet(instructionSet);
}
- StringBuilder builder = new StringBuilder("getsize");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(persona);
- builder.append(' ');
- builder.append(apkPath);
- builder.append(' ');
// TODO: Extend getSizeInfo to look at the full subdirectory tree,
// not just the first level.
- builder.append(libDirPath != null ? libDirPath : "!");
- builder.append(' ');
- builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
- builder.append(' ');
- builder.append(asecPath != null ? asecPath : "!");
- builder.append(' ');
// TODO: Extend getSizeInfo to look at *all* instrution sets, not
// just the primary.
- builder.append(instructionSets[0]);
-
- String s = mInstaller.transact(builder.toString());
- String res[] = s.split(" ");
+ final String rawRes = mInstaller.executeForResult("get_app_size", uuid, pkgname, userid,
+ flags, apkPath, libDirPath, fwdLockApkPath, asecPath, instructionSets[0]);
+ final String res[] = rawRes.split(" ");
if ((res == null) || (res.length != 5)) {
- return -1;
+ throw new InstallerException("Invalid size result: " + rawRes);
}
try {
pStats.codeSize = Long.parseLong(res[1]);
pStats.dataSize = Long.parseLong(res[2]);
pStats.cacheSize = Long.parseLong(res[3]);
pStats.externalCodeSize = Long.parseLong(res[4]);
- return Integer.parseInt(res[0]);
} catch (NumberFormatException e) {
- return -1;
+ throw new InstallerException("Invalid size result: " + rawRes);
}
}
- public int moveFiles() {
- return mInstaller.execute("movefiles");
+ public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
+ int dexFlags) throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags);
}
- @Deprecated
- public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId) {
- return linkNativeLibraryDirectory(null, dataPath, nativeLibPath32, userId);
+ public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
+ int dexoptNeeded, @Nullable String outputPath, int dexFlags)
+ throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
+ outputPath, dexFlags);
+ }
+
+ public void idmap(String targetApkPath, String overlayApkPath, int uid)
+ throws InstallerException {
+ mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
+ }
+
+ public void rmdex(String codePath, String instructionSet) throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.execute("rmdex", codePath, instructionSet);
+ }
+
+ public void rmPackageDir(String packageDir) throws InstallerException {
+ mInstaller.execute("rmpackagedir", packageDir);
+ }
+
+ public void createUserConfig(int userid) throws InstallerException {
+ mInstaller.execute("mkuserconfig", userid);
+ }
+
+ public void removeUserDataDirs(String uuid, int userid) throws InstallerException {
+ mInstaller.execute("rmuser", uuid, userid);
+ }
+
+ public void markBootComplete(String instructionSet) throws InstallerException {
+ assertValidInstructionSet(instructionSet);
+ mInstaller.execute("markbootcomplete", instructionSet);
+ }
+
+ public void freeCache(String uuid, long freeStorageSize) throws InstallerException {
+ mInstaller.execute("freecache", uuid, freeStorageSize);
+ }
+
+ public void moveFiles() throws InstallerException {
+ mInstaller.execute("movefiles");
}
/**
- * Links the 32 bit native library directory in an application's data directory to the
- * real location for backward compatibility. Note that no such symlink is created for
- * 64 bit shared libraries.
- *
- * @return -1 on error
+ * Links the 32 bit native library directory in an application's data
+ * directory to the real location for backward compatibility. Note that no
+ * such symlink is created for 64 bit shared libraries.
*/
- public int linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
- int userId) {
- if (dataPath == null) {
- Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
- return -1;
- } else if (nativeLibPath32 == null) {
- Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
- return -1;
- }
-
- StringBuilder builder = new StringBuilder("linklib");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(dataPath);
- builder.append(' ');
- builder.append(nativeLibPath32);
- builder.append(' ');
- builder.append(userId);
-
- return mInstaller.execute(builder.toString());
+ public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
+ int userId) throws InstallerException {
+ mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId);
}
- @Deprecated
- public boolean restoreconData(String pkgName, String seinfo, int uid) {
- return restoreconData(null, pkgName, seinfo, uid);
+ public void createOatDir(String oatDir, String dexInstructionSet)
+ throws InstallerException {
+ mInstaller.execute("createoatdir", oatDir, dexInstructionSet);
}
- public boolean restoreconData(String uuid, String pkgName, String seinfo, int uid) {
- StringBuilder builder = new StringBuilder("restorecondata");
- builder.append(' ');
- builder.append(escapeNull(uuid));
- builder.append(' ');
- builder.append(pkgName);
- builder.append(' ');
- builder.append(seinfo != null ? seinfo : "!");
- builder.append(' ');
- builder.append(uid);
- return (mInstaller.execute(builder.toString()) == 0);
+ public void linkFile(String relativePath, String fromBase, String toBase)
+ throws InstallerException {
+ mInstaller.execute("linkfile", relativePath, fromBase, toBase);
}
- public int createOatDir(String oatDir, String dexInstructionSet) {
- StringBuilder builder = new StringBuilder("createoatdir");
- builder.append(' ');
- builder.append(oatDir);
- builder.append(' ');
- builder.append(dexInstructionSet);
- return mInstaller.execute(builder.toString());
- }
-
-
- public int linkFile(String relativePath, String fromBase, String toBase) {
- StringBuilder builder = new StringBuilder("linkfile");
- builder.append(' ');
- builder.append(relativePath);
- builder.append(' ');
- builder.append(fromBase);
- builder.append(' ');
- builder.append(toBase);
- return mInstaller.execute(builder.toString());
- }
-
- /**
- * Returns true iff. {@code instructionSet} is a valid instruction set.
- */
- private static boolean isValidInstructionSet(String instructionSet) {
- if (instructionSet == null) {
- return false;
- }
-
+ private static void assertValidInstructionSet(String instructionSet)
+ throws InstallerException {
for (String abi : Build.SUPPORTED_ABIS) {
- if (instructionSet.equals(VMRuntime.getInstructionSet(abi))) {
- return true;
+ if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) {
+ return;
}
}
-
- return false;
+ throw new InstallerException("Invalid instruction set: " + instructionSet);
}
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 0796811..18618d5 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -24,8 +24,8 @@
import android.content.pm.ILauncherApps;
import android.content.pm.IOnAppsChangedListener;
import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
@@ -45,7 +45,6 @@
import com.android.internal.content.PackageMonitor;
import com.android.server.SystemService;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -200,7 +199,8 @@
mainIntent.setPackage(packageName);
long ident = Binder.clearCallingIdentity();
try {
- List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0 /* flags */,
+ List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
user.getIdentifier());
return new ParceledListSlice<>(apps);
} finally {
@@ -218,7 +218,8 @@
long ident = Binder.clearCallingIdentity();
try {
- ResolveInfo app = mPm.resolveActivityAsUser(intent, 0, user.getIdentifier());
+ ResolveInfo app = mPm.resolveActivityAsUser(intent,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
return app;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -236,7 +237,8 @@
long ident = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
- PackageInfo info = pm.getPackageInfo(packageName, 0, user.getIdentifier());
+ PackageInfo info = pm.getPackageInfo(packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
return info != null && info.applicationInfo.enabled;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -254,7 +256,8 @@
long ident = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
- ActivityInfo info = pm.getActivityInfo(component, 0, user.getIdentifier());
+ ActivityInfo info = pm.getActivityInfo(component,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
return info != null;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -279,7 +282,8 @@
long ident = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
- ActivityInfo info = pm.getActivityInfo(component, 0, user.getIdentifier());
+ ActivityInfo info = pm.getActivityInfo(component,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
if (!info.exported) {
throw new SecurityException("Cannot launch non-exported components "
+ component);
@@ -289,7 +293,7 @@
// as calling startActivityAsUser ignores the category and just
// resolves based on the component if present.
List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
- 0 /* flags */, user.getIdentifier());
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING, user.getIdentifier());
final int size = apps.size();
for (int i = 0; i < size; ++i) {
ActivityInfo activityInfo = apps.get(i).activityInfo;
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index d29a623..b45a922 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -27,6 +27,8 @@
import android.util.Log;
import android.util.Slog;
+import com.android.internal.os.InstallerConnection.InstallerException;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -166,12 +168,13 @@
| (vmSafeMode ? DEXOPT_SAFEMODE : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
| DEXOPT_BOOTCOMPLETE;
- final int ret = mPackageManagerService.mInstaller.dexopt(path, sharedGid,
- pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir, dexFlags);
-
- // Dex2oat might fail due to compiler / verifier errors.
- if (ret == 0) {
+ try {
+ mPackageManagerService.mInstaller.dexopt(path, sharedGid,
+ pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir,
+ dexFlags);
performedDexOpt = true;
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to dexopt", e);
}
}
}
@@ -210,8 +213,13 @@
File codePath = new File(pkg.codePath);
if (codePath.isDirectory()) {
File oatDir = getOatDir(codePath);
- mPackageManagerService.mInstaller.createOatDir(oatDir.getAbsolutePath(),
- dexInstructionSet);
+ try {
+ mPackageManagerService.mInstaller.createOatDir(oatDir.getAbsolutePath(),
+ dexInstructionSet);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to create oat dir", e);
+ return null;
+ }
return oatDir.getAbsolutePath();
}
return null;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 7e4e46b..23a58d0 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -258,11 +258,7 @@
for (File stage : unclaimedStages) {
Slog.w(TAG, "Deleting orphan stage " + stage);
synchronized (mPm.mInstallLock) {
- if (stage.isDirectory()) {
- mPm.mInstaller.rmPackageDir(stage.getAbsolutePath());
- } else {
- stage.delete();
- }
+ mPm.removeCodePathLI(stage);
}
}
}
@@ -386,8 +382,8 @@
final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
final int userId = readIntAttribute(in, ATTR_USER_ID);
final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME);
- final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID,
- mPm.getPackageUid(installerPackageName, userId));
+ final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, mPm.getPackageUid(
+ installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId));
final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 66d10b5..b84ffa3 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -69,6 +69,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
@@ -832,9 +833,14 @@
throw new IOException("File: " + pathStr + " outside base: " + baseStr);
}
- private void createOatDirs(List<String> instructionSets, File fromDir) {
+ private void createOatDirs(List<String> instructionSets, File fromDir)
+ throws PackageManagerException {
for (String instructionSet : instructionSets) {
- mPm.mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+ try {
+ mPm.mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+ } catch (InstallerException e) {
+ throw PackageManagerException.from(e);
+ }
}
}
@@ -842,13 +848,12 @@
throws IOException {
for (File fromFile : fromFiles) {
final String relativePath = getRelativePath(fromFile, fromDir);
- final int ret = mPm.mInstaller.linkFile(relativePath, fromDir.getAbsolutePath(),
- toDir.getAbsolutePath());
-
- if (ret < 0) {
- // installd will log failure details.
+ try {
+ mPm.mInstaller.linkFile(relativePath, fromDir.getAbsolutePath(),
+ toDir.getAbsolutePath());
+ } catch (InstallerException e) {
throw new IOException("failed linkOrCreateDir(" + relativePath + ", "
- + fromDir + ", " + toDir + ")");
+ + fromDir + ", " + toDir + ")", e);
}
}
@@ -947,7 +952,7 @@
}
final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
- UserHandle.USER_SYSTEM);
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
final int gid = UserHandle.getSharedAppGid(uid);
if (!PackageHelper.fixSdPermissions(cid, gid, null)) {
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
@@ -1041,7 +1046,10 @@
}
}
if (stageDir != null) {
- mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ try {
+ mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ } catch (InstallerException ignored) {
+ }
}
if (stageCid != null) {
PackageHelper.destroySdDir(stageCid);
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index a41636e..d04eedc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -16,8 +16,11 @@
package com.android.server.pm;
+import android.content.pm.PackageManager;
import android.content.pm.PackageParser.PackageParserException;
+import com.android.internal.os.InstallerConnection.InstallerException;
+
/** {@hide} */
public class PackageManagerException extends Exception {
public final int error;
@@ -36,4 +39,10 @@
throws PackageManagerException {
throw new PackageManagerException(e.error, e.getMessage(), e.getCause());
}
+
+ public static PackageManagerException from(InstallerException e)
+ throws PackageManagerException {
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+ e.getMessage(), e.getCause());
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 254e77b..f777faf 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -59,6 +59,7 @@
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
import static android.content.pm.PackageManager.MATCH_ALL;
+import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
@@ -218,6 +219,7 @@
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.os.IParcelFileDescriptorFactory;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
import com.android.internal.util.ArrayUtils;
@@ -317,6 +319,8 @@
static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
+ private static final boolean DISABLE_EPHEMERAL_APPS = true;
+
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
@@ -2064,7 +2068,7 @@
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
- } catch (IOException e) {
+ } catch (IOException | InstallerException e) {
Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+ e.getMessage());
}
@@ -2133,7 +2137,11 @@
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
- mInstaller.moveFiles();
+ try {
+ mInstaller.moveFiles();
+ } catch (InstallerException e) {
+ logCriticalInfo(Log.WARN, "Update commands failed: " + e);
+ }
// Prune any system packages that no longer exist.
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
@@ -2707,11 +2715,7 @@
removeDataDirsLI(ps.volumeUuid, ps.name);
if (ps.codePath != null) {
- if (ps.codePath.isDirectory()) {
- mInstaller.rmPackageDir(ps.codePath.getAbsolutePath());
- } else {
- ps.codePath.delete();
- }
+ removeCodePathLI(ps.codePath);
}
if (ps.resourcePath != null && !ps.resourcePath.equals(ps.codePath)) {
if (ps.resourcePath.isDirectory()) {
@@ -2836,12 +2840,7 @@
}
@Override
- public int getPackageUid(String packageName, int userId) {
- return getPackageUidEtc(packageName, 0, userId);
- }
-
- @Override
- public int getPackageUidEtc(String packageName, int flags, int userId) {
+ public int getPackageUid(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return -1;
flags = updateFlagsForPackage(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid");
@@ -2849,12 +2848,12 @@
// reader
synchronized (mPackages) {
final PackageParser.Package p = mPackages.get(packageName);
- if (p != null) {
+ if (p != null && p.isMatch(flags)) {
return UserHandle.getUid(userId, p.applicationInfo.uid);
}
if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps != null) {
+ if (ps != null && ps.isMatch(flags)) {
return UserHandle.getUid(userId, ps.appId);
}
}
@@ -2864,12 +2863,7 @@
}
@Override
- public int[] getPackageGids(String packageName, int userId) {
- return getPackageGidsEtc(packageName, 0, userId);
- }
-
- @Override
- public int[] getPackageGidsEtc(String packageName, int flags, int userId) {
+ public int[] getPackageGids(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForPackage(flags, userId, packageName);
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false,
@@ -2878,13 +2872,13 @@
// reader
synchronized (mPackages) {
final PackageParser.Package p = mPackages.get(packageName);
- if (p != null) {
+ if (p != null && p.isMatch(flags)) {
PackageSetting ps = (PackageSetting) p.mExtras;
return ps.getPermissionsState().computeGids(userId);
}
if ((flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps != null) {
+ if (ps != null && ps.isMatch(flags)) {
return ps.getPermissionsState().computeGids(userId);
}
}
@@ -3045,16 +3039,18 @@
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- int retCode = -1;
+ boolean success = true;
synchronized (mInstallLock) {
- retCode = mInstaller.freeCache(volumeUuid, freeStorageSize);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't clear application caches");
+ try {
+ mInstaller.freeCache(volumeUuid, freeStorageSize);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Couldn't clear application caches: " + e);
+ success = false;
}
}
if (observer != null) {
try {
- observer.onRemoveCompleted(null, (retCode >= 0));
+ observer.onRemoveCompleted(null, success);
} catch (RemoteException e) {
Slog.w(TAG, "RemoveException when invoking call back");
}
@@ -3072,17 +3068,19 @@
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- int retCode = -1;
+ boolean success = true;
synchronized (mInstallLock) {
- retCode = mInstaller.freeCache(volumeUuid, freeStorageSize);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't clear application caches");
+ try {
+ mInstaller.freeCache(volumeUuid, freeStorageSize);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Couldn't clear application caches: " + e);
+ success = false;
}
}
if(pi != null) {
try {
// Callback via pending intent
- int code = (retCode >= 0) ? 1 : 0;
+ int code = success ? 1 : 0;
pi.sendIntent(null, code, null,
null, null);
} catch (SendIntentException e1) {
@@ -3095,8 +3093,10 @@
void freeStorage(String volumeUuid, long freeStorageSize) throws IOException {
synchronized (mInstallLock) {
- if (mInstaller.freeCache(volumeUuid, freeStorageSize) < 0) {
- throw new IOException("Failed to free enough space");
+ try {
+ mInstaller.freeCache(volumeUuid, freeStorageSize);
+ } catch (InstallerException e) {
+ throw new IOException("Failed to free enough space", e);
}
}
}
@@ -3128,7 +3128,7 @@
/**
* Update given flags based on encryption status of current user.
*/
- private int updateFlagsForEncryption(int flags, int userId) {
+ private int updateFlags(int flags, int userId) {
if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
| PackageManager.MATCH_ENCRYPTION_AWARE)) != 0) {
// Caller expressed an explicit opinion about what encryption
@@ -3142,6 +3142,12 @@
flags |= PackageManager.MATCH_ENCRYPTION_AWARE;
}
}
+
+ // Safe mode means we should ignore any third-party apps
+ if (mSafeMode) {
+ flags |= PackageManager.MATCH_SYSTEM_ONLY;
+ }
+
return flags;
}
@@ -3150,8 +3156,8 @@
*/
private int updateFlagsForPackage(int flags, int userId, Object cookie) {
boolean triaged = true;
- if ((flags & PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS
- | PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS) != 0) {
+ if ((flags & (PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS
+ | PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS)) != 0) {
// Caller is asking for component details, so they'd better be
// asking for specific encryption matching behavior, or be triaged
if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE
@@ -3161,14 +3167,15 @@
}
}
if ((flags & (PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_SYSTEM_ONLY
| PackageManager.MATCH_DEBUG_TRIAGED_MISSING)) == 0) {
triaged = false;
}
if (DEBUG_TRIAGED_MISSING && (Binder.getCallingUid() == Process.SYSTEM_UID) && !triaged) {
- Log.w(TAG, "Caller hasn't been triaged for missing apps; they asked about " + cookie,
- new Throwable());
+ Log.w(TAG, "Caller hasn't been triaged for missing apps; they asked about " + cookie
+ + " with flags 0x" + Integer.toHexString(flags), new Throwable());
}
- return updateFlagsForEncryption(flags, userId);
+ return updateFlags(flags, userId);
}
/**
@@ -3182,6 +3189,12 @@
* Update given flags when being used to request {@link ComponentInfo}.
*/
private int updateFlagsForComponent(int flags, int userId, Object cookie) {
+ if (cookie instanceof Intent) {
+ if ((((Intent) cookie).getFlags() & Intent.FLAG_DEBUG_TRIAGED_MISSING) != 0) {
+ flags |= PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+ }
+ }
+
boolean triaged = true;
// Caller is asking for component details, so they'd better be
// asking for specific encryption matching behavior, or be triaged
@@ -3191,10 +3204,10 @@
triaged = false;
}
if (DEBUG_TRIAGED_MISSING && (Binder.getCallingUid() == Process.SYSTEM_UID) && !triaged) {
- Log.w(TAG, "Caller hasn't been triaged for missing apps; they asked about " + cookie,
- new Throwable());
+ Log.w(TAG, "Caller hasn't been triaged for missing apps; they asked about " + cookie
+ + " with flags 0x" + Integer.toHexString(flags), new Throwable());
}
- return updateFlagsForEncryption(flags, userId);
+ return updateFlags(flags, userId);
}
/**
@@ -4032,7 +4045,7 @@
"canShowRequestPermissionRationale for user " + userId);
}
- final int uid = getPackageUid(packageName, userId);
+ final int uid = getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId);
if (UserHandle.getAppId(getCallingUid()) != UserHandle.getAppId(uid)) {
return false;
}
@@ -4471,6 +4484,9 @@
private boolean isEphemeralAllowed(
Intent intent, List<ResolveInfo> resolvedActivites, int userId) {
// Short circuit and return early if possible.
+ if (DISABLE_EPHEMERAL_APPS) {
+ return false;
+ }
final int callingUser = UserHandle.getCallingUserId();
if (callingUser != UserHandle.USER_SYSTEM) {
return false;
@@ -5805,6 +5821,10 @@
@Override
public ParceledListSlice<EphemeralApplicationInfo> getEphemeralApplications(int userId) {
+ if (DISABLE_EPHEMERAL_APPS) {
+ return null;
+ }
+
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS,
"getEphemeralApplications");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
@@ -5823,6 +5843,10 @@
public boolean isEphemeralApplication(String packageName, int userId) {
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"isEphemeral");
+ if (DISABLE_EPHEMERAL_APPS) {
+ return false;
+ }
+
if (!isCallerSameApp(packageName)) {
return false;
}
@@ -5837,6 +5861,10 @@
@Override
public byte[] getEphemeralApplicationCookie(String packageName, int userId) {
+ if (DISABLE_EPHEMERAL_APPS) {
+ return null;
+ }
+
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"getCookie");
if (!isCallerSameApp(packageName)) {
@@ -5850,6 +5878,10 @@
@Override
public boolean setEphemeralApplicationCookie(String packageName, byte[] cookie, int userId) {
+ if (DISABLE_EPHEMERAL_APPS) {
+ return true;
+ }
+
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"setCookie");
if (!isCallerSameApp(packageName)) {
@@ -5863,6 +5895,10 @@
@Override
public Bitmap getEphemeralApplicationIcon(String packageName, int userId) {
+ if (DISABLE_EPHEMERAL_APPS) {
+ return null;
+ }
+
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS,
"getEphemeralApplicationIcon");
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
@@ -5918,8 +5954,6 @@
: null;
return ps != null
&& mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)
- && (!mSafeMode || (provider.info.applicationInfo.flags
- &ApplicationInfo.FLAG_SYSTEM) != 0)
? PackageParser.generateProviderInfo(provider, flags,
ps.readUserState(userId), userId)
: null;
@@ -5974,9 +6008,7 @@
&& (processName == null
|| (p.info.processName.equals(processName)
&& UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
- && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)
- && (!mSafeMode
- || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
+ && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
if (finalList == null) {
finalList = new ArrayList<ProviderInfo>(3);
}
@@ -6061,7 +6093,9 @@
}
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
// TODO: generate idmap for split APKs
- if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid) != 0) {
+ try {
+ mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid);
+ } catch (InstallerException e) {
Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
+ opkg.baseCodePath);
return false;
@@ -6121,11 +6155,7 @@
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
- if (file.isDirectory()) {
- mInstaller.rmPackageDir(file.getAbsolutePath());
- } else {
- file.delete();
- }
+ removeCodePathLI(file);
}
}
}
@@ -6691,50 +6721,65 @@
private void createDataDirsLI(String volumeUuid, String packageName, int uid, String seinfo)
throws PackageManagerException {
- int res = mInstaller.install(volumeUuid, packageName, uid, uid, seinfo);
- if (res != 0) {
+ // TODO: triage flags as part of 26466827
+ final int appId = UserHandle.getAppId(uid);
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+
+ try {
+ final int[] users = sUserManager.getUserIds();
+ for (int user : users) {
+ mInstaller.createAppData(volumeUuid, packageName, user, flags, appId, seinfo);
+ }
+ } catch (InstallerException e) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Failed to install " + packageName + ": " + res);
+ "Failed to prepare data directory", e);
}
+ }
+
+ private boolean removeDataDirsLI(String volumeUuid, String packageName) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+
+ boolean res = true;
+ final int[] users = sUserManager.getUserIds();
+ for (int user : users) {
+ try {
+ mInstaller.destroyAppData(volumeUuid, packageName, user, flags);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to delete data directory", e);
+ res = false;
+ }
+ }
+ return res;
+ }
+
+ void removeCodePathLI(File codePath) {
+ if (codePath.isDirectory()) {
+ try {
+ mInstaller.rmPackageDir(codePath.getAbsolutePath());
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to remove code path", e);
+ }
+ } else {
+ codePath.delete();
+ }
+ }
+
+ private void deleteCodeCacheDirsLI(String volumeUuid, String packageName) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
final int[] users = sUserManager.getUserIds();
for (int user : users) {
- if (user != 0) {
- res = mInstaller.createUserData(volumeUuid, packageName,
- UserHandle.getUid(user, uid), user, seinfo);
- if (res != 0) {
- throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
- "Failed to createUserData " + packageName + ": " + res);
- }
+ try {
+ mInstaller.clearAppData(volumeUuid, packageName, user,
+ flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to delete code cache directory", e);
}
}
}
- private int removeDataDirsLI(String volumeUuid, String packageName) {
- int[] users = sUserManager.getUserIds();
- int res = 0;
- for (int user : users) {
- int resInner = mInstaller.remove(volumeUuid, packageName, user);
- if (resInner < 0) {
- res = resInner;
- }
- }
-
- return res;
- }
-
- private int deleteCodeCacheDirsLI(String volumeUuid, String packageName) {
- int[] users = sUserManager.getUserIds();
- int res = 0;
- for (int user : users) {
- int resInner = mInstaller.deleteCodeCacheFiles(volumeUuid, packageName, user);
- if (resInner < 0) {
- res = resInner;
- }
- }
- return res;
- }
-
private void addSharedLibraryLPw(ArraySet<String> usesLibraryFiles, SharedLibraryEntry file,
PackageParser.Package changingLib) {
if (file.path != null) {
@@ -7233,6 +7278,8 @@
final File dataPath = Environment.getDataUserCredentialEncryptedPackageDirectory(
pkg.volumeUuid, UserHandle.USER_SYSTEM, pkg.packageName);
+ // TOOD: switch to ensure various directories
+
boolean uidError = false;
if (dataPath.exists()) {
int currentUid = 0;
@@ -7246,27 +7293,12 @@
// If we have mismatched owners for the data path, we have a problem.
if (currentUid != pkg.applicationInfo.uid) {
boolean recovered = false;
- if (currentUid == 0) {
- // The directory somehow became owned by root. Wow.
- // This is probably because the system was stopped while
- // installd was in the middle of messing with its libs
- // directory. Ask installd to fix that.
- int ret = mInstaller.fixUid(pkg.volumeUuid, pkgName,
- pkg.applicationInfo.uid, pkg.applicationInfo.uid);
- if (ret >= 0) {
- recovered = true;
- String msg = "Package " + pkg.packageName
- + " unexpectedly changed to uid 0; recovered to " +
- + pkg.applicationInfo.uid;
- reportSettingsProblem(Log.WARN, msg);
- }
- }
- if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
- || (scanFlags&SCAN_BOOTING) != 0)) {
+ if (((parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0
+ || (scanFlags & SCAN_BOOTING) != 0)) {
// If this is a system app, we can at least delete its
// current data so the application will still work.
- int ret = removeDataDirsLI(pkg.volumeUuid, pkgName);
- if (ret >= 0) {
+ boolean res = removeDataDirsLI(pkg.volumeUuid, pkgName);
+ if (res) {
// TODO: Kill the processes first
// Old data gone!
String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
@@ -7281,11 +7313,12 @@
if (!recovered) {
mHasSystemUidErrors = true;
}
- } else if (!recovered) {
+ } else {
// If we allow this install to proceed, we will be broken.
// Abort, abort!
throw new PackageManagerException(INSTALL_FAILED_UID_CHANGED,
- "scanPackageLI");
+ "Expected data to be owned by UID " + pkg.applicationInfo.uid
+ + " but found " + currentUid);
}
if (!recovered) {
pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
@@ -7315,8 +7348,16 @@
if (mShouldRestoreconData) {
Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
- mInstaller.restoreconData(pkg.volumeUuid, pkg.packageName,
- pkg.applicationInfo.seinfo, pkg.applicationInfo.uid);
+ // TODO: extend this to restorecon over all users
+ final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.restoreconAppData(pkg.volumeUuid, pkg.packageName,
+ UserHandle.USER_SYSTEM, flags, appId, pkg.applicationInfo.seinfo);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to restorecon " + pkg.packageName, e);
+ }
}
} else {
if (DEBUG_PACKAGE_SCANNING) {
@@ -7372,9 +7413,15 @@
if (!TextUtils.isEmpty(pkg.volumeUuid)) {
for (int userId : userIds) {
if (userId != UserHandle.USER_SYSTEM) {
- mInstaller.createUserData(pkg.volumeUuid, pkg.packageName,
- UserHandle.getUid(userId, pkg.applicationInfo.uid), userId,
- pkg.applicationInfo.seinfo);
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
+ try {
+ mInstaller.createAppData(pkg.volumeUuid, pkg.packageName, userId,
+ flags, appId, pkg.applicationInfo.seinfo);
+ } catch (InstallerException e) {
+ throw PackageManagerException.from(e);
+ }
}
}
}
@@ -7388,10 +7435,11 @@
try {
final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
for (int userId : userIds) {
- if (mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
- nativeLibPath, userId) < 0) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Failed linking native library dir (user=" + userId + ")");
+ try {
+ mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
+ nativeLibPath, userId);
+ } catch (InstallerException e) {
+ throw PackageManagerException.from(e);
}
}
} finally {
@@ -8124,8 +8172,11 @@
if (ps.pkg != null && ps.pkg.applicationInfo != null) {
ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi);
- mInstaller.rmdex(ps.codePathString,
- getDexCodeInstructionSet(getPreferredInstructionSet()));
+ try {
+ mInstaller.rmdex(ps.codePathString,
+ getDexCodeInstructionSet(getPreferredInstructionSet()));
+ } catch (InstallerException ignored) {
+ }
}
}
}
@@ -9242,10 +9293,6 @@
return null;
}
final PackageParser.Activity activity = info.activity;
- if (mSafeMode && (activity.info.applicationInfo.flags
- &ApplicationInfo.FLAG_SYSTEM) == 0) {
- return null;
- }
PackageSetting ps = (PackageSetting) activity.owner.mExtras;
if (ps == null) {
return null;
@@ -9466,10 +9513,6 @@
return null;
}
final PackageParser.Service service = info.service;
- if (mSafeMode && (service.info.applicationInfo.flags
- &ApplicationInfo.FLAG_SYSTEM) == 0) {
- return null;
- }
PackageSetting ps = (PackageSetting) service.owner.mExtras;
if (ps == null) {
return null;
@@ -9689,10 +9732,6 @@
return null;
}
final PackageParser.Provider provider = info.provider;
- if (mSafeMode && (provider.info.applicationInfo.flags
- & ApplicationInfo.FLAG_SYSTEM) == 0) {
- return null;
- }
PackageSetting ps = (PackageSetting) provider.owner.mExtras;
if (ps == null) {
return null;
@@ -11120,9 +11159,12 @@
final long sizeBytes = mContainerService.calculateInstalledSize(
origin.resolvedPath, isForwardLocked(), packageAbiOverride);
- if (mInstaller.freeCache(null, sizeBytes + lowThreshold) >= 0) {
+ try {
+ mInstaller.freeCache(null, sizeBytes + lowThreshold);
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
installFlags, packageAbiOverride);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to free cache", e);
}
/*
@@ -11198,7 +11240,8 @@
* do, then we'll defer to them to verify the packages.
*/
final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage, verifierUser.getIdentifier());
+ : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+ verifierUser.getIdentifier());
if (!origin.existing && requiredUid != -1
&& isVerificationEnabled(verifierUser.getIdentifier(), installFlags)) {
final Intent verification = new Intent(
@@ -11519,11 +11562,9 @@
String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String codePath : allCodePaths) {
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- int retCode = mInstaller.rmdex(codePath, dexCodeInstructionSet);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove dex file for package at location " + codePath
- + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
+ try {
+ mInstaller.rmdex(codePath, dexCodeInstructionSet);
+ } catch (InstallerException ignored) {
}
}
}
@@ -11709,11 +11750,7 @@
return false;
}
- if (codeFile.isDirectory()) {
- mInstaller.rmPackageDir(codeFile.getAbsolutePath());
- } else {
- codeFile.delete();
- }
+ removeCodePathLI(codeFile);
if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
resourceFile.delete();
@@ -12045,8 +12082,8 @@
@Override
int doPreCopy() {
if (isFwdLocked()) {
- if (!PackageHelper.fixSdPermissions(cid,
- getPackageUid(DEFAULT_CONTAINER_PACKAGE, 0), RES_FILE_NAME)) {
+ if (!PackageHelper.fixSdPermissions(cid, getPackageUid(DEFAULT_CONTAINER_PACKAGE,
+ MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM), RES_FILE_NAME)) {
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
}
}
@@ -12090,8 +12127,11 @@
if (DEBUG_INSTALL) Slog.d(TAG, "Moving " + move.packageName + " from "
+ move.fromUuid + " to " + move.toUuid);
synchronized (mInstaller) {
- if (mInstaller.copyCompleteApp(move.fromUuid, move.toUuid, move.packageName,
- move.dataAppName, move.appId, move.seinfo) != 0) {
+ try {
+ mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName,
+ move.dataAppName, move.appId, move.seinfo);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to move app", e);
return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
}
}
@@ -12154,11 +12194,7 @@
synchronized (mInstallLock) {
// Clean up both app data and code
removeDataDirsLI(volumeUuid, move.packageName);
- if (codeFile.isDirectory()) {
- mInstaller.rmPackageDir(codeFile.getAbsolutePath());
- } else {
- codeFile.delete();
- }
+ removeCodePathLI(codeFile);
}
return true;
}
@@ -13048,6 +13084,7 @@
final int verifierUid = getPackageUid(
mIntentFilterVerifierComponent.getPackageName(),
+ MATCH_DEBUG_TRIAGED_MISSING,
(userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
mHandler.removeMessages(START_INTENT_FILTER_VERIFICATIONS);
@@ -13838,7 +13875,13 @@
outInfo.removedAppId = appId;
outInfo.removedUsers = new int[] {removeUser};
}
- mInstaller.clearUserData(ps.volumeUuid, packageName, removeUser);
+ // TODO: triage flags as part of 26466827
+ final int installerFlags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.destroyAppData(ps.volumeUuid, packageName, removeUser, installerFlags);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to delete app data", e);
+ }
removeKeystoreDataIfNeeded(removeUser, appId);
schedulePackageCleaning(packageName, removeUser, false);
synchronized (mPackages) {
@@ -14012,13 +14055,16 @@
// Always delete data directories for package, even if we found no other
// record of app. This helps users recover from UID mismatches without
// resorting to a full data wipe.
- int retCode = mInstaller.clearUserData(pkg.volumeUuid, packageName, userId);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove cache files for package " + packageName);
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.clearAppData(pkg.volumeUuid, packageName, userId, flags);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Couldn't remove cache files for package " + packageName, e);
return false;
}
- final int appId = pkg.applicationInfo.uid;
+ final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
removeKeystoreDataIfNeeded(userId, appId);
// Create a native library symlink only if we have native libraries
@@ -14027,9 +14073,11 @@
if (pkg.applicationInfo.primaryCpuAbi != null &&
!VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
- if (mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
- nativeLibPath, userId) < 0) {
- Slog.w(TAG, "Failed linking native library dir");
+ try {
+ mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
+ nativeLibPath, userId);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed linking native library dir", e);
return false;
}
}
@@ -14242,10 +14290,14 @@
Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
return false;
}
- int retCode = mInstaller.deleteCacheFiles(p.volumeUuid, packageName, userId);
- if (retCode < 0) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.clearAppData(p.volumeUuid, packageName, userId,
+ flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+ } catch (InstallerException e) {
Slog.w(TAG, "Couldn't remove cache files for package "
- + packageName + " u" + userId);
+ + packageName + " u" + userId, e);
return false;
}
return true;
@@ -14339,9 +14391,12 @@
apkPath = p.baseCodePath;
}
- int res = mInstaller.getSizeInfo(p.volumeUuid, packageName, userHandle, apkPath,
- libDirRoot, publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
- if (res < 0) {
+ // TODO: triage flags as part of 26466827
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ mInstaller.getAppSize(p.volumeUuid, packageName, userHandle, flags, apkPath,
+ libDirRoot, publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
+ } catch (InstallerException e) {
return false;
}
@@ -15679,11 +15734,14 @@
pw.print(" Required: ");
pw.print(mRequiredVerifierPackage);
pw.print(" (uid=");
- pw.print(getPackageUid(mRequiredVerifierPackage, 0));
+ pw.print(getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
pw.println(")");
} else if (mRequiredVerifierPackage != null) {
pw.print("vrfy,"); pw.print(mRequiredVerifierPackage);
- pw.print(","); pw.println(getPackageUid(mRequiredVerifierPackage, 0));
+ pw.print(",");
+ pw.println(getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
}
}
@@ -15698,11 +15756,14 @@
pw.print(" Using: ");
pw.print(verifierPackageName);
pw.print(" (uid=");
- pw.print(getPackageUid(verifierPackageName, 0));
+ pw.print(getPackageUid(verifierPackageName, MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
pw.println(")");
} else if (verifierPackageName != null) {
pw.print("ifv,"); pw.print(verifierPackageName);
- pw.print(","); pw.println(getPackageUid(verifierPackageName, 0));
+ pw.print(",");
+ pw.println(getPackageUid(verifierPackageName, MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
}
} else {
pw.println();
@@ -16550,7 +16611,11 @@
if (destroyUser) {
synchronized (mInstallLock) {
- mInstaller.removeUserDataDirs(volumeUuid, userId);
+ try {
+ mInstaller.removeUserDataDirs(volumeUuid, userId);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to clean up user dirs", e);
+ }
}
}
}
@@ -16616,11 +16681,7 @@
if (packageName != null) {
removeDataDirsLI(volumeUuid, packageName);
}
- if (file.isDirectory()) {
- mInstaller.rmPackageDir(file.getAbsolutePath());
- } else {
- file.delete();
- }
+ removeCodePathLI(file);
}
}
}
@@ -16956,7 +17017,11 @@
for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
final String volumeUuid = vol.getFsUuid();
if (DEBUG_INSTALL) Slog.d(TAG, "Removing user data on volume " + volumeUuid);
- mInstaller.removeUserDataDirs(volumeUuid, userHandle);
+ try {
+ mInstaller.removeUserDataDirs(volumeUuid, userHandle);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to remove user data", e);
+ }
}
synchronized (mPackages) {
removeUnusedPackagesLILPw(userManager, userHandle);
@@ -17019,7 +17084,11 @@
/** Called by UserManagerService */
void createNewUser(int userHandle) {
synchronized (mInstallLock) {
- mInstaller.createUserConfig(userHandle);
+ try {
+ mInstaller.createUserConfig(userHandle);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to create user config", e);
+ }
mSettings.createNewUserLI(this, mInstaller, userHandle);
}
synchronized (mPackages) {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index e7c0ef7..f106b62 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -17,6 +17,7 @@
package com.android.server.pm;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import java.io.File;
@@ -78,4 +79,11 @@
public boolean isSharedUser() {
return sharedUser != null;
}
+
+ public boolean isMatch(int flags) {
+ if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
+ return isSystem();
+ }
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 3f9ce7a..9fef515 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -81,6 +81,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
@@ -3668,7 +3669,7 @@
int userHandle) {
String[] volumeUuids;
String[] names;
- int[] uids;
+ int[] appIds;
String[] seinfos;
int packagesCount;
synchronized (mPackages) {
@@ -3676,7 +3677,7 @@
packagesCount = packages.size();
volumeUuids = new String[packagesCount];
names = new String[packagesCount];
- uids = new int[packagesCount];
+ appIds = new int[packagesCount];
seinfos = new String[packagesCount];
Iterator<PackageSetting> packagesIterator = packages.iterator();
for (int i = 0; i < packagesCount; i++) {
@@ -3690,7 +3691,7 @@
// required args and call the installer after mPackages lock has been released
volumeUuids[i] = ps.volumeUuid;
names[i] = ps.name;
- uids[i] = UserHandle.getUid(userHandle, ps.appId);
+ appIds[i] = ps.appId;
seinfos[i] = ps.pkg.applicationInfo.seinfo;
}
}
@@ -3698,7 +3699,14 @@
if (names[i] == null) {
continue;
}
- installer.createUserData(volumeUuids[i], names[i], uids[i], userHandle, seinfos[i]);
+ // TODO: triage flags!
+ final int flags = Installer.FLAG_CE_STORAGE | Installer.FLAG_DE_STORAGE;
+ try {
+ installer.createAppData(volumeUuids[i], names[i], userHandle, flags, appIds[i],
+ seinfos[i]);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to prepare app data", e);
+ }
}
synchronized (mPackages) {
applyDefaultPreferredAppsLPw(service, userHandle);
@@ -3799,63 +3807,11 @@
}
boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) {
- return isEnabledLPr(componentInfo, flags, userId)
- && isMatchLPr(componentInfo, flags);
- }
+ final PackageSetting ps = mPackages.get(componentInfo.packageName);
+ if (ps == null) return false;
- private boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
- if ((flags & MATCH_DISABLED_COMPONENTS) != 0) {
- return true;
- }
- final PackageSetting packageSettings = mPackages.get(componentInfo.packageName);
- if (PackageManagerService.DEBUG_SETTINGS) {
- Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = "
- + componentInfo.packageName + " componentName = " + componentInfo.name);
- Log.v(PackageManagerService.TAG, "enabledComponents: "
- + compToString(packageSettings.getEnabledComponents(userId)));
- Log.v(PackageManagerService.TAG, "disabledComponents: "
- + compToString(packageSettings.getDisabledComponents(userId)));
- }
- if (packageSettings == null) {
- return false;
- }
- PackageUserState ustate = packageSettings.readUserState(userId);
- if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) != 0) {
- if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
- return true;
- }
- }
- if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED
- || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
- || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
- || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
- && ustate.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
- return false;
- }
- if (ustate.enabledComponents != null
- && ustate.enabledComponents.contains(componentInfo.name)) {
- return true;
- }
- if (ustate.disabledComponents != null
- && ustate.disabledComponents.contains(componentInfo.name)) {
- return false;
- }
- return componentInfo.enabled;
- }
-
- private boolean isMatchLPr(ComponentInfo componentInfo, int flags) {
- if ((flags & MATCH_SYSTEM_ONLY) != 0) {
- final PackageSetting ps = mPackages.get(componentInfo.packageName);
- if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- return false;
- }
- }
-
- final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
- && !componentInfo.encryptionAware;
- final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
- && componentInfo.encryptionAware;
- return matchesUnaware || matchesAware;
+ final PackageUserState userState = ps.readUserState(userId);
+ return userState.isMatch(componentInfo, flags);
}
String getInstallerPackageNameLPr(String packageName) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 3d614a3..ce6b369 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -276,6 +276,8 @@
private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
new ArrayList<>();
+ private final LockPatternUtils mLockPatternUtils;
+
private static UserManagerService sInstance;
public static UserManagerService getInstance() {
@@ -320,6 +322,7 @@
}
mLocalService = new LocalService();
LocalServices.addService(UserManagerInternal.class, mLocalService);
+ mLockPatternUtils = new LockPatternUtils(mContext);
}
void systemReady() {
@@ -456,7 +459,7 @@
@Override
public int getCredentialOwnerProfile(int userHandle) {
checkManageUsersPermission("get the credential owner");
- if (!LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+ if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
synchronized (mUsersLock) {
UserInfo profileParent = getProfileParentLU(userHandle);
if (profileParent != null) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f13d964..9c629bd 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3003,6 +3003,14 @@
UserHandle.CURRENT_OR_SELF);
}
return -1;
+ } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP
+ || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
+ || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
+ if (mUseTvRouting) {
+ // On TVs volume keys never go to the foreground app.
+ dispatchDirectAudioEvent(event);
+ return -1;
+ }
} else if (KeyEvent.isMetaKey(keyCode)) {
if (down) {
mPendingMetaAction = true;
@@ -3788,7 +3796,7 @@
// size. We need to do this directly, instead of relying on
// it to bubble up from the nav bar, because this needs to
// change atomically with screen rotations.
- mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
+ mNavigationBarOnBottom = isNavigationBarOnBottom(displayWidth, displayHeight);
if (mNavigationBarOnBottom) {
// It's a system nav bar or a portrait screen; nav bar goes on bottom.
int top = displayHeight - overscanBottom
@@ -3859,6 +3867,10 @@
return false;
}
+ private boolean isNavigationBarOnBottom(int displayWidth, int displayHeight) {
+ return !mNavigationBarCanMove || displayWidth < displayHeight;
+ }
+
/** {@inheritDoc} */
@Override
public int getSystemDecorLayerLw() {
@@ -4050,7 +4062,13 @@
cf.top = vf.top = mStableTop;
cf.right = vf.right = mStableRight;
vf.bottom = mStableBottom;
- cf.bottom = mContentBottom;
+
+ if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
+ cf.bottom = mContentBottom;
+ } else {
+ cf.bottom = mDockBottom;
+ vf.bottom = mContentBottom;
+ }
} else {
// Default policy decor for the default display
@@ -5080,10 +5098,6 @@
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
- if (mUseTvRouting) {
- // On TVs volume keys never go to the foreground app
- result &= ~ACTION_PASS_TO_USER;
- }
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
if (interactive && !mScreenshotChordVolumeDownKeyTriggered
@@ -5143,19 +5157,17 @@
break;
}
}
-
- if ((result & ACTION_PASS_TO_USER) == 0) {
- if (mUseTvRouting) {
- dispatchDirectAudioEvent(event);
- } else {
- // If we aren't passing to the user and no one else
- // handled it send it to the session manager to
- // figure out.
- MediaSessionLegacyHelper.getHelper(mContext)
- .sendVolumeKeyEvent(event, true);
- }
- break;
- }
+ }
+ if (mUseTvRouting) {
+ // On TVs, defer special key handlings to
+ // {@link interceptKeyBeforeDispatching()}.
+ result |= ACTION_PASS_TO_USER;
+ } else if ((result & ACTION_PASS_TO_USER) == 0) {
+ // If we aren't passing to the user and no one else
+ // handled it send it to the session manager to
+ // figure out.
+ MediaSessionLegacyHelper.getHelper(mContext)
+ .sendVolumeKeyEvent(event, true);
}
break;
}
@@ -5931,6 +5943,22 @@
}
}
+ @Override
+ public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
+ Rect outInsets) {
+ outInsets.setEmpty();
+ if (mStatusBar != null) {
+ outInsets.top = mStatusBarHeight;
+ }
+ if (mNavigationBar != null) {
+ if (isNavigationBarOnBottom(displayWidth, displayHeight)) {
+ outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode);
+ } else {
+ outInsets.right = getNavigationBarWidth(displayRotation, mUiMode);
+ }
+ }
+ }
+
void sendCloseSystemWindows() {
PhoneWindow.sendCloseSystemWindows(mContext, null);
}
@@ -6382,6 +6410,7 @@
if (mLockScreenTimerActive != enable) {
if (enable) {
if (localLOGV) Log.v(TAG, "setting lockscreen timer");
+ mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
} else {
if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 4c7f888..e3e1097 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -23,19 +23,16 @@
import android.app.ISearchManager;
import android.app.SearchManager;
import android.app.SearchableInfo;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.os.Binder;
import android.os.Bundle;
-import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -43,9 +40,11 @@
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
+import com.android.server.SystemService;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.FileDescriptor;
@@ -53,19 +52,42 @@
import java.util.List;
/**
- * The search manager service handles the search UI, and maintains a registry of searchable
- * activities.
+ * The search manager service handles the search UI, and maintains a registry of
+ * searchable activities.
*/
public class SearchManagerService extends ISearchManager.Stub {
-
- // general debugging support
private static final String TAG = "SearchManagerService";
+ public static class Lifecycle extends SystemService {
+ private SearchManagerService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mService = new SearchManagerService(getContext());
+ publishBinderService(Context.SEARCH_SERVICE, mService);
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mService.onUnlockUser(userHandle);
+ }
+
+ @Override
+ public void onCleanupUser(int userHandle) {
+ mService.onCleanupUser(userHandle);
+ }
+ }
+
// Context that the service is running in.
private final Context mContext;
// This field is initialized lazily in getSearchables(), and then never modified.
- private final SparseArray<Searchables> mSearchables = new SparseArray<Searchables>();
+ @GuardedBy("mSearchables")
+ private final SparseArray<Searchables> mSearchables = new SparseArray<>();
/**
* Initializes the Search Manager service in the provided system context.
@@ -75,65 +97,47 @@
*/
public SearchManagerService(Context context) {
mContext = context;
- IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(new BootCompletedReceiver(), filter);
- mContext.registerReceiver(new UserReceiver(),
- new IntentFilter(Intent.ACTION_USER_REMOVED));
new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
+ new GlobalSearchProviderObserver(context.getContentResolver());
}
private Searchables getSearchables(int userId) {
- long origId = Binder.clearCallingIdentity();
+ return getSearchables(userId, false);
+ }
+
+ private Searchables getSearchables(int userId, boolean forceUpdate) {
+ final long token = Binder.clearCallingIdentity();
try {
- boolean userExists = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
- .getUserInfo(userId) != null;
- if (!userExists) return null;
+ final UserManager um = mContext.getSystemService(UserManager.class);
+ if (um.getUserInfo(userId) == null) {
+ throw new IllegalStateException("User " + userId + " doesn't exist");
+ }
+ if (!um.isUserUnlocked(userId)) {
+ throw new IllegalStateException("User " + userId + " isn't unlocked");
+ }
} finally {
- Binder.restoreCallingIdentity(origId);
+ Binder.restoreCallingIdentity(token);
}
synchronized (mSearchables) {
Searchables searchables = mSearchables.get(userId);
-
if (searchables == null) {
- //Log.i(TAG, "Building list of searchable activities for userId=" + userId);
searchables = new Searchables(mContext, userId);
- searchables.buildSearchableList();
+ searchables.updateSearchableList();
mSearchables.append(userId, searchables);
+ } else if (forceUpdate) {
+ searchables.updateSearchableList();
}
return searchables;
}
}
- private void onUserRemoved(int userId) {
- if (userId != UserHandle.USER_NULL) {
- synchronized (mSearchables) {
- mSearchables.remove(userId);
- }
- }
+ private void onUnlockUser(int userId) {
+ getSearchables(userId, true);
}
- /**
- * Creates the initial searchables list after boot.
- */
- private final class BootCompletedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- new Thread() {
- @Override
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- mContext.unregisterReceiver(BootCompletedReceiver.this);
- getSearchables(0);
- }
- }.start();
- }
- }
-
- private final class UserReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
+ private void onCleanupUser(int userId) {
+ synchronized (mSearchables) {
+ mSearchables.remove(userId);
}
}
@@ -158,7 +162,7 @@
// Update list of searchable activities
for (int i = 0; i < mSearchables.size(); i++) {
if (changingUserId == mSearchables.keyAt(i)) {
- getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+ mSearchables.valueAt(i).updateSearchableList();
break;
}
}
@@ -187,14 +191,13 @@
public void onChange(boolean selfChange) {
synchronized (mSearchables) {
for (int i = 0; i < mSearchables.size(); i++) {
- getSearchables(mSearchables.keyAt(i)).buildSearchableList();
+ mSearchables.valueAt(i).updateSearchableList();
}
}
Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
-
}
//
@@ -208,6 +211,7 @@
* @return Returns a SearchableInfo record describing the parameters of the search,
* or null if no searchable metadata was available.
*/
+ @Override
public SearchableInfo getSearchableInfo(final ComponentName launchActivity) {
if (launchActivity == null) {
Log.e(TAG, "getSearchableInfo(), activity == null");
@@ -219,10 +223,12 @@
/**
* Returns a list of the searchable activities that can be included in global search.
*/
+ @Override
public List<SearchableInfo> getSearchablesInGlobalSearch() {
return getSearchables(UserHandle.getCallingUserId()).getSearchablesInGlobalSearchList();
}
+ @Override
public List<ResolveInfo> getGlobalSearchActivities() {
return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivities();
}
@@ -230,6 +236,7 @@
/**
* Gets the name of the global search activity.
*/
+ @Override
public ComponentName getGlobalSearchActivity() {
return getSearchables(UserHandle.getCallingUserId()).getGlobalSearchActivity();
}
@@ -237,6 +244,7 @@
/**
* Gets the name of the web search activity.
*/
+ @Override
public ComponentName getWebSearchActivity() {
return getSearchables(UserHandle.getCallingUserId()).getWebSearchActivity();
}
diff --git a/services/core/java/com/android/server/search/Searchables.java b/services/core/java/com/android/server/search/Searchables.java
index 0ffbb7d..0046fbb 100644
--- a/services/core/java/com/android/server/search/Searchables.java
+++ b/services/core/java/com/android/server/search/Searchables.java
@@ -200,7 +200,7 @@
*
* TODO: sort the list somehow? UI choice.
*/
- public void buildSearchableList() {
+ public void updateSearchableList() {
// These will become the new values at the end of the method
HashMap<ComponentName, SearchableInfo> newSearchablesMap
= new HashMap<ComponentName, SearchableInfo>();
@@ -215,11 +215,13 @@
long ident = Binder.clearCallingIdentity();
try {
- searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);
+ searchList = queryIntentActivities(intent,
+ PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
List<ResolveInfo> webSearchInfoList;
final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
- webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
+ webSearchInfoList = queryIntentActivities(webSearchIntent,
+ PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
// analyze each one, generate a Searchables record, and record
if (searchList != null || webSearchInfoList != null) {
@@ -282,8 +284,8 @@
// Step 1 : Query the package manager for a list
// of activities that can handle the GLOBAL_SEARCH intent.
Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
- List<ResolveInfo> activities =
- queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ List<ResolveInfo> activities = queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
if (activities != null && !activities.isEmpty()) {
// Step 2: Rank matching activities according to our heuristics.
Collections.sort(activities, GLOBAL_SEARCH_RANKER);
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index d888c56..42b8721 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -290,14 +290,9 @@
}
public void setDeviceLockedForUser(int userId, boolean locked) {
- if (LockPatternUtils.isSeparateWorkChallengeEnabled()) {
- UserInfo info = mUserManager.getUserInfo(userId);
- if (info.isManagedProfile()) {
- synchronized (mDeviceLockedForUser) {
- mDeviceLockedForUser.put(userId, locked);
- }
- } else {
- Log.wtf(TAG, "Requested to change lock state for non-profile user " + userId);
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ synchronized (mDeviceLockedForUser) {
+ mDeviceLockedForUser.put(userId, locked);
}
}
}
@@ -669,7 +664,7 @@
public boolean isDeviceLocked(int userId) throws RemoteException {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false /* allowAll */, true /* requireFull */, "isDeviceLocked", null);
- if (!LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+ if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
userId = resolveProfileParent(userId);
}
@@ -680,13 +675,13 @@
public boolean isDeviceSecure(int userId) throws RemoteException {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false /* allowAll */, true /* requireFull */, "isDeviceSecure", null);
- if (!LockPatternUtils.isSeparateWorkChallengeEnabled()) {
- userId = resolveProfileParent(userId);
- }
long token = Binder.clearCallingIdentity();
try {
- return new LockPatternUtils(mContext).isSecure(userId);
+ if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ userId = resolveProfileParent(userId);
+ }
+ return mLockPatternUtils.isSecure(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index a035826..ebbb8b3 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -116,7 +116,7 @@
public void close() {
synchronized (mLock) {
- if (mPtr != 0l) {
+ if (mPtr != 0L) {
nativeClose(mPtr);
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index d814ebf..3193ff8 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -465,7 +465,7 @@
try {
context = mContext.createPackageContextAsUser("android", 0, user);
} catch (NameNotFoundException e) {
- Slog.e(TAG, "failed to create package contenxt as user " + user);
+ Slog.e(TAG, "failed to create package context as user " + user);
context = mContext;
}
return context.getContentResolver();
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 7be0ead..c3a6f5d 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -291,15 +291,24 @@
// If the user has chosen provider, use that
for (WebViewProviderInfo provider : providers) {
- if (provider.packageName.equals(userChosenProvider)) {
+ if (provider.packageName.equals(userChosenProvider) && provider.isEnabled()) {
return provider.getPackageInfo();
}
}
- // User did not choose, or the choice failed, use the most stable provider available
+ // 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 (WebViewProviderInfo provider : providers) {
+ if (provider.isAvailableByDefault() && provider.isEnabled()) {
+ return provider.getPackageInfo();
+ }
+ }
+
+ // Could not find any enabled package either, use the most stable provider.
for (WebViewProviderInfo provider : providers) {
return provider.getPackageInfo();
}
+
mAnyWebViewInstalled = false;
throw new WebViewFactory.MissingWebViewPackageException(
"Could not find a loadable WebView package");
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 51787b0..a9025bd 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -393,7 +393,7 @@
}
mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
}
- if (task.isDockedInEffect() && !task.isResizeable()) {
+ if (task.isTwoFingerScrollMode()) {
stack.getBounds(mTmpRect);
mNonResizeableRegion.op(mTmpRect, Region.Op.UNION);
break;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b4ddebc..6bb3e20 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -558,8 +558,9 @@
}
boolean isResizeableByDockedStack() {
- return mStack != null && getDisplayContent().getDockedStackLocked() != null &&
- StackId.isTaskResizeableByDockedStack(mStack.mStackId);
+ final DisplayContent displayContent = getDisplayContent();
+ return displayContent != null && displayContent.getDockedStackLocked() != null
+ && mStack != null && StackId.isTaskResizeableByDockedStack(mStack.mStackId);
}
/**
@@ -570,6 +571,10 @@
return inDockedWorkspace() || isResizeableByDockedStack();
}
+ boolean isTwoFingerScrollMode() {
+ return isDockedInEffect() && !isResizeable();
+ }
+
WindowState getTopVisibleAppMainWindow() {
final AppWindowToken token = getTopVisibleAppToken();
return token != null ? token.findMainWindow() : null;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index fc6ad70..27d6e03 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -26,6 +26,9 @@
import android.view.DisplayInfo;
import android.view.Surface;
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
+import com.android.internal.policy.DockedDividerUtils;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -85,6 +88,7 @@
/** Detach this stack from its display when animation completes. */
boolean mDeferDetach;
+ private boolean mUpdateBoundsAfterRotation = false;
TaskStack(WindowManagerService service, int stackId) {
mService = service;
@@ -126,7 +130,7 @@
Configuration config = configs.get(task.mTaskId);
if (config != null) {
Rect bounds = taskBounds.get(task.mTaskId);
- if (!task.isResizeable() && task.isDockedInEffect()) {
+ if (task.isTwoFingerScrollMode()) {
// This is a non-resizeable task that's docked (or side-by-side to the docked
// stack). It might have been scrolled previously, and after the stack resizing,
// it might no longer fully cover the stack area.
@@ -235,6 +239,7 @@
}
void updateDisplayInfo(Rect bounds) {
+ mUpdateBoundsAfterRotation = false;
if (mDisplayContent != null) {
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
@@ -244,20 +249,72 @@
} else if (mFullscreen) {
setBounds(null);
} else {
+ mUpdateBoundsAfterRotation = true;
mTmpRect2.set(mBounds);
- mDisplayContent.rotateBounds(
- mRotation, mDisplayContent.getDisplayInfo().rotation, mTmpRect2);
- if (setBounds(mTmpRect2)) {
- // Post message to inform activity manager of the bounds change simulating
- // a one-way call. We do this to prevent a deadlock between window manager
- // lock and activity manager lock been held.
- mService.mH.sendMessage(mService.mH.obtainMessage(
- RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mBounds));
+ final int newRotation = mDisplayContent.getDisplayInfo().rotation;
+ if (mRotation == newRotation) {
+ setBounds(mTmpRect2);
}
+
+ // If the rotation changes, we'll handle it in updateBoundsAfterRotation
}
}
}
+ /**
+ * Updates the bounds after rotating the screen. We can't handle it in
+ * {@link #updateDisplayInfo} because at that point the configuration might not be fully updated
+ * yet.
+ */
+ void updateBoundsAfterRotation() {
+ if (!mUpdateBoundsAfterRotation) {
+ return;
+ }
+ mUpdateBoundsAfterRotation = false;
+ final int newRotation = getDisplayInfo().rotation;
+ mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
+ if (mStackId == DOCKED_STACK_ID) {
+ snapDockedStackAfterRotation(mTmpRect2);
+ }
+
+ // Post message to inform activity manager of the bounds change simulating
+ // a one-way call. We do this to prevent a deadlock between window manager
+ // lock and activity manager lock been held.
+ mService.mH.sendMessage(mService.mH.obtainMessage(
+ RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2));
+ }
+
+ /**
+ * Snaps the bounds after rotation to the closest snap target for the docked stack.
+ */
+ private void snapDockedStackAfterRotation(Rect outBounds) {
+
+ // Calculate the current position.
+ final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+ final int dividerSize = mService.getDefaultDisplayContentLocked()
+ .getDockedDividerController().getContentWidth();
+ final int dockSide = getDockSide(outBounds);
+ final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
+ dockSide, dividerSize);
+ final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
+ final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
+
+ // Snap the position to a target.
+ final int rotation = displayInfo.rotation;
+ final int orientation = mService.mCurConfiguration.orientation;
+ mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
+ final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
+ mService.mContext.getResources(),
+ 0 /* minFlingVelocityPxPerSecond */, displayWidth, displayHeight,
+ dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds);
+ final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
+
+ // Recalculate the bounds based on the position of the target.
+ DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
+ outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
+ dividerSize);
+ }
+
boolean isAnimating() {
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
@@ -682,6 +739,10 @@
* information which side of the screen was the dock anchored.
*/
int getDockSide() {
+ return getDockSide(mBounds);
+ }
+
+ int getDockSide(Rect bounds) {
if (mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId)) {
return DOCKED_INVALID;
}
@@ -692,14 +753,14 @@
final int orientation = mService.mCurConfiguration.orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// Portrait mode, docked either at the top or the bottom.
- if (mBounds.top - mTmpRect.top < mTmpRect.bottom - mBounds.bottom) {
+ if (bounds.top - mTmpRect.top < mTmpRect.bottom - bounds.bottom) {
return DOCKED_TOP;
} else {
return DOCKED_BOTTOM;
}
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Landscape mode, docked either on the left or on the right.
- if (mBounds.left - mTmpRect.left < mTmpRect.right - mBounds.right) {
+ if (bounds.left - mTmpRect.left < mTmpRect.right - bounds.right) {
return DOCKED_LEFT;
} else {
return DOCKED_RIGHT;
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index 98033f6..3dc512f 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -34,13 +34,7 @@
import static android.view.PointerIcon.STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;
public class TaskTapPointerEventListener implements PointerEventListener {
- private static final int TAP_TIMEOUT_MSEC = 300;
- private static final float TAP_MOTION_SLOP_INCHES = 0.125f;
- private final int mMotionSlop;
- private float mDownX;
- private float mDownY;
- private int mPointerId;
final private Region mTouchExcludeRegion = new Region();
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
@@ -55,8 +49,6 @@
DisplayContent displayContent) {
mService = service;
mDisplayContent = displayContent;
- DisplayInfo info = displayContent.getDisplayInfo();
- mMotionSlop = (int)(info.logicalDensityDpi * TAP_MOTION_SLOP_INCHES);
}
// initialize the object, note this must be done outside WindowManagerService
@@ -74,31 +66,19 @@
final int action = motionEvent.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
- mPointerId = motionEvent.getPointerId(0);
- mDownX = motionEvent.getX();
- mDownY = motionEvent.getY();
+ final int x = (int) motionEvent.getX();
+ final int y = (int) motionEvent.getY();
- final int x = (int) mDownX;
- final int y = (int) mDownY;
synchronized (this) {
if (!mTouchExcludeRegion.contains(x, y)) {
- mService.mH.obtainMessage(H.TAP_DOWN_OUTSIDE_TASK, x, y,
- mDisplayContent).sendToTarget();
+ mService.mH.obtainMessage(H.TAP_OUTSIDE_TASK,
+ x, y, mDisplayContent).sendToTarget();
}
}
break;
}
case MotionEvent.ACTION_MOVE: {
- if (mPointerId >= 0) {
- int index = motionEvent.findPointerIndex(mPointerId);
- if ((motionEvent.getEventTime() - motionEvent.getDownTime()) > TAP_TIMEOUT_MSEC
- || index < 0
- || Math.abs(motionEvent.getX(index) - mDownX) > mMotionSlop
- || Math.abs(motionEvent.getY(index) - mDownY) > mMotionSlop) {
- mPointerId = -1;
- }
- }
if (motionEvent.getPointerCount() != 2) {
stopTwoFingerScroll();
}
@@ -149,24 +129,6 @@
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP: {
- int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
- >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- // Extract the index of the pointer that left the touch sensor
- if (mPointerId == motionEvent.getPointerId(index)) {
- final int x = (int)motionEvent.getX(index);
- final int y = (int)motionEvent.getY(index);
- synchronized(this) {
- if ((motionEvent.getEventTime() - motionEvent.getDownTime())
- < TAP_TIMEOUT_MSEC
- && Math.abs(x - mDownX) < mMotionSlop
- && Math.abs(y - mDownY) < mMotionSlop
- && !mTouchExcludeRegion.contains(x, y)) {
- mService.mH.obtainMessage(H.TAP_OUTSIDE_TASK, x, y,
- mDisplayContent).sendToTarget();
- }
- }
- mPointerId = -1;
- }
stopTwoFingerScroll();
break;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2477acd..7d142ec 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -119,6 +119,7 @@
import com.android.internal.R;
import com.android.internal.app.IAssistScreenshotReceiver;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -1990,6 +1991,10 @@
}
}
+ // If the window is being added to a task that's docked but non-resizeable,
+ // we need to update this new window's scroll position when it's added.
+ win.applyScrollIfNeeded();
+
if (type == TYPE_DOCK_DIVIDER) {
getDefaultDisplayContentLocked().getDockedDividerController().setWindow(win);
}
@@ -2977,7 +2982,7 @@
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
Animation a = mAppTransition.loadAnimation(lp, transit, enter,
mCurConfiguration.orientation, frame, insets, surfaceInsets, isVoiceInteraction,
- freeform, atoken.mTask.mTaskId);
+ !fullscreen, atoken.mTask.mTaskId);
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = null;
@@ -3523,6 +3528,7 @@
}
}
+ @Override
public void setNewConfiguration(Configuration config) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setNewConfiguration()")) {
@@ -3536,10 +3542,20 @@
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
}
+ if (orientationChanged) {
+ updateTaskStackBoundsAfterRotation();
+ }
mWindowPlacerLocked.performSurfacePlacement();
}
}
+ private void updateTaskStackBoundsAfterRotation() {
+ for (int stackNdx = mStackIdToStack.size() - 1; stackNdx >= 0; stackNdx--) {
+ final TaskStack stack = mStackIdToStack.valueAt(stackNdx);
+ stack.updateBoundsAfterRotation();
+ }
+ }
+
@Override
public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
@@ -7163,18 +7179,25 @@
} catch(RemoteException e) {}
}
- private void startResizingTask(DisplayContent displayContent, int startX, int startY) {
- Task task = null;
+ private void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
+ int taskId = -1;
synchronized (mWindowMap) {
- task = displayContent.findTaskForControlPoint(startX, startY);
- if (task == null || !startPositioningLocked(
- task.getTopVisibleAppMainWindow(), true /*resize*/, startX, startY)) {
- return;
+ final Task task = displayContent.findTaskForControlPoint(x, y);
+ if (task != null) {
+ if (!startPositioningLocked(
+ task.getTopVisibleAppMainWindow(), true /*resize*/, x, y)) {
+ return;
+ }
+ taskId = task.mTaskId;
+ } else {
+ taskId = displayContent.taskIdFromPoint(x, y);
}
}
- try {
- mActivityManager.setFocusedTask(task.mTaskId);
- } catch(RemoteException e) {}
+ if (taskId >= 0) {
+ try {
+ mActivityManager.setFocusedTask(taskId);
+ } catch(RemoteException e) {}
+ }
}
private boolean startPositioningLocked(
@@ -7489,18 +7512,17 @@
public static final int RESET_ANR_MESSAGE = 38;
public static final int WALLPAPER_DRAW_PENDING_TIMEOUT = 39;
- public static final int TAP_DOWN_OUTSIDE_TASK = 40;
- public static final int FINISH_TASK_POSITIONING = 41;
+ public static final int FINISH_TASK_POSITIONING = 40;
- public static final int UPDATE_DOCKED_STACK_DIVIDER = 42;
+ public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
- public static final int RESIZE_STACK = 43;
- public static final int RESIZE_TASK = 44;
+ public static final int RESIZE_STACK = 42;
+ public static final int RESIZE_TASK = 43;
- public static final int TWO_FINGER_SCROLL_START = 45;
- public static final int SHOW_NON_RESIZEABLE_DOCK_TOAST = 46;
+ public static final int TWO_FINGER_SCROLL_START = 44;
+ public static final int SHOW_NON_RESIZEABLE_DOCK_TOAST = 45;
- public static final int WINDOW_REPLACEMENT_TIMEOUT = 47;
+ public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
/**
* Used to denote that an integer field in a message will not be used.
@@ -7954,27 +7976,13 @@
}
break;
- case TAP_OUTSIDE_TASK: {
- int taskId;
- synchronized (mWindowMap) {
- taskId = ((DisplayContent)msg.obj).taskIdFromPoint(msg.arg1, msg.arg2);
- }
- if (taskId >= 0) {
- try {
- mActivityManager.setFocusedTask(taskId);
- } catch (RemoteException e) {
- }
- }
- }
- break;
-
case TWO_FINGER_SCROLL_START: {
startScrollingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
}
break;
- case TAP_DOWN_OUTSIDE_TASK: {
- startResizingTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
+ case TAP_OUTSIDE_TASK: {
+ handleTapOutsideTask((DisplayContent)msg.obj, msg.arg1, msg.arg2);
}
break;
@@ -10262,6 +10270,14 @@
listener);
}
+ @Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) {
+ try {
+ getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver);
+ } catch (RemoteException e) {
+ }
+ }
+
private final class LocalService extends WindowManagerInternal {
@Override
public void requestTraversalFromDisplayManager() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b7fd60f..058fa67 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1458,15 +1458,24 @@
}
boolean inDockedWorkspace() {
- Task task = getTask();
+ final Task task = getTask();
return task != null && task.inDockedWorkspace();
}
boolean isDockedInEffect() {
- Task task = getTask();
+ final Task task = getTask();
return task != null && task.isDockedInEffect();
}
+ void applyScrollIfNeeded() {
+ final Task task = getTask();
+ if (task != null && task.isTwoFingerScrollMode()) {
+ task.getDimBounds(mTmpRect);
+ mXOffset = mTmpRect.left;
+ mYOffset = mTmpRect.top;
+ }
+ }
+
int getTouchableRegion(Region region, int flags) {
final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
if (modal && mAppToken != null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index dd58b3c..c4d5c50 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -254,6 +254,7 @@
final IPackageManager mIPackageManager;
final UserManager mUserManager;
final UserManagerInternal mUserManagerInternal;
+ private final LockPatternUtils mLockPatternUtils;
final LocalService mLocalService;
@@ -388,6 +389,7 @@
private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
private static final String TAG_DISABLE_CAMERA = "disable-camera";
private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
+ private static final String TAG_DISABLE_CONTACTS_SEARCH = "disable-contacts-search";
private static final String TAG_DISABLE_BLUETOOTH_CONTACT_SHARING
= "disable-bt-contacts-sharing";
private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
@@ -476,6 +478,7 @@
boolean encryptionRequested = false;
boolean disableCamera = false;
boolean disableCallerId = false;
+ boolean disableContactsSearch = false;
boolean disableBluetoothContactSharing = true;
boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
boolean requireAutoTime = false; // Can only be set by a device owner.
@@ -638,6 +641,11 @@
out.attribute(null, ATTR_VALUE, Boolean.toString(disableCallerId));
out.endTag(null, TAG_DISABLE_CALLER_ID);
}
+ if (disableContactsSearch) {
+ out.startTag(null, TAG_DISABLE_CONTACTS_SEARCH);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(disableContactsSearch));
+ out.endTag(null, TAG_DISABLE_CONTACTS_SEARCH);
+ }
if (disableBluetoothContactSharing) {
out.startTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
out.attribute(null, ATTR_VALUE,
@@ -809,6 +817,9 @@
} else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
disableCallerId = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CONTACTS_SEARCH.equals(tag)) {
+ disableContactsSearch = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_DISABLE_BLUETOOTH_CONTACT_SHARING.equals(tag)) {
disableBluetoothContactSharing = Boolean.parseBoolean(parser
.getAttributeValue(null, ATTR_VALUE));
@@ -1034,6 +1045,8 @@
pw.println(disableCamera);
pw.print(prefix); pw.print("disableCallerId=");
pw.println(disableCallerId);
+ pw.print(prefix); pw.print("disableContactsSearch=");
+ pw.println(disableContactsSearch);
pw.print(prefix); pw.print("disableBluetoothContactSharing=");
pw.println(disableBluetoothContactSharing);
pw.print(prefix); pw.print("disableScreenCapture=");
@@ -1317,6 +1330,7 @@
mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
mLocalService = new LocalService();
+ mLockPatternUtils = new LockPatternUtils(mContext);
mHasFeature = mContext.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
@@ -1808,7 +1822,7 @@
if (!mHasFeature) {
return null;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
Intent resolveIntent = new Intent();
resolveIntent.setComponent(adminName);
List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceiversAsUser(
@@ -2411,7 +2425,7 @@
Bundle onEnableData) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
DevicePolicyData policy = getUserData(userHandle);
DeviceAdminInfo info = findAdmin(adminReceiver, userHandle,
@@ -2457,7 +2471,7 @@
if (!mHasFeature) {
return false;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
}
@@ -2468,7 +2482,7 @@
if (!mHasFeature) {
return false;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
DevicePolicyData policyData = getUserData(userHandle);
return policyData.mRemovingAdmins.contains(adminReceiver);
@@ -2480,7 +2494,7 @@
if (!mHasFeature) {
return false;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (administrator == null) {
@@ -2497,7 +2511,7 @@
return Collections.EMPTY_LIST;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
DevicePolicyData policy = getUserData(userHandle);
final int N = policy.mAdminList.size();
@@ -2517,7 +2531,7 @@
if (!mHasFeature) {
return false;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
DevicePolicyData policy = getUserData(userHandle);
final int N = policy.mAdminList.size();
@@ -2535,7 +2549,7 @@
if (!mHasFeature) {
return;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin == null) {
@@ -2561,10 +2575,16 @@
}
}
- private boolean isAdminApiLevelPreN(@NonNull ComponentName who, int userHandle) {
+ private boolean isAdminApiLevelMOrBelow(@NonNull ComponentName who, int userHandle) {
DeviceAdminInfo adminInfo = findAdmin(who, userHandle, false);
return adminInfo.getActivityInfo().applicationInfo.targetSdkVersion
- < Build.VERSION_CODES.N;
+ <= Build.VERSION_CODES.M;
+ }
+
+ @Override
+ public boolean isSeparateProfileChallengeAllowed(int userHandle) {
+ ComponentName profileOwner = getProfileOwner(userHandle);
+ return !isAdminApiLevelMOrBelow(profileOwner, userHandle);
}
@Override
@@ -2594,7 +2614,7 @@
if (!mHasFeature) {
return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
@@ -2606,7 +2626,7 @@
return admin != null ? admin.passwordQuality : mode;
}
- if (LockPatternUtils.isSeparateWorkChallengeEnabled() && !parent) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle) && !parent) {
// If a Work Challenge is in use, only return its restrictions.
DevicePolicyData policy = getUserDataUnchecked(userHandle);
final int N = policy.mAdminList.size();
@@ -2626,7 +2646,7 @@
// Only aggregate data for the parent profile plus the non-work challenge
// enabled profiles.
if (!(userInfo.isManagedProfile()
- && LockPatternUtils.isSeparateWorkChallengeEnabled())) {
+ && mLockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id))) {
DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
@@ -2664,7 +2684,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -2711,7 +2731,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -2771,7 +2791,7 @@
if (!mHasFeature) {
return 0L;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
long timeout = 0L;
@@ -2898,7 +2918,7 @@
if (!mHasFeature) {
return 0L;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
return getPasswordExpirationLocked(who, userHandle);
}
@@ -2926,7 +2946,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -2970,7 +2990,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -3017,7 +3037,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -3067,7 +3087,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -3117,7 +3137,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -3167,7 +3187,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int length = 0;
@@ -3200,7 +3220,7 @@
if (!mHasFeature) {
return true;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
int id = getCredentialOwner(userHandle);
@@ -3212,8 +3232,8 @@
getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
ComponentName adminComponentName = admin.info.getComponent();
// TODO: Include the Admin sdk level check in LockPatternUtils check.
- ComponentName who = !isAdminApiLevelPreN(adminComponentName, userHandle)
- && LockPatternUtils.isSeparateWorkChallengeEnabled()
+ ComponentName who = !isAdminApiLevelMOrBelow(adminComponentName, userHandle)
+ && mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)
? adminComponentName : null;
if (policy.mActivePasswordQuality < getPasswordQuality(who, userHandle, parent)
|| policy.mActivePasswordLength < getPasswordMinimumLength(null, userHandle)) {
@@ -3272,7 +3292,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
ActiveAdmin admin = (who != null) ? getActiveAdminUncheckedLocked(who, userHandle)
: getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle);
@@ -3285,7 +3305,7 @@
if (!mHasFeature) {
return UserHandle.USER_NULL;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
ActiveAdmin admin = getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle);
return admin != null ? admin.getUserHandle().getIdentifier() : UserHandle.USER_NULL;
@@ -3584,7 +3604,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
long time = 0;
@@ -3906,7 +3926,7 @@
return;
}
final int userHandle = mInjector.userHandleGetCallingUserId();
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
@@ -3985,7 +4005,7 @@
if (!mHasFeature) {
return;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
@@ -4014,9 +4034,9 @@
if (!mHasFeature) {
return;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
// Managed Profile password can only be changed when per user encryption is present.
- if (!LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+ if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
enforceNotManagedProfile(userHandle, "set the active password");
}
@@ -4043,7 +4063,7 @@
setExpirationAlarmCheckLocked(mContext, policy);
// Send a broadcast to each profile using this password as its primary unlock.
- if (LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
sendAdminCommandLocked(
DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
@@ -4083,7 +4103,7 @@
@Override
public void reportFailedPasswordAttempt(int userHandle) {
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
enforceNotManagedProfile(userHandle, "report failed password attempt");
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
@@ -4125,7 +4145,7 @@
@Override
public void reportSuccessfulPasswordAttempt(int userHandle) {
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
@@ -4209,7 +4229,7 @@
if (!mHasFeature) {
return null;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized(this) {
DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
// Scan through active admins and find if anyone has already
@@ -4346,7 +4366,7 @@
if (!mHasFeature) {
return false;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
// Check for permissions if a particular caller is specified
if (who != null) {
@@ -4376,7 +4396,7 @@
if (!mHasFeature) {
// Ok to return current status.
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
return getEncryptionStatus();
}
@@ -4624,7 +4644,7 @@
if (!mHasFeature) {
return 0;
}
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
long ident = mInjector.binderClearCallingIdentity();
try {
synchronized (this) {
@@ -4635,10 +4655,9 @@
UserInfo user = mUserManager.getUserInfo(userHandle);
final List<UserInfo> profiles;
- if (user.isManagedProfile() || LockPatternUtils.isSeparateWorkChallengeEnabled()) {
- // If we are being asked about a managed profile or the main user profile has a
- // separate lock from the work profile, just return keyguard features disabled
- // by admins in the profile.
+ if (user.isManagedProfile()) {
+ // If we are being asked about a managed profile, just return keyguard features
+ // disabled by admins in the profile.
profiles = Collections.singletonList(user);
} else {
// Otherwise return those set by admins in the user
@@ -4657,9 +4676,11 @@
// If we are being asked explictly about this user
// return all disabled features even if its a managed profile.
which |= admin.disabledKeyguardFeatures;
- } else {
+ } else if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(
+ userInfo.id)) {
// Otherwise a managed profile is only allowed to disable
- // some features on the parent user.
+ // some features on the parent user, and we only aggregate them if
+ // it doesn't have its own challenge.
which |= (admin.disabledKeyguardFeatures
& PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER);
}
@@ -5185,17 +5206,28 @@
}
}
- private void enforceCrossUserPermission(int userHandle) {
+ private void enforceFullCrossUsersPermission(int userHandle) {
+ enforceSystemUserOrPermission(userHandle,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ }
+
+ private void enforceCrossUsersPermission(int userHandle) {
+ enforceSystemUserOrPermission(userHandle,
+ android.Manifest.permission.INTERACT_ACROSS_USERS);
+ }
+
+ private void enforceSystemUserOrPermission(int userHandle, String permission) {
if (userHandle < 0) {
throw new IllegalArgumentException("Invalid userId " + userHandle);
}
final int callingUid = mInjector.binderGetCallingUid();
- if (userHandle == UserHandle.getUserId(callingUid)) return;
+ if (userHandle == UserHandle.getUserId(callingUid)) {
+ return;
+ }
if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
|| callingUid == Process.ROOT_UID)) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
- + " INTERACT_ACROSS_USERS_FULL permission");
+ mContext.enforceCallingOrSelfPermission(permission,
+ "Must be system or have " + permission + " permission");
}
}
@@ -5405,7 +5437,7 @@
return null;
}
Preconditions.checkNotNull(agent, "agent null");
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
final String componentName = agent.flattenToString();
@@ -6068,7 +6100,7 @@
@Override
public Bundle getUserRestrictions(ComponentName who, int userHandle) {
Preconditions.checkNotNull(who, "ComponentName is null");
- enforceCrossUserPermission(userHandle);
+ enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
ActiveAdmin activeAdmin = getActiveAdminUncheckedLocked(who, userHandle);
if (activeAdmin == null) {
@@ -6260,7 +6292,7 @@
@Override
public String[] getAccountTypesWithManagementDisabledAsUser(int userId) {
- enforceCrossUserPermission(userId);
+ enforceFullCrossUsersPermission(userId);
if (!mHasFeature) {
return null;
}
@@ -6332,7 +6364,7 @@
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (admin.disableCallerId != disabled) {
admin.disableCallerId = disabled;
- saveSettingsLocked(UserHandle.getCallingUserId());
+ saveSettingsLocked(mInjector.userHandleGetCallingUserId());
}
}
}
@@ -6352,8 +6384,7 @@
@Override
public boolean getCrossProfileCallerIdDisabledForUser(int userId) {
- // TODO: Should there be a check to make sure this relationship is within a profile group?
- //enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system");
+ enforceCrossUsersPermission(userId);
synchronized (this) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableCallerId : false;
@@ -6361,6 +6392,44 @@
}
@Override
+ public void setCrossProfileContactsSearchDisabled(ComponentName who, boolean disabled) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ if (admin.disableContactsSearch != disabled) {
+ admin.disableContactsSearch = disabled;
+ saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ }
+ }
+ }
+
+ @Override
+ public boolean getCrossProfileContactsSearchDisabled(ComponentName who) {
+ if (!mHasFeature) {
+ return false;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ return admin.disableContactsSearch;
+ }
+ }
+
+ @Override
+ public boolean getCrossProfileContactsSearchDisabledForUser(int userId) {
+ enforceCrossUsersPermission(userId);
+ synchronized (this) {
+ ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
+ return (admin != null) ? admin.disableContactsSearch : false;
+ }
+ }
+
+ @Override
public void startManagedQuickContact(String actualLookupKey, long actualContactId,
long actualDirectoryId, Intent originalIntent) {
final Intent intent = QuickContact.rebuildManagedQuickContactsIntent(
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index dd6493c..79786d3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -45,7 +45,6 @@
import android.util.EventLog;
import android.util.Slog;
import android.view.WindowManager;
-import android.webkit.WebViewFactory;
import com.android.internal.R;
import com.android.internal.os.BinderInternal;
@@ -68,6 +67,7 @@
import com.android.server.lights.LightsService;
import com.android.server.media.MediaRouterService;
import com.android.server.media.MediaSessionService;
+import com.android.server.media.MediaResourceMonitorService;
import com.android.server.media.projection.MediaProjectionManagerService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
@@ -81,7 +81,6 @@
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.restrictions.RestrictionsManagerService;
-import com.android.server.search.SearchManagerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
import com.android.server.telecom.TelecomLoaderService;
@@ -138,6 +137,9 @@
"com.android.server.job.JobSchedulerService";
private static final String MOUNT_SERVICE_CLASS =
"com.android.server.MountService$Lifecycle";
+ private static final String SEARCH_MANAGER_SERVICE_CLASS =
+ "com.android.server.search.SearchManagerService$Lifecycle";
+
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
/**
@@ -844,8 +846,7 @@
if (!disableNonCoreServices) {
traceBeginAndSlog("StartSearchManagerService");
try {
- ServiceManager.addService(Context.SEARCH_SERVICE,
- new SearchManagerService(context));
+ mSystemServiceManager.startService(SEARCH_MANAGER_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting Search Service", e);
}
@@ -1025,6 +1026,10 @@
mSystemServiceManager.startService(TvInputManagerService.class);
}
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
+ mSystemServiceManager.startService(MediaResourceMonitorService.class);
+ }
+
if (!disableNonCoreServices) {
traceBeginAndSlog("StartMediaRouterService");
try {
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 00e1acb..5abb6e7 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -16,6 +16,9 @@
package com.android.server.print;
+import static android.content.pm.PackageManager.GET_SERVICES;
+import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+
import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -61,7 +64,6 @@
* Context.PRINT_SERVICE.
* PrintManager implementation is contained within.
*/
-
public final class PrintManagerService extends SystemService {
private final PrintManagerImpl mPrintManagerImpl;
@@ -553,8 +555,14 @@
// to handle it as the change may affect ongoing print jobs.
UserState userState = getOrCreateUserStateLocked(getChangingUserId());
boolean stoppedSomePackages = false;
- Iterator<PrintServiceInfo> iterator = userState.getEnabledPrintServices()
- .iterator();
+
+ List<PrintServiceInfo> enabledServices = userState
+ .getEnabledPrintServices();
+ if (enabledServices == null) {
+ return false;
+ }
+
+ Iterator<PrintServiceInfo> iterator = enabledServices.iterator();
while (iterator.hasNext()) {
ComponentName componentName = iterator.next().getComponentName();
String componentPackage = componentName.getPackageName();
@@ -586,7 +594,8 @@
intent.setPackage(packageName);
List<ResolveInfo> installedServices = mContext.getPackageManager()
- .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES,
+ .queryIntentServicesAsUser(intent,
+ GET_SERVICES | MATCH_DEBUG_TRIAGED_MISSING,
getChangingUserId());
if (installedServices != null) {
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index dcc02a3..78edc4d 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -16,12 +16,16 @@
package com.android.server.print;
+import static android.content.pm.PackageManager.GET_META_DATA;
+import static android.content.pm.PackageManager.GET_SERVICES;
+import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+
+import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
-import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Icon;
@@ -333,7 +337,7 @@
mSpooler.setPrintJobState(printJobId, PrintJobInfo.STATE_QUEUED, null);
}
- public List<PrintServiceInfo> getEnabledPrintServices() {
+ public @Nullable List<PrintServiceInfo> getEnabledPrintServices() {
synchronized (mLock) {
List<PrintServiceInfo> enabledServices = null;
final int installedServiceCount = mInstalledServices.size();
@@ -676,8 +680,8 @@
Set<PrintServiceInfo> tempPrintServices = new HashSet<PrintServiceInfo>();
List<ResolveInfo> installedServices = mContext.getPackageManager()
- .queryIntentServicesAsUser(mQueryIntent, PackageManager.GET_SERVICES
- | PackageManager.GET_META_DATA, mUserId);
+ .queryIntentServicesAsUser(mQueryIntent,
+ GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING, mUserId);
final int installedCount = installedServices.size();
for (int i = 0, count = installedCount; i < count; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 27deb72..27d5207 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -59,6 +59,7 @@
import android.os.MessageQueue.IdleHandler;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.LogPrinter;
@@ -1504,4 +1505,10 @@
ka3.stop();
callback3.expectStopped();
}
+
+ @SmallTest
+ public void testGetCaptivePortalServerUrl() throws Exception {
+ String url = mCm.getCaptivePortalServerUrl();
+ assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java b/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java
index 79b9135..0f9bf2f 100644
--- a/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java
+++ b/services/tests/servicestests/src/com/android/server/search/SearchablesTest.java
@@ -72,7 +72,7 @@
public void testNonSearchable() {
// test basic array & hashmap
Searchables searchables = new Searchables(mContext, 0);
- searchables.buildSearchableList();
+ searchables.updateSearchableList();
// confirm that we return null for non-searchy activities
ComponentName nonActivity = new ComponentName(
@@ -104,7 +104,7 @@
// build item list with real-world source data
mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_PASSTHROUGH);
Searchables searchables = new Searchables(mockContext, 0);
- searchables.buildSearchableList();
+ searchables.updateSearchableList();
// tests with "real" searchables (deprecate, this should be a unit test)
ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList();
int count = searchablesList.size();
@@ -123,7 +123,7 @@
mockPM.setSearchablesMode(MyMockPackageManager.SEARCHABLES_MOCK_ZERO);
Searchables searchables = new Searchables(mockContext, 0);
- searchables.buildSearchableList();
+ searchables.updateSearchableList();
ArrayList<SearchableInfo> searchablesList = searchables.getSearchablesList();
assertNotNull(searchablesList);
MoreAsserts.assertEmpty(searchablesList);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 23e8894..e27441e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -418,7 +418,8 @@
private void notifyBatteryStats(String packageName, int userId, boolean idle) {
try {
- int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId);
+ final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
if (idle) {
mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE,
packageName, uid);
@@ -614,9 +615,8 @@
// the sync adapter is a system package.
try {
PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo(
- packageName, 0, userId);
- if (pi == null || pi.applicationInfo == null
- || !pi.applicationInfo.isSystemApp()) {
+ packageName, PackageManager.MATCH_SYSTEM_ONLY, userId);
+ if (pi == null || pi.applicationInfo == null) {
continue;
}
if (!packageName.equals(providerPkgName)) {
@@ -863,8 +863,8 @@
List<ApplicationInfo> apps;
try {
- ParceledListSlice<ApplicationInfo> slice
- = AppGlobals.getPackageManager().getInstalledApplications(0, userId);
+ ParceledListSlice<ApplicationInfo> slice = AppGlobals.getPackageManager()
+ .getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
if (slice == null) {
return new int[0];
}
@@ -1266,8 +1266,8 @@
"No permission to change app idle state");
final long token = Binder.clearCallingIdentity();
try {
- PackageInfo pi = AppGlobals.getPackageManager()
- .getPackageInfo(packageName, 0, userId);
+ PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
if (pi == null) return;
UsageStatsService.this.setAppIdle(packageName, idle, userId);
} catch (RemoteException re) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 72621a4..630367d 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -59,6 +59,7 @@
private final Context mContext;
private final UsageStatsDatabase mDatabase;
private final IntervalStats[] mCurrentStats;
+ private IntervalStats mAppIdleRollingWindow;
private boolean mStatsChanged = false;
private final UnixCalendar mDailyExpiryDate;
private final StatsUpdatedListener mListener;
@@ -137,6 +138,8 @@
initializeDefaultsForApps(currentTimeMillis, deviceUsageTime,
mDatabase.isFirstUpdate());
}
+
+ refreshAppIdleRollingWindow(currentTimeMillis);
}
/**
@@ -170,6 +173,7 @@
persistActiveStats();
mDatabase.onTimeChanged(newTime - oldTime);
loadActiveStats(newTime, resetBeginIdleTime);
+ refreshAppIdleRollingWindow(newTime);
}
void reportEvent(UsageEvents.Event event, long deviceUsageTime) {
@@ -211,6 +215,11 @@
}
}
+ if (event.mEventType != Event.CONFIGURATION_CHANGE) {
+ mAppIdleRollingWindow.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ mAppIdleRollingWindow.updateBeginIdleTime(event.mPackage, deviceUsageTime);
+ }
+
notifyStatsChanged();
}
@@ -222,6 +231,7 @@
for (IntervalStats stats : mCurrentStats) {
stats.updateBeginIdleTime(packageName, beginIdleTime);
}
+ mAppIdleRollingWindow.updateBeginIdleTime(packageName, beginIdleTime);
notifyStatsChanged();
}
@@ -229,6 +239,7 @@
for (IntervalStats stats : mCurrentStats) {
stats.updateSystemLastUsedTime(packageName, lastUsedTime);
}
+ mAppIdleRollingWindow.updateSystemLastUsedTime(packageName, lastUsedTime);
notifyStatsChanged();
}
@@ -387,9 +398,8 @@
}
long getBeginIdleTime(String packageName) {
- final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY];
UsageStats packageUsage;
- if ((packageUsage = yearly.packageStats.get(packageName)) == null) {
+ if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) {
return -1;
} else {
return packageUsage.getBeginIdleTime();
@@ -397,9 +407,8 @@
}
long getSystemLastUsedTime(String packageName) {
- final IntervalStats yearly = mCurrentStats[UsageStatsManager.INTERVAL_YEARLY];
UsageStats packageUsage;
- if ((packageUsage = yearly.packageStats.get(packageName)) == null) {
+ if ((packageUsage = mAppIdleRollingWindow.packageStats.get(packageName)) == null) {
return -1;
} else {
return packageUsage.getLastTimeSystemUsed();
@@ -461,6 +470,8 @@
}
persistActiveStats();
+ refreshAppIdleRollingWindow(currentTimeMillis);
+
final long totalTime = SystemClock.elapsedRealtime() - startTime;
Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime
+ " milliseconds");
@@ -503,6 +514,7 @@
}
}
}
+
mStatsChanged = false;
updateRolloverDeadline();
}
@@ -516,6 +528,68 @@
mDailyExpiryDate.getTimeInMillis() + ")");
}
+ private static void mergePackageStats(IntervalStats dst, IntervalStats src) {
+ dst.endTime = Math.max(dst.endTime, src.endTime);
+
+ final int srcPackageCount = src.packageStats.size();
+ for (int i = 0; i < srcPackageCount; i++) {
+ final String packageName = src.packageStats.keyAt(i);
+ final UsageStats srcStats = src.packageStats.valueAt(i);
+ final UsageStats dstStats = dst.packageStats.get(packageName);
+ if (dstStats == null) {
+ dst.packageStats.put(packageName, new UsageStats(srcStats));
+ } else {
+ dstStats.add(src.packageStats.valueAt(i));
+ }
+ }
+ }
+
+ /**
+ * Merges all the stats into the first element of the resulting list.
+ */
+ private static final StatCombiner<IntervalStats> sPackageStatsMerger =
+ new StatCombiner<IntervalStats>() {
+ @Override
+ public void combine(IntervalStats stats, boolean mutable,
+ List<IntervalStats> accumulatedResult) {
+ IntervalStats accum;
+ if (accumulatedResult.isEmpty()) {
+ accum = new IntervalStats();
+ accum.beginTime = stats.beginTime;
+ accumulatedResult.add(accum);
+ } else {
+ accum = accumulatedResult.get(0);
+ }
+
+ mergePackageStats(accum, stats);
+ }
+ };
+
+ /**
+ * App idle operates on a rolling window of time. When we roll over time, we end up with a
+ * period of time where in-memory stats are empty and we don't hit the disk for older stats
+ * for performance reasons. Suddenly all apps will become idle.
+ *
+ * Instead, at times we do a deep query to find all the apps that have run in the past few
+ * days and keep the cached data up to date.
+ *
+ * @param currentTimeMillis
+ */
+ void refreshAppIdleRollingWindow(long currentTimeMillis) {
+ // Start the rolling window for AppIdle requests.
+ List<IntervalStats> stats = mDatabase.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
+ currentTimeMillis - (1000 * 60 * 60 * 24 * 2), currentTimeMillis,
+ sPackageStatsMerger);
+
+ if (stats == null || stats.isEmpty()) {
+ mAppIdleRollingWindow = new IntervalStats();
+ mergePackageStats(mAppIdleRollingWindow,
+ mCurrentStats[UsageStatsManager.INTERVAL_YEARLY]);
+ } else {
+ mAppIdleRollingWindow = stats.get(0);
+ }
+ }
+
//
// -- DUMP related methods --
//
@@ -538,6 +612,9 @@
pw.println(" stats");
printIntervalStats(pw, mCurrentStats[interval], screenOnTime, true);
}
+
+ pw.println("AppIdleRollingWindow cache");
+ printIntervalStats(pw, mAppIdleRollingWindow, screenOnTime, true);
}
private String formatDateTime(long dateTime, boolean pretty) {
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index b18af33..b56ce73 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -687,7 +687,7 @@
.append("] PhoneAccount: ")
.append(mAccountHandle)
.append(" Capabilities: ")
- .append(mCapabilities)
+ .append(capabilitiesToString(mCapabilities))
.append(" Schemes: ");
for (String scheme : mSupportedUriSchemes) {
sb.append(scheme)
@@ -698,4 +698,42 @@
sb.append("]");
return sb.toString();
}
+
+ /**
+ * Generates a string representation of a capabilities bitmask.
+ *
+ * @param capabilities The capabilities bitmask.
+ * @return String representation of the capabilities bitmask.
+ */
+ private String capabilitiesToString(int capabilities) {
+ StringBuilder sb = new StringBuilder();
+ if (hasCapabilities(CAPABILITY_VIDEO_CALLING)) {
+ sb.append("Video ");
+ }
+ if (hasCapabilities(CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
+ sb.append("Presence ");
+ }
+ if (hasCapabilities(CAPABILITY_CALL_PROVIDER)) {
+ sb.append("CallProvider ");
+ }
+ if (hasCapabilities(CAPABILITY_CALL_SUBJECT)) {
+ sb.append("CallSubject ");
+ }
+ if (hasCapabilities(CAPABILITY_CONNECTION_MANAGER)) {
+ sb.append("ConnectionMgr ");
+ }
+ if (hasCapabilities(CAPABILITY_EMERGENCY_CALLS_ONLY)) {
+ sb.append("EmergOnly ");
+ }
+ if (hasCapabilities(CAPABILITY_MULTI_USER)) {
+ sb.append("MultiUser ");
+ }
+ if (hasCapabilities(CAPABILITY_PLACE_EMERGENCY_CALLS)) {
+ sb.append("PlaceEmerg ");
+ }
+ if (hasCapabilities(CAPABILITY_SIM_SUBSCRIPTION)) {
+ sb.append("SimSub ");
+ }
+ return sb.toString();
+ }
}
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index dabf706..216603c 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -16,13 +16,23 @@
package android.telecom;
+import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Represents attributes of video calls.
*/
public class VideoProfile implements Parcelable {
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({QUALITY_UNKNOWN, QUALITY_HIGH, QUALITY_MEDIUM, QUALITY_LOW, QUALITY_DEFAULT})
+ public @interface VideoQuality {}
+
/**
* "Unknown" video quality.
* @hide
@@ -48,6 +58,14 @@
*/
public static final int QUALITY_DEFAULT = 4;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ flag = true,
+ value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL,
+ STATE_PAUSED})
+ public @interface VideoState {}
+
/**
* Used when answering or dialing a call to indicate that the call does not have a video
* component.
@@ -107,7 +125,7 @@
*
* @param videoState The video state.
*/
- public VideoProfile(int videoState) {
+ public VideoProfile(@VideoState int videoState) {
this(videoState, QUALITY_DEFAULT);
}
@@ -117,7 +135,7 @@
* @param videoState The video state.
* @param quality The video quality.
*/
- public VideoProfile(int videoState, int quality) {
+ public VideoProfile(@VideoState int videoState, @VideoQuality int quality) {
mVideoState = videoState;
mQuality = quality;
}
@@ -130,6 +148,7 @@
* {@link VideoProfile#STATE_RX_ENABLED},
* {@link VideoProfile#STATE_PAUSED}.
*/
+ @VideoState
public int getVideoState() {
return mVideoState;
}
@@ -139,6 +158,7 @@
* Valid values: {@link VideoProfile#QUALITY_HIGH}, {@link VideoProfile#QUALITY_MEDIUM},
* {@link VideoProfile#QUALITY_LOW}, {@link VideoProfile#QUALITY_DEFAULT}.
*/
+ @VideoQuality
public int getQuality() {
return mQuality;
}
@@ -211,7 +231,7 @@
* @param videoState The video state.
* @return String representation of the video state.
*/
- public static String videoStateToString(int videoState) {
+ public static String videoStateToString(@VideoState int videoState) {
StringBuilder sb = new StringBuilder();
sb.append("Audio");
@@ -240,7 +260,7 @@
* @param videoState The video state.
* @return {@code True} if the video state is audio only, {@code false} otherwise.
*/
- public static boolean isAudioOnly(int videoState) {
+ public static boolean isAudioOnly(@VideoState int videoState) {
return !hasState(videoState, VideoProfile.STATE_TX_ENABLED)
&& !hasState(videoState, VideoProfile.STATE_RX_ENABLED);
}
@@ -251,7 +271,7 @@
* @param videoState The video state.
* @return {@code True} if video transmission or reception is enabled, {@code false} otherwise.
*/
- public static boolean isVideo(int videoState) {
+ public static boolean isVideo(@VideoState int videoState) {
return hasState(videoState, VideoProfile.STATE_TX_ENABLED)
|| hasState(videoState, VideoProfile.STATE_RX_ENABLED)
|| hasState(videoState, VideoProfile.STATE_BIDIRECTIONAL);
@@ -263,7 +283,7 @@
* @param videoState The video state.
* @return {@code True} if video transmission is enabled, {@code false} otherwise.
*/
- public static boolean isTransmissionEnabled(int videoState) {
+ public static boolean isTransmissionEnabled(@VideoState int videoState) {
return hasState(videoState, VideoProfile.STATE_TX_ENABLED);
}
@@ -273,7 +293,7 @@
* @param videoState The video state.
* @return {@code True} if video reception is enabled, {@code false} otherwise.
*/
- public static boolean isReceptionEnabled(int videoState) {
+ public static boolean isReceptionEnabled(@VideoState int videoState) {
return hasState(videoState, VideoProfile.STATE_RX_ENABLED);
}
@@ -283,7 +303,7 @@
* @param videoState The video state.
* @return {@code True} if the video is bi-directional, {@code false} otherwise.
*/
- public static boolean isBidirectional(int videoState) {
+ public static boolean isBidirectional(@VideoState int videoState) {
return hasState(videoState, VideoProfile.STATE_BIDIRECTIONAL);
}
@@ -293,7 +313,7 @@
* @param videoState The video state.
* @return {@code True} if the video is paused, {@code false} otherwise.
*/
- public static boolean isPaused(int videoState) {
+ public static boolean isPaused(@VideoState int videoState) {
return hasState(videoState, VideoProfile.STATE_PAUSED);
}
@@ -304,7 +324,7 @@
* @param state The state to check.
* @return {@code True} if the state is set.
*/
- private static boolean hasState(int videoState, int state) {
+ private static boolean hasState(@VideoState int videoState, @VideoState int state) {
return (videoState & state) == state;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6ffc026..80c5b1e 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -473,6 +473,15 @@
public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
/**
+ * Determine whether user can switch Wi-Fi preferred or Cellular preferred in calling preference.
+ * Some operators support Wi-Fi Calling only, not VoLTE.
+ * They don't need "Cellular preferred" option.
+ * In this case, set uneditalbe attribute for preferred preference.
+ * @hide
+ */
+ public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool";
+
+ /**
* If this is true, the SIM card (through Customer Service Profile EF file) will be able to
* prevent manual operator selection. If false, this SIM setting will be ignored and manual
* operator selection will always be available. See CPHS4_2.WW6, CPHS B.4.7.1 for more
@@ -553,6 +562,23 @@
public static final String BOOL_ALLOW_VIDEO_PAUSE =
"bool_allow_video_pause";
+
+ /**
+ * Flag indicating whether the carrier supports RCS presence indication for video calls. When
+ * {@code true}, the carrier supports RCS presence indication for video calls. When presence
+ * is supported, the device should use the
+ * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} bit mask and set the
+ * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit to indicate
+ * whether each contact supports video calling. The UI is made aware that presence is enabled
+ * via {@link android.telecom.PhoneAccount#CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE}
+ * and can choose to hide or show the video calling icon based on whether a contact supports
+ * video.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -628,6 +654,7 @@
sDefaults.putBoolean(KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, false);
sDefaults.putBoolean(BOOL_ALLOW_EMERGENCY_VIDEO_CALLS, false);
sDefaults.putBoolean(BOOL_ALLOW_VIDEO_PAUSE, true);
+ sDefaults.putBoolean(KEY_EDITABLE_WFC_MODE_BOOL, true);
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
@@ -662,6 +689,7 @@
sDefaults.putString(KEY_MMS_UA_PROF_URL_STRING, "");
sDefaults.putString(KEY_MMS_USER_AGENT_STRING, "");
sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true);
+ sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 9998937..39f3213 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -24,6 +24,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Looper;
import android.telephony.Rlog;
import android.os.Handler;
import android.os.Message;
@@ -347,7 +348,31 @@
* for #onSubscriptionsChanged to be invoked.
*/
public static class OnSubscriptionsChangedListener {
- private final Handler mHandler = new Handler() {
+ private final Handler mHandler;
+
+ public OnSubscriptionsChangedListener() {
+ mHandler = new OnSubscriptionsChangedListenerHandler();
+ }
+
+ /**
+ * Contructor that takes in looper as parameter in case a subclass/instantiation needs
+ * to use a specific looper (like in tests where mainLooper may need to be used).
+ * @param looper Looper to be used for mHandler
+ * @hide
+ */
+ protected OnSubscriptionsChangedListener(Looper looper) {
+ mHandler = new OnSubscriptionsChangedListenerHandler(looper);
+ }
+
+ private class OnSubscriptionsChangedListenerHandler extends Handler {
+ private OnSubscriptionsChangedListenerHandler() {
+ super();
+ }
+
+ private OnSubscriptionsChangedListenerHandler(Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
if (DBG) {
@@ -355,7 +380,7 @@
}
OnSubscriptionsChangedListener.this.onSubscriptionsChanged();
}
- };
+ }
/**
* Callback invoked when there is any change to any SubscriptionInfo. Typically
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 5381e4ef6..81aa6c6 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -149,7 +149,14 @@
@Override
public ApplicationInfo getApplicationInfo(String packageName, int flags)
- throws NameNotFoundException {
+ throws NameNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
+ @Override
+ public ApplicationInfo getApplicationInfoAsUser(String packageName, int flags, int userId)
+ throws NameNotFoundException {
throw new UnsupportedOperationException();
}
@@ -315,21 +322,25 @@
throw new UnsupportedOperationException();
}
+ /** @hide */
@Override
public byte[] getEphemeralCookie() {
return new byte[0];
}
+ /** @hide */
@Override
public boolean isEphemeralApplication() {
return false;
}
+ /** @hide */
@Override
public int getEphemeralCookieMaxSizeBytes() {
return 0;
}
+ /** @hide */
@Override
public boolean setEphemeralCookie(@NonNull byte[] cookie) {
return false;
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index fecfdf9..3a30230 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -175,7 +175,7 @@
.setTopic(new Notification.Topic("hello", "Hello"))
.build();
- mNM.notify(999, n);
+ mNM.notify(70, n);
}
},
@@ -194,7 +194,7 @@
.setStyle(picture)
.build();
- mNM.notify(9999, n);
+ mNM.notify(71, n);
}
},
new Test("with topic Bananas") {
@@ -211,10 +211,28 @@
.setTopic(new Notification.Topic("bananas", "Bananas"))
.build();
- mNM.notify(999, n);
+ mNM.notify(72, n);
}
},
+ new Test("with delete intent") {
+ public void run() {
+ Notification.BigTextStyle bigText = new Notification.BigTextStyle();
+ bigText.bigText("bananas are great\nso tasty\nyum\nyum\nyum\n");
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon1)
+ .setStyle(bigText)
+ .setWhen(mActivityCreateTime)
+ .setContentTitle("bananananana")
+ .setContentText("This is a banana!!!")
+ .setTopic(new Notification.Topic("bananas", "Bananas"))
+ .setDeleteIntent(makeIntent2())
+ .build();
+
+ mNM.notify(73, n);
+ }
+ },
+
new Test("Whens") {
public void run()
{
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index e1f9642..5e7d3ec 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -582,10 +582,15 @@
if (formatted && translateable) {
if (!util::verifyJavaStringFormat(*stringValue->value)) {
- mDiag->error(DiagMessage(outResource->source)
- << "multiple substitutions specified in non-positional format; "
- "did you mean to add the formatted=\"false\" attribute?");
- return false;
+ DiagMessage msg(outResource->source);
+ msg << "multiple substitutions specified in non-positional format; "
+ "did you mean to add the formatted=\"false\" attribute?";
+ if (mOptions.errorOnPositionalArguments) {
+ mDiag->error(msg);
+ return false;
+ }
+
+ mDiag->warn(msg);
}
}
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 9ad749e..51cbbe1 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -44,6 +44,11 @@
* Whether the default setting for this parser is to allow translation.
*/
bool translatable = true;
+
+ /**
+ * Whether positional arguments in formatted strings are treated as errors or warnings.
+ */
+ bool errorOnPositionalArguments = true;
};
/*
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp
index b3b0f65..c78670f 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/compile/Compile.cpp
@@ -107,6 +107,7 @@
Maybe<std::string> resDir;
std::vector<std::u16string> products;
bool pseudolocalize = false;
+ bool legacyMode = false;
bool verbose = false;
};
@@ -192,6 +193,7 @@
ResourceParserOptions parserOptions;
parserOptions.products = options.products;
+ parserOptions.errorOnPositionalArguments = !options.legacyMode;
// If the filename includes donottranslate, then the default translatable is false.
parserOptions.translatable = pathData.name.find(u"donottranslate") == std::string::npos;
@@ -438,6 +440,8 @@
.optionalFlag("--dir", "Directory to scan for resources", &options.resDir)
.optionalSwitch("--pseudo-localize", "Generate resources for pseudo-locales "
"(en-XA and ar-XB)", &options.pseudolocalize)
+ .optionalSwitch("--legacy", "Treat errors that used to be valid in AAPT as warnings",
+ &options.legacyMode)
.optionalSwitch("-v", "Enables verbose logging", &options.verbose);
if (!flags.parse("aapt2 compile", args, &std::cerr)) {
return 1;
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 652e52f..8a87d96 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -228,29 +228,53 @@
return {};
}
+ /**
+ * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked.
+ * Postcondition: ResourceTable has only one package left. All others are stripped, or there
+ * is an error and false is returned.
+ */
bool verifyNoExternalPackages() {
+ auto isExtPackageFunc = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
+ return mContext.getCompilationPackage() != pkg->name ||
+ !pkg->id ||
+ pkg->id.value() != mContext.getPackageId();
+ };
+
bool error = false;
for (const auto& package : mFinalTable.packages) {
- if (mContext.getCompilationPackage() != package->name ||
- !package->id || package->id.value() != mContext.getPackageId()) {
+ if (isExtPackageFunc(package)) {
// We have a package that is not related to the one we're building!
for (const auto& type : package->types) {
for (const auto& entry : type->entries) {
+ ResourceNameRef resName(package->name, type->type, entry->name);
+
for (const auto& configValue : entry->values) {
- mContext.getDiagnostics()->error(
- DiagMessage(configValue.value->getSource())
- << "defined resource '"
- << ResourceNameRef(package->name,
- type->type,
- entry->name)
- << "' for external package '"
- << package->name << "'");
- error = true;
+ // Special case the occurrence of an ID that is being generated for the
+ // 'android' package. This is due to legacy reasons.
+ if (valueCast<Id>(configValue.value.get()) &&
+ package->name == u"android") {
+ mContext.getDiagnostics()->warn(
+ DiagMessage(configValue.value->getSource())
+ << "generated id '" << resName
+ << "' for external package '" << package->name
+ << "'");
+ } else {
+ mContext.getDiagnostics()->error(
+ DiagMessage(configValue.value->getSource())
+ << "defined resource '" << resName
+ << "' for external package '" << package->name
+ << "'");
+ error = true;
+ }
}
}
}
}
}
+
+ auto newEndIter = std::remove_if(mFinalTable.packages.begin(), mFinalTable.packages.end(),
+ isExtPackageFunc);
+ mFinalTable.packages.erase(newEndIter, mFinalTable.packages.end());
return !error;
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 31dd3d9..db4c6dc6 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -327,12 +327,19 @@
return null;
}
- // let the framework inflate the ColorStateList from the XML file.
- File f = new File(value);
- if (f.isFile()) {
- try {
- XmlPullParser parser = ParserFactory.create(f);
+ try {
+ // Get the state list file content from callback to parse PSI file
+ XmlPullParser parser = mContext.getLayoutlibCallback().getXmlFileParser(value);
+ if (parser == null) {
+ // If used with a version of Android Studio that does not implement getXmlFileParser
+ // fall back to reading the file from disk
+ File f = new File(value);
+ if (f.isFile()) {
+ parser = ParserFactory.create(f);
+ }
+ }
+ if (parser != null) {
BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
parser, mContext, resValue.isFramework());
try {
@@ -341,18 +348,18 @@
} finally {
blockParser.ensurePopped();
}
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e, null);
- return null;
- } catch (Exception e) {
- // this is an error and not warning since the file existence is checked before
- // attempting to parse it.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e, null);
-
- return null;
}
+ } catch (XmlPullParserException e) {
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Failed to configure parser for " + value, e, null);
+ return null;
+ } catch (Exception e) {
+ // this is an error and not warning since the file existence is checked before
+ // attempting to parse it.
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+ "Failed to parse file " + value, e, null);
+
+ return null;
}
try {
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index 60514b6..8d5863b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -122,4 +122,35 @@
/*package*/ static boolean nativeIsSeekable(FileDescriptor fd) {
return true;
}
+
+ /**
+ * Set the newly decoded bitmap's density based on the Options.
+ *
+ * Copied from {@link BitmapFactory#setDensityFromOptions(Bitmap, Options)}.
+ */
+ @LayoutlibDelegate
+ /*package*/ static void setDensityFromOptions(Bitmap outputBitmap, Options opts) {
+ if (outputBitmap == null || opts == null) return;
+
+ final int density = opts.inDensity;
+ if (density != 0) {
+ outputBitmap.setDensity(density);
+ final int targetDensity = opts.inTargetDensity;
+ if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
+ return;
+ }
+
+ // --- Change from original implementation begins ---
+ // LayoutLib doesn't scale the nine patch when decoding it. Hence, don't change the
+ // density of the source bitmap in case of ninepatch.
+
+ if (opts.inScaled) {
+ // --- Change from original implementation ends. ---
+ outputBitmap.setDensity(targetDensity);
+ }
+ } else if (opts.inBitmap != null) {
+ // bitmap was reused, ensure density is reset
+ outputBitmap.setDensity(Bitmap.getDefaultDensity());
+ }
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 4625de2..08258c9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -145,6 +145,12 @@
}
@Override
+ public ApplicationInfo getApplicationInfoAsUser(String packageName, int flags, int userId)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
public ActivityInfo getActivityInfo(ComponentName component, int flags)
throws NameNotFoundException {
return null;
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index 2b86bfb..d8ead23 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
new file mode 100644
index 0000000..65d1dc5
--- /dev/null
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 2dca07c..dea86bf 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -305,6 +305,11 @@
renderAndVerify("array_check.xml", "array_check.png");
}
+ @Test
+ public void testAllWidgetsTablet() throws ClassNotFoundException {
+ renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012);
+ }
+
@AfterClass
public static void tearDown() {
sLayoutLibLog = null;
@@ -423,6 +428,16 @@
*/
private void renderAndVerify(String layoutFileName, String goldenFileName)
throws ClassNotFoundException {
+ renderAndVerify(layoutFileName, goldenFileName, ConfigGenerator.NEXUS_5);
+ }
+
+ /**
+ * Create a new rendering session and test that rendering given layout on given device
+ * doesn't throw any exceptions and matches the provided image.
+ */
+ private void renderAndVerify(String layoutFileName, String goldenFileName,
+ ConfigGenerator deviceConfig)
+ throws ClassNotFoundException {
// Create the layout pull parser.
LayoutPullParser parser = new LayoutPullParser(APP_TEST_RES + "/layout/" + layoutFileName);
// Create LayoutLibCallback.
@@ -430,7 +445,7 @@
layoutLibCallback.initResources();
// TODO: Set up action bar handler properly to test menu rendering.
// Create session params.
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
+ SessionParams params = getSessionParams(parser, deviceConfig,
layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
renderAndVerify(params, goldenFileName);
}
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java
index 8e0cec6..34fc726 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java
@@ -126,6 +126,21 @@
.setSoftButtons(true)
.setNavigation(Navigation.NONAV);
+ public static final ConfigGenerator NEXUS_7_2012 = new ConfigGenerator()
+ .setScreenHeight(1280)
+ .setScreenWidth(800)
+ .setXdpi(195)
+ .setYdpi(200)
+ .setOrientation(ScreenOrientation.PORTRAIT)
+ .setDensity(Density.TV)
+ .setRatio(ScreenRatio.NOTLONG)
+ .setSize(ScreenSize.LARGE)
+ .setKeyboard(Keyboard.NOKEY)
+ .setTouchScreen(TouchScreen.FINGER)
+ .setKeyboardState(KeyboardState.SOFT)
+ .setSoftButtons(true)
+ .setNavigation(Navigation.NONAV);
+
private static final String TAG_ATTR = "attr";
private static final String TAG_ENUM = "enum";
private static final String TAG_FLAG = "flag";
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 3ca7590..6e6ad8f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -166,6 +166,7 @@
"android.content.res.TypedArray#getValueAt",
"android.content.res.TypedArray#obtain",
"android.graphics.BitmapFactory#finishDecode",
+ "android.graphics.BitmapFactory#setDensityFromOptions",
"android.graphics.drawable.GradientDrawable#buildRing",
"android.graphics.Typeface#getSystemFontConfigLocation",
"android.os.Handler#sendMessageAtTime",