Merge "Fix path position in BakedOpDispatcher"
diff --git a/api/current.txt b/api/current.txt
index 6c49041..b748a89 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 {
@@ -6133,6 +6166,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();
@@ -6150,6 +6184,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
@@ -6163,6 +6199,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);
@@ -6223,6 +6260,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();
@@ -6230,6 +6269,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
@@ -27189,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();
@@ -27213,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
@@ -31327,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";
@@ -33569,6 +33616,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";
}
@@ -39076,7 +39124,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);
diff --git a/api/system-current.txt b/api/system-current.txt
index 3ede80a..f7a6841 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 {
@@ -6347,6 +6381,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 +6399,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 +6414,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 +6475,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 +6484,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
@@ -29179,7 +29225,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 +29249,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 +33509,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";
@@ -35705,6 +35753,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";
}
@@ -41424,7 +41473,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);
diff --git a/api/test-current.txt b/api/test-current.txt
index 306cf73..1e044ba 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 {
@@ -6135,6 +6168,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();
@@ -6152,6 +6186,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
@@ -6165,6 +6201,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);
@@ -6225,6 +6262,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();
@@ -6232,6 +6271,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
@@ -27197,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();
@@ -27221,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
@@ -31339,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";
@@ -33583,6 +33630,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";
}
@@ -39092,7 +39140,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);
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/app/Activity.java b/core/java/android/app/Activity.java
index 64642ac..34527c2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2843,16 +2843,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/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4531a74..81e00ff 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
}
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/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/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..84f6f3d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4021,13 +4021,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 +4044,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/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..f41928e 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);
@@ -3119,7 +3303,7 @@
*
* @see #isEphemeralApplication()
* @see #getEphemeralCookieMaxSizeBytes()
- * @see #getEphemeralCookie();
+ * @see #getEphemeralCookie()
*/
public abstract boolean setEphemeralCookie(@NonNull byte[] cookie);
@@ -3165,19 +3349,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 +3395,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 +3435,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 +3472,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 +3521,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 +3559,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 +3593,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 +3638,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 +3670,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 +3704,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 +3779,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 +3812,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 +3844,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 +3886,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 +3923,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 +3945,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,28 +4368,37 @@
*
* @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) {
@@ -3944,211 +4417,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 +4690,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 +4794,6 @@
*
* @hide
*/
- // @SystemApi
public void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {
freeStorageAndNotify(null, freeStorageSize, observer);
}
@@ -4561,28 +4885,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 +5177,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 +5247,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..1349662 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();
@@ -4623,6 +4620,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 +4877,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/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 515e9a2..cabc6fa 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -23,7 +23,6 @@
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 +45,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
@@ -1611,7 +1610,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/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..d4c9944 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -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/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/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/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/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/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..cea9867 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1616,14 +1616,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 +1639,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 +1820,7 @@
}
final ThreadedRenderer renderer = getHardwareRenderer();
if (renderer != null) {
+ loadBackgroundDrawablesIfNeeded();
mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState));
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/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 6d3c7d7..e162810 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -498,6 +498,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));
@@ -1637,6 +1653,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},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e8054fc..75077df 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" />
@@ -1069,6 +1070,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. -->
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/public.xml b/core/res/res/values/public.xml
index ebb1b37..acea461 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2688,6 +2688,7 @@
<public type="attr" name="tickMark" />
<public type="attr" name="tickMarkTint" />
<public type="attr" name="tickMarkTintMode" />
+ <public type="attr" name="canPerformGestures" />
<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/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c658675..a092408 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -176,6 +176,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 +264,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 +897,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 +1170,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.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index c59d1c7..7bfd7ca 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -624,6 +624,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();
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 693a519..dbb7661 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -52,6 +52,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);
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/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/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 7f710fc..180a48e 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;
@@ -218,6 +220,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 +321,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 +333,11 @@
}
updateActionBar();
- invalidateOptionsMenu();
+
+ // Prevents searchView from being recreated while searching
+ if (!mSearchManager.isSearching()) {
+ invalidateOptionsMenu();
+ }
}
final List<String> getExcludedAuthorities() {
@@ -720,7 +729,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 +747,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 +803,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 +820,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 +833,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 +872,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/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..898713f 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();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/EmptyDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/EmptyDocumentHolder.java
index ab67a5b..d1f8ff7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/EmptyDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/EmptyDocumentHolder.java
@@ -18,22 +18,33 @@
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.
- final int gridMargin = context.getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
- itemView.setMinimumHeight(gridMargin * 2);
+ 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) {
- // Nothing to bind.
+ 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 0359d68..3ee1d42 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
@@ -76,6 +76,8 @@
public void onBindViewHolder(DocumentHolder holder, int p, List<Object> payload) {
if (holder.getItemViewType() != ITEM_TYPE_SECTION_BREAK) {
mDelegate.onBindViewHolder(holder, toDelegatePosition(p), payload);
+ } else {
+ ((EmptyDocumentHolder)holder).bind(mEnv.getDisplayState());
}
}
@@ -83,6 +85,8 @@
public void onBindViewHolder(DocumentHolder holder, int p) {
if (holder.getItemViewType() != ITEM_TYPE_SECTION_BREAK) {
mDelegate.onBindViewHolder(holder, toDelegatePosition(p));
+ } else {
+ ((EmptyDocumentHolder)holder).bind(mEnv.getDisplayState());
}
}
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/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..6179b4b 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -69,10 +69,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..2f94e1e 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -69,10 +69,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..29767c3 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -73,14 +73,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..3316b30 100644
--- a/packages/PrintSpooler/res/values-az-rAZ/strings.xml
+++ b/packages/PrintSpooler/res/values-az-rAZ/strings.xml
@@ -69,10 +69,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..86baf10 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -70,11 +70,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..2c02b74 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -69,10 +69,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..d48d91d 100644
--- a/packages/PrintSpooler/res/values-bn-rBD/strings.xml
+++ b/packages/PrintSpooler/res/values-bn-rBD/strings.xml
@@ -69,10 +69,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..d0fd75e 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -69,10 +69,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..bec34ac 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -71,12 +71,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..de29146 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -69,10 +69,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..054454e 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -69,10 +69,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..abae961 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -69,10 +69,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..b656dcd 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -69,10 +69,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..b656dcd 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -69,10 +69,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..b656dcd 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -69,10 +69,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..712bb80 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -69,10 +69,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..dfd6a62 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -69,10 +69,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..7b962af 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -69,10 +69,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..4551cc2 100644
--- a/packages/PrintSpooler/res/values-eu-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-eu-rES/strings.xml
@@ -69,10 +69,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..d85978d 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -69,10 +69,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..4472459 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -69,10 +69,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..1d45315 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -69,10 +69,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..df7dfef 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -69,10 +69,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..eae6450 100644
--- a/packages/PrintSpooler/res/values-gl-rES/strings.xml
+++ b/packages/PrintSpooler/res/values-gl-rES/strings.xml
@@ -69,10 +69,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..8028274 100644
--- a/packages/PrintSpooler/res/values-gu-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-gu-rIN/strings.xml
@@ -69,10 +69,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..5bfcc6e 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -69,10 +69,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..bf244c5 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -70,11 +70,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..6c608f1 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -69,10 +69,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..801410b 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -69,10 +69,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..227a372 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -69,10 +69,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..f078ff8 100644
--- a/packages/PrintSpooler/res/values-is-rIS/strings.xml
+++ b/packages/PrintSpooler/res/values-is-rIS/strings.xml
@@ -69,10 +69,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..10b3601 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -69,10 +69,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..8a04c76 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -71,12 +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="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..a132fb1 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -69,10 +69,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..675245b 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -69,10 +69,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..4c7c4f4 100644
--- a/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
+++ b/packages/PrintSpooler/res/values-kk-rKZ/strings.xml
@@ -69,10 +69,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..fac7c0c 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -69,10 +69,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..61279fc 100644
--- a/packages/PrintSpooler/res/values-kn-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-kn-rIN/strings.xml
@@ -69,10 +69,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..fe47e55 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -69,10 +69,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..79b38d1 100644
--- a/packages/PrintSpooler/res/values-ky-rKG/strings.xml
+++ b/packages/PrintSpooler/res/values-ky-rKG/strings.xml
@@ -69,10 +69,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..3140a25 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -69,10 +69,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..4f0772e 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -71,12 +71,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..0efa50f 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -70,11 +70,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..2805dee 100644
--- a/packages/PrintSpooler/res/values-mk-rMK/strings.xml
+++ b/packages/PrintSpooler/res/values-mk-rMK/strings.xml
@@ -69,10 +69,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..9617a7a 100644
--- a/packages/PrintSpooler/res/values-ml-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ml-rIN/strings.xml
@@ -69,10 +69,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..59bb9bf 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -69,10 +69,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..2b6661e 100644
--- a/packages/PrintSpooler/res/values-mr-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-mr-rIN/strings.xml
@@ -69,10 +69,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..c066627 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -69,10 +69,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..a63e85e 100644
--- a/packages/PrintSpooler/res/values-my-rMM/strings.xml
+++ b/packages/PrintSpooler/res/values-my-rMM/strings.xml
@@ -69,10 +69,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..8128011 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -69,10 +69,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..89b2fbb 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -69,10 +69,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..70b93e6 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -69,10 +69,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..da81919 100644
--- a/packages/PrintSpooler/res/values-pa-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-pa-rIN/strings.xml
@@ -69,10 +69,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..b7613cf 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -71,12 +71,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..199f304 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -69,10 +69,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..ea94c55 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -69,10 +69,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..199f304 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -69,10 +69,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..1c74aab 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -70,11 +70,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..e900ab9 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -71,12 +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="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..5731849 100644
--- a/packages/PrintSpooler/res/values-si-rLK/strings.xml
+++ b/packages/PrintSpooler/res/values-si-rLK/strings.xml
@@ -69,10 +69,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..1c7b740 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -71,12 +71,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..4c794dc 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -71,12 +71,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..aff55f6 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -69,10 +69,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..043048e 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -70,11 +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="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..fd8581f 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -69,10 +69,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..0950f57 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -69,10 +69,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..bf6feae 100644
--- a/packages/PrintSpooler/res/values-ta-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-ta-rIN/strings.xml
@@ -69,10 +69,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..4d14b8c 100644
--- a/packages/PrintSpooler/res/values-te-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-te-rIN/strings.xml
@@ -69,10 +69,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..e1f82e1 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -69,10 +69,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..052d8cc 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -69,10 +69,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..7f9e6f5 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -69,10 +69,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..d34aa2a 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -71,12 +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="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..ccf6f56 100644
--- a/packages/PrintSpooler/res/values-ur-rPK/strings.xml
+++ b/packages/PrintSpooler/res/values-ur-rPK/strings.xml
@@ -69,10 +69,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..d1fc47f 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -69,10 +69,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..eb5de95 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -69,10 +69,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..e39849e 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -69,10 +69,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..1148226 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -69,10 +69,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..c0dd3de 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -69,10 +69,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..231b1bf 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -69,10 +69,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/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 54d2dfa..3fd4f7f 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>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 95badc5..cd4529f 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>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index e4d97d7..7c598229 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>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 93b6438..1349a7a 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>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 0b1238b..4d9d4fb 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>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index dae40d9..833fb62 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>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index dae40d9..833fb62 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>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index dae40d9..833fb62 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>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 855b72c..4d4ab24 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>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index fe5fc29..6405ca8 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>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e1a35f7..d591426 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>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 498f204..ce36de3 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>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index b32bfb7..3ee0775 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>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 0190454..c0098d2 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>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 4b72648..2a0ff45 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>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 5cde233..0a46b27 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>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 42c9a05..fb401f0 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>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 6988a73..1262512 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>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 8d912e9..3e53e94 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>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index e175208..54099c7 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>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index bf9bf8a..7e45fb2 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>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index da9d204..a8f25c6 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>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 549711c..300aaa3 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>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index aed4365..a414668 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>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index ea5dc00..c23a8a7 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>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 6a47406..84bfe94f 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>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 538a38c..4b5359a 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>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 014a6fb..6b21041 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>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 87da105..0652b05 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>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index d76e87f..2457847 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>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 4aea631..622c13f 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>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 1f72d04..5f27232 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>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index cd4812f..0a86cdb 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>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index ae0b15d..99ee44c 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>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 5885513..a109197 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>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index dd4b58d..98a3121 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>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index dd4b58d..98a3121 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>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index a666da0..00ff92b 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>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index e93bae1..9a3a7e6 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>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 6753624..083dd05 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>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 7db7835..e12f435 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>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index ed37933..1f66583 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>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 9596ce5..ab96afd 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>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 7d0d0a0..f8901c9 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>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d1041da..8a33946 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>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index e66f073..d386039 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>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 6826419..b17b516 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>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8f62326..d0e7f87 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>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 5e0839a..e6ddcdd 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>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 0834303..e9fe7e4 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>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index d2d8b76..e53336b 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>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 178e301..193f066 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>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 5b96383..de8996e 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>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index db5f09b..9a86f3a 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>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 787a442..3ab60f5 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>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f7e25db..ac19cf5 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -726,4 +726,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/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/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/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-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index bb8f4ad..1e2dba3 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>
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..905da13 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. -->
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..4136c11 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1269,4 +1269,16 @@
<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>
+
</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/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..91f88b9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -466,7 +466,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..8ce6da2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -109,7 +109,7 @@
}
public interface DetailAdapter {
- int getTitle();
+ CharSequence getTitle();
Boolean getToggleState();
View createDetailView(Context context, View convertView, ViewGroup parent);
Intent getSettingsIntent();
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..3406da9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -506,7 +506,7 @@
public void sendCloseSystemWindows(String reason) {
if (ActivityManagerNative.isSystemReady()) {
try {
- ActivityManagerNative.getDefault().closeSystemDialogs(reason);
+ mIam.closeSystemDialogs(reason);
} catch (RemoteException e) {
}
}
@@ -779,6 +779,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) {
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/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/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..fb2bc17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -166,16 +166,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 +187,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 +221,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 +261,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/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/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/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/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/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/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 aa99442..11f9e2d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3174,7 +3174,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..d12eadb 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1211,10 +1211,11 @@
}
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) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fcb9962..f21eba1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -255,6 +255,9 @@
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.MATCH_DEBUG_TRIAGED_MISSING;
+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;
@@ -1952,6 +1955,7 @@
}
case SYSTEM_USER_UNLOCK_MSG: {
mSystemServiceManager.unlockUser(msg.arg1);
+ mRecentTasks.cleanupLocked(msg.arg1);
break;
}
case SYSTEM_USER_CURRENT_MSG: {
@@ -2290,7 +2294,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) {
@@ -2764,8 +2768,7 @@
}
if (!r.isFocusable()) {
- if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
- "setFocusedActivityLocked: unfocusable r=" + r);
+ if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: unfocusable r=" + r);
return false;
}
@@ -2874,9 +2877,8 @@
synchronized (ActivityManagerService.this) {
TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
if (task != null) {
- ActivityRecord r = task.topRunningActivityLocked();
- if (r != null) {
- setFocusedActivityLocked(r, "setFocusedTask");
+ final ActivityRecord r = task.topRunningActivityLocked();
+ if (setFocusedActivityLocked(r, "setFocusedTask")) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
}
@@ -3444,7 +3446,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,
@@ -3703,21 +3706,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;
@@ -5385,7 +5378,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) {
@@ -5470,7 +5463,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) {
@@ -5556,7 +5550,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) {
@@ -5950,8 +5945,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) {
}
}
@@ -6931,8 +6926,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()
@@ -7027,8 +7022,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()
@@ -7775,7 +7770,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);
@@ -7913,7 +7909,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;
}
@@ -7974,7 +7970,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;
}
@@ -8441,8 +8438,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) {
@@ -8598,7 +8595,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);
@@ -9883,7 +9881,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) {
}
@@ -12457,19 +12455,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++) {
@@ -13989,7 +13981,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) {
}
}
@@ -14925,7 +14917,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;
}
@@ -17123,7 +17116,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 {
@@ -21078,7 +21071,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/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/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 40d01e7..b8cbecb 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -220,6 +220,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, ...)
@@ -820,6 +821,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 +1086,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 +1850,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 +4595,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;
}
}
}
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/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/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/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 7e4e46b..55b8bf2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -386,8 +386,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..1655cb6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -947,7 +947,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,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 254e77b..870ae89 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;
@@ -2836,12 +2837,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 +2845,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 +2860,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 +2869,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);
}
}
@@ -3150,8 +3141,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,12 +3152,13 @@
}
}
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);
}
@@ -3182,6 +3174,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,8 +3189,8 @@
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);
}
@@ -4032,7 +4030,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;
}
@@ -11198,7 +11196,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(
@@ -12045,8 +12044,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;
}
}
@@ -13048,6 +13047,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);
@@ -15679,11 +15679,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 +15701,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();
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/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/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/Task.java b/services/core/java/com/android/server/wm/Task.java
index b4ddebc..47a4936 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);
}
/**
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..aa5cc7f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2977,7 +2977,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;
@@ -7163,18 +7163,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 +7496,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 +7960,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;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index dd6493c..287b39c 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;
@@ -81,7 +80,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 +136,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 +845,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);
}
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 00e1acb..2e0866c 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;
@@ -586,7 +588,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..4198217 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -16,12 +16,15 @@
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.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;
@@ -676,8 +679,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/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/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 5381e4ef6..01583f56 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();
}
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",