Merge "Use FastJNI for trivial MotionEvent native methods"
diff --git a/api/current.txt b/api/current.txt
index ef18bf9..3637f14 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -241,10 +241,8 @@
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
- field public static final int activityHeight = 16844021; // 0x10104f5
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
- field public static final int activityWidth = 16844020; // 0x10104f4
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -323,7 +321,7 @@
field public static final int buttonBarNeutralButtonStyle = 16843914; // 0x101048a
field public static final int buttonBarPositiveButtonStyle = 16843913; // 0x1010489
field public static final int buttonBarStyle = 16843566; // 0x101032e
- field public static final int buttonGravity = 16844029; // 0x10104fd
+ field public static final int buttonGravity = 16844030; // 0x10104fe
field public static final int buttonStyle = 16842824; // 0x1010048
field public static final int buttonStyleInset = 16842826; // 0x101004a
field public static final int buttonStyleSmall = 16842825; // 0x1010049
@@ -373,7 +371,7 @@
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int collapseContentDescription = 16843984; // 0x10104d0
- field public static final int collapseIcon = 16844030; // 0x10104fe
+ field public static final int collapseIcon = 16844031; // 0x10104ff
field public static final int color = 16843173; // 0x10101a5
field public static final int colorAccent = 16843829; // 0x1010435
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
@@ -414,7 +412,7 @@
field public static final int contentInsetRight = 16843862; // 0x1010456
field public static final int contentInsetStart = 16843859; // 0x1010453
field public static final int contextClickable = 16844007; // 0x10104e7
- field public static final int contextPopupMenuStyle = 16844032; // 0x1010500
+ field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
field public static final int controlX1 = 16843772; // 0x10103fc
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
@@ -673,8 +671,10 @@
field public static final int indicatorStart = 16843729; // 0x10103d1
field public static final int inflatedId = 16842995; // 0x10100f3
field public static final int initOrder = 16842778; // 0x101001a
+ field public static final int initialHeight = 16844021; // 0x10104f5
field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
field public static final int initialLayout = 16843345; // 0x1010251
+ field public static final int initialWidth = 16844020; // 0x10104f4
field public static final int innerRadius = 16843359; // 0x101025f
field public static final int innerRadiusRatio = 16843163; // 0x101019b
field public static final deprecated int inputMethod = 16843112; // 0x1010168
@@ -780,7 +780,7 @@
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
- field public static final int level = 16844031; // 0x10104ff
+ field public static final int level = 16844032; // 0x1010500
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -813,7 +813,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxButtonHeight = 16844028; // 0x10104fc
+ field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
field public static final int maxHeight = 16843040; // 0x1010120
@@ -841,6 +841,7 @@
field public static final int minResizeWidth = 16843669; // 0x1010395
field public static final int minSdkVersion = 16843276; // 0x101020c
field public static final int minWidth = 16843071; // 0x101013f
+ field public static final int minimalSize = 16844022; // 0x10104f6
field public static final int minimumHorizontalAngle = 16843901; // 0x101047d
field public static final int minimumVerticalAngle = 16843902; // 0x101047e
field public static final int mipMap = 16843725; // 0x10103cd
@@ -997,7 +998,7 @@
field public static final int resizeClip = 16843983; // 0x10104cf
field public static final int resizeMode = 16843619; // 0x1010363
field public static final int resizeable = 16843405; // 0x101028d
- field public static final int resizeableActivity = 16844022; // 0x10104f6
+ field public static final int resizeableActivity = 16844023; // 0x10104f7
field public static final int resource = 16842789; // 0x1010025
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -1221,7 +1222,7 @@
field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
field public static final int textAppearanceMedium = 16842817; // 0x1010041
field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
- field public static final int textAppearancePopupMenuHeader = 16844033; // 0x1010501
+ field public static final int textAppearancePopupMenuHeader = 16844034; // 0x1010502
field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
field public static final int textAppearanceSearchResultTitle = 16843425; // 0x10102a1
field public static final int textAppearanceSmall = 16842818; // 0x1010042
@@ -1290,11 +1291,11 @@
field public static final int tintMode = 16843771; // 0x10103fb
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
- field public static final int titleMargin = 16844023; // 0x10104f7
- field public static final int titleMarginBottom = 16844027; // 0x10104fb
- field public static final int titleMarginEnd = 16844025; // 0x10104f9
- field public static final int titleMarginStart = 16844024; // 0x10104f8
- field public static final int titleMarginTop = 16844026; // 0x10104fa
+ field public static final int titleMargin = 16844024; // 0x10104f8
+ field public static final int titleMarginBottom = 16844028; // 0x10104fc
+ field public static final int titleMarginEnd = 16844026; // 0x10104fa
+ field public static final int titleMarginStart = 16844025; // 0x10104f9
+ field public static final int titleMarginTop = 16844027; // 0x10104fb
field public static final int titleTextAppearance = 16843822; // 0x101042e
field public static final int titleTextColor = 16844003; // 0x10104e3
field public static final int titleTextStyle = 16843512; // 0x10102f8
@@ -2876,6 +2877,7 @@
method public android.animation.TimeInterpolator getInterpolator();
method public java.util.ArrayList<android.animation.Animator.AnimatorListener> getListeners();
method public abstract long getStartDelay();
+ method public long getTotalDuration();
method public boolean isPaused();
method public abstract boolean isRunning();
method public boolean isStarted();
@@ -2891,6 +2893,7 @@
method public void setupEndValues();
method public void setupStartValues();
method public void start();
+ field public static final long DURATION_INFINITE = -1L; // 0xffffffffffffffffL
}
public static abstract interface Animator.AnimatorListener {
@@ -8922,8 +8925,8 @@
field public int configChanges;
field public int documentLaunchMode;
field public int flags;
- field public android.content.pm.ActivityInfo.InitialLayout initialLayout;
field public int launchMode;
+ field public android.content.pm.ActivityInfo.Layout layout;
field public int maxRecents;
field public java.lang.String parentActivityName;
field public java.lang.String permission;
@@ -8936,11 +8939,12 @@
field public int uiOptions;
}
- public static final class ActivityInfo.InitialLayout {
- ctor public ActivityInfo.InitialLayout(int, float, int, float, int);
+ public static final class ActivityInfo.Layout {
+ ctor public ActivityInfo.Layout(int, float, int, float, int, int);
field public final int gravity;
field public final int height;
field public final float heightFraction;
+ field public final int minimalSize;
field public final int width;
field public final float widthFraction;
}
@@ -18173,6 +18177,24 @@
public class MtpEvent {
ctor public MtpEvent();
method public int getEventCode();
+ field public static final int EVENT_CANCEL_TRANSACTION = 16385; // 0x4001
+ field public static final int EVENT_CAPTURE_COMPLETE = 16397; // 0x400d
+ field public static final int EVENT_DEVICE_INFO_CHANGED = 16392; // 0x4008
+ field public static final int EVENT_DEVICE_PROP_CHANGED = 16390; // 0x4006
+ field public static final int EVENT_DEVICE_RESET = 16395; // 0x400b
+ field public static final int EVENT_OBJECT_ADDED = 16386; // 0x4002
+ field public static final int EVENT_OBJECT_INFO_CHANGED = 16391; // 0x4007
+ field public static final int EVENT_OBJECT_PROP_CHANGED = 51201; // 0xc801
+ field public static final int EVENT_OBJECT_PROP_DESC_CHANGED = 51202; // 0xc802
+ field public static final int EVENT_OBJECT_REFERENCES_CHANGED = 51203; // 0xc803
+ field public static final int EVENT_OBJECT_REMOVED = 16387; // 0x4003
+ field public static final int EVENT_REQUEST_OBJECT_TRANSFER = 16393; // 0x4009
+ field public static final int EVENT_STORAGE_INFO_CHANGED = 16396; // 0x400c
+ field public static final int EVENT_STORE_ADDED = 16388; // 0x4004
+ field public static final int EVENT_STORE_FULL = 16394; // 0x400a
+ field public static final int EVENT_STORE_REMOVED = 16389; // 0x4005
+ field public static final int EVENT_UNDEFINED = 16384; // 0x4000
+ field public static final int EVENT_UNREPORTED_STATUS = 16398; // 0x400e
}
public final class MtpObjectInfo {
diff --git a/api/system-current.txt b/api/system-current.txt
index 0b216bdd..076815e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -333,10 +333,8 @@
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
field public static final int activityCloseExitAnimation = 16842939; // 0x10100bb
- field public static final int activityHeight = 16844021; // 0x10104f5
field public static final int activityOpenEnterAnimation = 16842936; // 0x10100b8
field public static final int activityOpenExitAnimation = 16842937; // 0x10100b9
- field public static final int activityWidth = 16844020; // 0x10104f4
field public static final int addPrintersActivity = 16843750; // 0x10103e6
field public static final int addStatesFromChildren = 16842992; // 0x10100f0
field public static final int adjustViewBounds = 16843038; // 0x101011e
@@ -415,7 +413,7 @@
field public static final int buttonBarNeutralButtonStyle = 16843914; // 0x101048a
field public static final int buttonBarPositiveButtonStyle = 16843913; // 0x1010489
field public static final int buttonBarStyle = 16843566; // 0x101032e
- field public static final int buttonGravity = 16844029; // 0x10104fd
+ field public static final int buttonGravity = 16844030; // 0x10104fe
field public static final int buttonStyle = 16842824; // 0x1010048
field public static final int buttonStyleInset = 16842826; // 0x101004a
field public static final int buttonStyleSmall = 16842825; // 0x1010049
@@ -465,7 +463,7 @@
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int collapseContentDescription = 16843984; // 0x10104d0
- field public static final int collapseIcon = 16844030; // 0x10104fe
+ field public static final int collapseIcon = 16844031; // 0x10104ff
field public static final int color = 16843173; // 0x10101a5
field public static final int colorAccent = 16843829; // 0x1010435
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
@@ -506,7 +504,7 @@
field public static final int contentInsetRight = 16843862; // 0x1010456
field public static final int contentInsetStart = 16843859; // 0x1010453
field public static final int contextClickable = 16844007; // 0x10104e7
- field public static final int contextPopupMenuStyle = 16844032; // 0x1010500
+ field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
field public static final int controlX1 = 16843772; // 0x10103fc
field public static final int controlX2 = 16843774; // 0x10103fe
field public static final int controlY1 = 16843773; // 0x10103fd
@@ -765,8 +763,10 @@
field public static final int indicatorStart = 16843729; // 0x10103d1
field public static final int inflatedId = 16842995; // 0x10100f3
field public static final int initOrder = 16842778; // 0x101001a
+ field public static final int initialHeight = 16844021; // 0x10104f5
field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
field public static final int initialLayout = 16843345; // 0x1010251
+ field public static final int initialWidth = 16844020; // 0x10104f4
field public static final int innerRadius = 16843359; // 0x101025f
field public static final int innerRadiusRatio = 16843163; // 0x101019b
field public static final deprecated int inputMethod = 16843112; // 0x1010168
@@ -872,7 +872,7 @@
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
- field public static final int level = 16844031; // 0x10104ff
+ field public static final int level = 16844032; // 0x1010500
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -905,7 +905,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxButtonHeight = 16844028; // 0x10104fc
+ field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
field public static final int maxHeight = 16843040; // 0x1010120
@@ -933,6 +933,7 @@
field public static final int minResizeWidth = 16843669; // 0x1010395
field public static final int minSdkVersion = 16843276; // 0x101020c
field public static final int minWidth = 16843071; // 0x101013f
+ field public static final int minimalSize = 16844022; // 0x10104f6
field public static final int minimumHorizontalAngle = 16843901; // 0x101047d
field public static final int minimumVerticalAngle = 16843902; // 0x101047e
field public static final int mipMap = 16843725; // 0x10103cd
@@ -1089,7 +1090,7 @@
field public static final int resizeClip = 16843983; // 0x10104cf
field public static final int resizeMode = 16843619; // 0x1010363
field public static final int resizeable = 16843405; // 0x101028d
- field public static final int resizeableActivity = 16844022; // 0x10104f6
+ field public static final int resizeableActivity = 16844023; // 0x10104f7
field public static final int resource = 16842789; // 0x1010025
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -1317,7 +1318,7 @@
field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
field public static final int textAppearanceMedium = 16842817; // 0x1010041
field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
- field public static final int textAppearancePopupMenuHeader = 16844033; // 0x1010501
+ field public static final int textAppearancePopupMenuHeader = 16844034; // 0x1010502
field public static final int textAppearanceSearchResultSubtitle = 16843424; // 0x10102a0
field public static final int textAppearanceSearchResultTitle = 16843425; // 0x10102a1
field public static final int textAppearanceSmall = 16842818; // 0x1010042
@@ -1386,11 +1387,11 @@
field public static final int tintMode = 16843771; // 0x10103fb
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
- field public static final int titleMargin = 16844023; // 0x10104f7
- field public static final int titleMarginBottom = 16844027; // 0x10104fb
- field public static final int titleMarginEnd = 16844025; // 0x10104f9
- field public static final int titleMarginStart = 16844024; // 0x10104f8
- field public static final int titleMarginTop = 16844026; // 0x10104fa
+ field public static final int titleMargin = 16844024; // 0x10104f8
+ field public static final int titleMarginBottom = 16844028; // 0x10104fc
+ field public static final int titleMarginEnd = 16844026; // 0x10104fa
+ field public static final int titleMarginStart = 16844025; // 0x10104f9
+ field public static final int titleMarginTop = 16844027; // 0x10104fb
field public static final int titleTextAppearance = 16843822; // 0x101042e
field public static final int titleTextColor = 16844003; // 0x10104e3
field public static final int titleTextStyle = 16843512; // 0x10102f8
@@ -2975,6 +2976,7 @@
method public android.animation.TimeInterpolator getInterpolator();
method public java.util.ArrayList<android.animation.Animator.AnimatorListener> getListeners();
method public abstract long getStartDelay();
+ method public long getTotalDuration();
method public boolean isPaused();
method public abstract boolean isRunning();
method public boolean isStarted();
@@ -2990,6 +2992,7 @@
method public void setupEndValues();
method public void setupStartValues();
method public void start();
+ field public static final long DURATION_INFINITE = -1L; // 0xffffffffffffffffL
}
public static abstract interface Animator.AnimatorListener {
@@ -9179,8 +9182,8 @@
field public int configChanges;
field public int documentLaunchMode;
field public int flags;
- field public android.content.pm.ActivityInfo.InitialLayout initialLayout;
field public int launchMode;
+ field public android.content.pm.ActivityInfo.Layout layout;
field public int maxRecents;
field public java.lang.String parentActivityName;
field public java.lang.String permission;
@@ -9193,11 +9196,12 @@
field public int uiOptions;
}
- public static final class ActivityInfo.InitialLayout {
- ctor public ActivityInfo.InitialLayout(int, float, int, float, int);
+ public static final class ActivityInfo.Layout {
+ ctor public ActivityInfo.Layout(int, float, int, float, int, int);
field public final int gravity;
field public final int height;
field public final float heightFraction;
+ field public final int minimalSize;
field public final int width;
field public final float widthFraction;
}
@@ -19685,6 +19689,24 @@
public class MtpEvent {
ctor public MtpEvent();
method public int getEventCode();
+ field public static final int EVENT_CANCEL_TRANSACTION = 16385; // 0x4001
+ field public static final int EVENT_CAPTURE_COMPLETE = 16397; // 0x400d
+ field public static final int EVENT_DEVICE_INFO_CHANGED = 16392; // 0x4008
+ field public static final int EVENT_DEVICE_PROP_CHANGED = 16390; // 0x4006
+ field public static final int EVENT_DEVICE_RESET = 16395; // 0x400b
+ field public static final int EVENT_OBJECT_ADDED = 16386; // 0x4002
+ field public static final int EVENT_OBJECT_INFO_CHANGED = 16391; // 0x4007
+ field public static final int EVENT_OBJECT_PROP_CHANGED = 51201; // 0xc801
+ field public static final int EVENT_OBJECT_PROP_DESC_CHANGED = 51202; // 0xc802
+ field public static final int EVENT_OBJECT_REFERENCES_CHANGED = 51203; // 0xc803
+ field public static final int EVENT_OBJECT_REMOVED = 16387; // 0x4003
+ field public static final int EVENT_REQUEST_OBJECT_TRANSFER = 16393; // 0x4009
+ field public static final int EVENT_STORAGE_INFO_CHANGED = 16396; // 0x400c
+ field public static final int EVENT_STORE_ADDED = 16388; // 0x4004
+ field public static final int EVENT_STORE_FULL = 16394; // 0x400a
+ field public static final int EVENT_STORE_REMOVED = 16389; // 0x4005
+ field public static final int EVENT_UNDEFINED = 16384; // 0x4000
+ field public static final int EVENT_UNREPORTED_STATUS = 16398; // 0x400e
}
public final class MtpObjectInfo {
@@ -25721,7 +25743,8 @@
ctor public UserHandle(android.os.Parcel);
method public int describeContents();
method public int getIdentifier();
- method public boolean isOwner();
+ method public deprecated boolean isOwner();
+ method public boolean isSystem();
method public static int myUserId();
method public static android.os.UserHandle readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 4a13136..81da6af 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -2033,7 +2033,7 @@
}
try {
- mAm.resizeStack(stackId, bounds);
+ mAm.resizeStack(stackId, bounds, false);
Thread.sleep(delayMs);
} catch (RemoteException e) {
showError("Error: resizing stack " + e);
@@ -2127,8 +2127,8 @@
}
// Resize stacks
- mAm.resizeStack(currentStackInfo.stackId, currentStackBounds);
- mAm.resizeStack(newStackInfo.stackId, newStackBounds);
+ mAm.resizeStack(currentStackInfo.stackId, currentStackBounds, false);
+ mAm.resizeStack(newStackInfo.stackId, newStackBounds, false);
} catch (RemoteException e) {
}
}
diff --git a/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
index d1f7a00..c9b9e58 100644
--- a/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
+++ b/cmds/appops/src/com/android/commands/appops/AppOpsCommand.java
@@ -168,7 +168,12 @@
final IPackageManager pm = ActivityThread.getPackageManager();
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
- final int uid = pm.getPackageUid(packageName, userId);
+ final int uid;
+ if ("root".equals(packageName)) {
+ uid = 0;
+ } else {
+ uid = pm.getPackageUid(packageName, userId);
+ }
if (uid < 0) {
System.err.println("Error: No UID for " + packageName + " in user " + userId);
return;
@@ -211,7 +216,12 @@
final IPackageManager pm = ActivityThread.getPackageManager();
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
- final int uid = pm.getPackageUid(packageName, userId);
+ final int uid;
+ if ("root".equals(packageName)) {
+ uid = 0;
+ } else {
+ uid = pm.getPackageUid(packageName, userId);
+ }
if (uid < 0) {
System.err.println("Error: No UID for " + packageName + " in user " + userId);
return;
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp
index 41395f1..9d60ee1 100644
--- a/cmds/idmap/create.cpp
+++ b/cmds/idmap/create.cpp
@@ -41,7 +41,7 @@
ALOGD("error: fchmod %s: %s\n", path, strerror(errno));
goto fail;
}
- if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX | LOCK_NB)) != 0) {
+ if (TEMP_FAILURE_RETRY(flock(fd, LOCK_EX)) != 0) {
ALOGD("error: flock %s: %s\n", path, strerror(errno));
goto fail;
}
diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp
index 90cfa2c..3ab1915 100644
--- a/cmds/idmap/idmap.cpp
+++ b/cmds/idmap/idmap.cpp
@@ -13,7 +13,8 @@
idmap --help \n\
idmap --fd target overlay fd \n\
idmap --path target overlay idmap \n\
- idmap --scan dir-to-scan target-to-look-for target dir-to-hold-idmaps \n\
+ idmap --scan target-package-name-to-look-for path-to-target-apk dir-to-hold-idmaps \\\
+ dir-to-scan [additional-dir-to-scan [additional-dir-to-scan [...]]]\n\
idmap --inspect idmap \n\
\n\
DESCRIPTION \n\
@@ -49,9 +50,9 @@
'overlay' (path to apk); write results to 'idmap' (path). \n\
\n\
--scan: non-recursively search directory 'dir-to-scan' (path) for overlay packages with \n\
- target package 'target-to-look-for' (package name) present at 'target' (path to \n\
- apk). For each overlay package found, create an idmap file in 'dir-to-hold-idmaps' \n\
- (path). \n\
+ target package 'target-package-name-to-look-for' (package name) present at\n\
+ 'path-to-target-apk' (path to apk). For each overlay package found, create an\n\
+ idmap file in 'dir-to-hold-idmaps' (path). \n\
\n\
--inspect: decode the binary format of 'idmap' (path) and display the contents in a \n\
debug-friendly format. \n\
@@ -166,19 +167,14 @@
return idmap_create_path(target_apk_path, overlay_apk_path, idmap_path);
}
- int maybe_scan(const char *overlay_dir, const char *target_package_name,
- const char *target_apk_path, const char *idmap_dir)
+ int maybe_scan(const char *target_package_name, const char *target_apk_path,
+ const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
{
if (!verify_root_or_system()) {
fprintf(stderr, "error: permission denied: not user root or user system\n");
return -1;
}
- if (!verify_directory_readable(overlay_dir)) {
- ALOGD("error: no read access to %s: %s\n", overlay_dir, strerror(errno));
- return -1;
- }
-
if (!verify_file_readable(target_apk_path)) {
ALOGD("error: failed to read apk %s: %s\n", target_apk_path, strerror(errno));
return -1;
@@ -189,7 +185,16 @@
return -1;
}
- return idmap_scan(overlay_dir, target_package_name, target_apk_path, idmap_dir);
+ const size_t N = overlay_dirs->size();
+ for (size_t i = 0; i < N; i++) {
+ const char *dir = overlay_dirs->itemAt(i);
+ if (!verify_directory_readable(dir)) {
+ ALOGD("error: no read access to %s: %s\n", dir, strerror(errno));
+ return -1;
+ }
+ }
+
+ return idmap_scan(target_package_name, target_apk_path, idmap_dir, overlay_dirs);
}
int maybe_inspect(const char *idmap_path)
@@ -230,8 +235,12 @@
return maybe_create_path(argv[2], argv[3], argv[4]);
}
- if (argc == 6 && !strcmp(argv[1], "--scan")) {
- return maybe_scan(argv[2], argv[3], argv[4], argv[5]);
+ if (argc >= 6 && !strcmp(argv[1], "--scan")) {
+ android::Vector<const char *> v;
+ for (int i = 5; i < argc; i++) {
+ v.push(argv[i]);
+ }
+ return maybe_scan(argv[2], argv[3], argv[4], &v);
}
if (argc == 3 && !strcmp(argv[1], "--inspect")) {
diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h
index f507dd8..8d4210b 100644
--- a/cmds/idmap/idmap.h
+++ b/cmds/idmap/idmap.h
@@ -1,9 +1,11 @@
+
#ifndef _IDMAP_H_
#define _IDMAP_H_
#define LOG_TAG "idmap"
#include <utils/Log.h>
+#include <utils/Vector.h>
#include <errno.h>
#include <stdio.h>
@@ -26,8 +28,8 @@
// Regarding target_package_name: the idmap_scan implementation should
// be able to extract this from the manifest in target_apk_path,
// simplifying the external API.
-int idmap_scan(const char *overlay_dir, const char *target_package_name,
- const char *target_apk_path, const char *idmap_dir);
+int idmap_scan(const char *target_package_name, const char *target_apk_path,
+ const char *idmap_dir, const android::Vector<const char *> *overlay_dirs);
int idmap_inspect(const char *idmap_path);
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index 612a7eb..f1b2f9e 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -25,8 +25,7 @@
bool operator<(Overlay const& rhs) const
{
- // Note: order is reversed by design
- return rhs.priority < priority;
+ return rhs.priority > priority;
}
String8 apk_path;
@@ -167,8 +166,8 @@
}
}
-int idmap_scan(const char *overlay_dir, const char *target_package_name,
- const char *target_apk_path, const char *idmap_dir)
+int idmap_scan(const char *target_package_name, const char *target_apk_path,
+ const char *idmap_dir, const android::Vector<const char *> *overlay_dirs)
{
String8 filename = String8(idmap_dir);
filename.appendPath("overlays.list");
@@ -176,45 +175,49 @@
return EXIT_FAILURE;
}
- DIR *dir = opendir(overlay_dir);
- if (dir == NULL) {
- return EXIT_FAILURE;
- }
-
SortedVector<Overlay> overlayVector;
- struct dirent *dirent;
- while ((dirent = readdir(dir)) != NULL) {
- struct stat st;
- char overlay_apk_path[PATH_MAX + 1];
- snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
- if (stat(overlay_apk_path, &st) < 0) {
- continue;
- }
- if (!S_ISREG(st.st_mode)) {
- continue;
+ const size_t N = overlay_dirs->size();
+ for (size_t i = 0; i < N; ++i) {
+ const char *overlay_dir = overlay_dirs->itemAt(i);
+ DIR *dir = opendir(overlay_dir);
+ if (dir == NULL) {
+ return EXIT_FAILURE;
}
- int priority = parse_apk(overlay_apk_path, target_package_name);
- if (priority < 0) {
- continue;
+ struct dirent *dirent;
+ while ((dirent = readdir(dir)) != NULL) {
+ struct stat st;
+ char overlay_apk_path[PATH_MAX + 1];
+ snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
+ if (stat(overlay_apk_path, &st) < 0) {
+ continue;
+ }
+ if (!S_ISREG(st.st_mode)) {
+ continue;
+ }
+
+ int priority = parse_apk(overlay_apk_path, target_package_name);
+ if (priority < 0) {
+ continue;
+ }
+
+ String8 idmap_path(idmap_dir);
+ idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
+ idmap_path.append("@idmap");
+
+ if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
+ ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
+ target_apk_path, overlay_apk_path, idmap_path.string());
+ continue;
+ }
+
+ Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
+ overlayVector.add(overlay);
}
- String8 idmap_path(idmap_dir);
- idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
- idmap_path.append("@idmap");
-
- if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
- ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
- target_apk_path, overlay_apk_path, idmap_path.string());
- continue;
- }
-
- Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
- overlayVector.add(overlay);
+ closedir(dir);
}
- closedir(dir);
-
if (!writePackagesList(filename.string(), overlayVector)) {
return EXIT_FAILURE;
}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 393956f..3f8e311 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -283,7 +283,7 @@
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("-p")) {
validCommand = true;
- return displayPackageFilePath(args[1]);
+ return displayPackageFilePath(args[1], UserHandle.USER_OWNER);
}
}
return 1;
@@ -767,12 +767,25 @@
}
private int runPath() {
+ int userId = UserHandle.USER_OWNER;
+ String option = nextOption();
+ if (option != null && option.equals("--user")) {
+ String optionData = nextOptionData();
+ if (optionData == null || !isNumber(optionData)) {
+ System.err.println("Error: no USER_ID specified");
+ showUsage();
+ return 1;
+ } else {
+ userId = Integer.parseInt(optionData);
+ }
+ }
+
String pkg = nextArg();
if (pkg == null) {
System.err.println("Error: no package specified");
return 1;
}
- return displayPackageFilePath(pkg);
+ return displayPackageFilePath(pkg, userId);
}
private int runDump() {
@@ -1637,7 +1650,7 @@
}
private int runClear() {
- int userId = 0;
+ int userId = UserHandle.USER_OWNER;
String option = nextOption();
if (option != null && option.equals("--user")) {
String optionData = nextOptionData();
@@ -1709,7 +1722,7 @@
}
private int runSetEnabledSetting(int state) {
- int userId = 0;
+ int userId = UserHandle.USER_OWNER;
String option = nextOption();
if (option != null && option.equals("--user")) {
String optionData = nextOptionData();
@@ -1758,7 +1771,7 @@
}
private int runSetHiddenSetting(boolean state) {
- int userId = 0;
+ int userId = UserHandle.USER_OWNER;
String option = nextOption();
if (option != null && option.equals("--user")) {
String optionData = nextOptionData();
@@ -1963,9 +1976,9 @@
* Displays the package file for a package.
* @param pckg
*/
- private int displayPackageFilePath(String pckg) {
+ private int displayPackageFilePath(String pckg, int userId) {
try {
- PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
+ PackageInfo info = mPm.getPackageInfo(pckg, 0, userId);
if (info != null && info.applicationInfo != null) {
System.out.print("package:");
System.out.println(info.applicationInfo.sourceDir);
@@ -2104,7 +2117,7 @@
System.err.println(" pm list features");
System.err.println(" pm list libraries");
System.err.println(" pm list users");
- System.err.println(" pm path PACKAGE");
+ System.err.println(" pm path [--user USER_ID] PACKAGE");
System.err.println(" pm dump PACKAGE");
System.err.println(" pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
System.err.println(" pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index d331c2a..844063c 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -28,7 +28,6 @@
/**
* The value used to indicate infinite duration (e.g. when Animators repeat infinitely).
- * @hide
*/
public static final long DURATION_INFINITE = -1;
/**
@@ -191,11 +190,18 @@
/**
* Gets the total duration of the animation, accounting for animation sequences, start delay,
* and repeating. Return {@link #DURATION_INFINITE} if the duration is infinite.
- * @hide
- * TODO: Unhide
+ *
+ * @return Total time an animation takes to finish, starting from the time {@link #start()}
+ * is called. {@link #DURATION_INFINITE} will be returned if the animation or any
+ * child animation repeats infinite times.
*/
public long getTotalDuration() {
- return getStartDelay() + getDuration();
+ long duration = getDuration();
+ if (duration == DURATION_INFINITE) {
+ return DURATION_INFINITE;
+ } else {
+ return getStartDelay() + duration;
+ }
}
/**
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index d444638..1ab55dd 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1030,9 +1030,6 @@
}
}
- /**
- * @hide
- */
@Override
public long getTotalDuration() {
updateAnimatorsDuration();
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 9b905bd..6f65889 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -126,12 +126,6 @@
new AccelerateDecelerateInterpolator();
/**
- * Used to indicate whether the animation is currently playing in reverse. This causes the
- * elapsed fraction to be inverted to calculate the appropriate values.
- */
- private boolean mPlayingBackwards = false;
-
- /**
* Flag to indicate whether this animator is playing in reverse mode, specifically
* by being started or interrupted by a call to reverse(). This flag is different than
* mPlayingBackwards, which indicates merely whether the current iteration of the
@@ -141,13 +135,13 @@
private boolean mReversing;
/**
- * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
- * repeatCount (if repeatCount!=INFINITE), the animation ends
+ * Tracks the overall fraction of the animation, ranging from 0 to mRepeatCount + 1
*/
- private int mCurrentIteration = 0;
+ private float mOverallFraction = 0f;
/**
* Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
+ * This is calculated by interpolating the fraction (range: [0, 1]) in the current iteration.
*/
private float mCurrentFraction = 0f;
@@ -195,12 +189,12 @@
//
// How long the animation should last in ms
- private long mUnscaledDuration = 300;
- private long mDuration = (long)(mUnscaledDuration * sDurationScale);
+ private long mDuration = 300;
- // The amount of time in ms to delay starting the animation after start() is called
- long mStartDelay = 0;
- private long mUnscaledStartDelay = 0;
+ // The amount of time in ms to delay starting the animation after start() is called. Note
+ // that this start delay is unscaled. When there is a duration scale set on the animator, the
+ // scaling factor will be applied to this delay.
+ private long mStartDelay = 0;
// The number of times the animation will repeat. The default is 0, which means the animation
// will play only once
@@ -524,13 +518,12 @@
throw new IllegalArgumentException("Animators cannot have negative duration: " +
duration);
}
- mUnscaledDuration = duration;
- updateScaledDuration();
+ mDuration = duration;
return this;
}
- private void updateScaledDuration() {
- mDuration = (long)(mUnscaledDuration * sDurationScale);
+ private long getScaledDuration() {
+ return (long)(mDuration * sDurationScale);
}
/**
@@ -540,18 +533,15 @@
*/
@Override
public long getDuration() {
- return mUnscaledDuration;
+ return mDuration;
}
- /**
- * @hide
- */
@Override
public long getTotalDuration() {
if (mRepeatCount == INFINITE) {
return DURATION_INFINITE;
} else {
- return mUnscaledStartDelay + (mUnscaledDuration * (mRepeatCount + 1));
+ return mStartDelay + (mDuration * (mRepeatCount + 1));
}
}
@@ -566,7 +556,7 @@
* @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
*/
public void setCurrentPlayTime(long playTime) {
- float fraction = mUnscaledDuration > 0 ? (float) playTime / mUnscaledDuration : 1;
+ float fraction = mDuration > 0 ? (float) playTime / mDuration : 1;
setCurrentFraction(fraction);
}
@@ -589,37 +579,82 @@
*/
public void setCurrentFraction(float fraction) {
initAnimation();
- if (fraction < 0) {
- fraction = 0;
- }
- int iteration = (int) fraction;
- if (fraction == 1) {
- iteration -= 1;
- } else if (fraction > 1) {
- if (iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE) {
- if (mRepeatMode == REVERSE) {
- mPlayingBackwards = (iteration % 2) != 0;
- }
- fraction = fraction % 1f;
- } else {
- fraction = 1;
- iteration -= 1;
- }
- } else {
- mPlayingBackwards = mReversing;
- }
- mCurrentIteration = iteration;
- long seekTime = (long) (mDuration * fraction);
+ fraction = clampFraction(fraction);
+ long seekTime = (long) (getScaledDuration() * fraction);
long currentTime = AnimationUtils.currentAnimationTimeMillis();
mStartTime = currentTime - seekTime;
mStartTimeCommitted = true; // do not allow start time to be compensated for jank
if (!mRunning) {
mSeekFraction = fraction;
}
- if (mPlayingBackwards) {
- fraction = 1f - fraction;
+ mOverallFraction = fraction;
+ final float currentIterationFraction = getCurrentIterationFraction(fraction);
+ animateValue(currentIterationFraction);
+ }
+
+ /**
+ * Calculates current iteration based on the overall fraction. The overall fraction will be
+ * in the range of [0, mRepeatCount + 1]. Both current iteration and fraction in the current
+ * iteration can be derived from it.
+ */
+ private int getCurrentIteration(float fraction) {
+ fraction = clampFraction(fraction);
+ // If the overall fraction is a positive integer, we consider the current iteration to be
+ // complete. In other words, the fraction for the current iteration would be 1, and the
+ // current iteration would be overall fraction - 1.
+ double iteration = Math.floor(fraction);
+ if (fraction == iteration && fraction > 0) {
+ iteration--;
}
- animateValue(fraction);
+ return (int) iteration;
+ }
+
+ /**
+ * Calculates the fraction of the current iteration, taking into account whether the animation
+ * should be played backwards. E.g. When the animation is played backwards in an iteration,
+ * the fraction for that iteration will go from 1f to 0f.
+ */
+ private float getCurrentIterationFraction(float fraction) {
+ fraction = clampFraction(fraction);
+ int iteration = getCurrentIteration(fraction);
+ float currentFraction = fraction - iteration;
+ return shouldPlayBackward(iteration) ? 1f - currentFraction : currentFraction;
+ }
+
+ /**
+ * Clamps fraction into the correct range: [0, mRepeatCount + 1]. If repeat count is infinite,
+ * no upper bound will be set for the fraction.
+ *
+ * @param fraction fraction to be clamped
+ * @return fraction clamped into the range of [0, mRepeatCount + 1]
+ */
+ private float clampFraction(float fraction) {
+ if (fraction < 0) {
+ fraction = 0;
+ } else if (mRepeatCount != INFINITE) {
+ fraction = Math.min(fraction, mRepeatCount + 1);
+ }
+ return fraction;
+ }
+
+ /**
+ * Calculates the direction of animation playing (i.e. forward or backward), based on 1)
+ * whether the entire animation is being reversed, 2) repeat mode applied to the current
+ * iteration.
+ */
+ private boolean shouldPlayBackward(int iteration) {
+ if (iteration > 0 && mRepeatMode == REVERSE &&
+ (iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {
+ // if we were seeked to some other iteration in a reversing animator,
+ // figure out the correct direction to start playing based on the iteration
+ if (mReversing) {
+ return (iteration % 2) == 0;
+ } else {
+ return (iteration % 2) != 0;
+ }
+ } else {
+ return mReversing;
+ }
}
/**
@@ -636,9 +671,10 @@
return 0;
}
if (mSeekFraction >= 0) {
- return (long) (mUnscaledDuration * mSeekFraction);
+ return (long) (mDuration * mSeekFraction);
}
- return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
+ float durationScale = sDurationScale == 0 ? 1 : sDurationScale;
+ return (long) ((AnimationUtils.currentAnimationTimeMillis() - mStartTime) / durationScale);
}
/**
@@ -649,7 +685,7 @@
*/
@Override
public long getStartDelay() {
- return mUnscaledStartDelay;
+ return mStartDelay;
}
/**
@@ -660,8 +696,7 @@
*/
@Override
public void setStartDelay(long startDelay) {
- this.mStartDelay = (long)(startDelay * sDurationScale);
- mUnscaledStartDelay = startDelay;
+ mStartDelay = startDelay;
}
/**
@@ -907,40 +942,27 @@
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
mReversing = playBackwards;
- mPlayingBackwards = playBackwards;
- if (playBackwards && mSeekFraction != -1) {
- if (mSeekFraction == 0 && mCurrentIteration == 0) {
- // special case: reversing from seek-to-0 should act as if not seeked at all
- mSeekFraction = 0;
- } else if (mRepeatCount == INFINITE) {
- mSeekFraction = 1 - (mSeekFraction % 1);
+ // Special case: reversing from seek-to-0 should act as if not seeked at all.
+ if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
+ if (mRepeatCount == INFINITE) {
+ // Calculate the fraction of the current iteration.
+ float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction));
+ mSeekFraction = 1 - fraction;
} else {
- mSeekFraction = 1 + mRepeatCount - (mCurrentIteration + mSeekFraction);
- }
- mCurrentIteration = (int) mSeekFraction;
- mSeekFraction = mSeekFraction % 1;
- }
- if (mCurrentIteration > 0 && mRepeatMode == REVERSE &&
- (mCurrentIteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {
- // if we were seeked to some other iteration in a reversing animator,
- // figure out the correct direction to start playing based on the iteration
- if (playBackwards) {
- mPlayingBackwards = (mCurrentIteration % 2) == 0;
- } else {
- mPlayingBackwards = (mCurrentIteration % 2) != 0;
+ mSeekFraction = 1 + mRepeatCount - mSeekFraction;
}
}
mStarted = true;
mPaused = false;
mRunning = false;
mAnimationEndRequested = false;
- updateScaledDuration(); // in case the scale factor has changed since creation time
AnimationHandler animationHandler = AnimationHandler.getInstance();
- animationHandler.addAnimationFrameCallback(this, mStartDelay);
+ animationHandler.addAnimationFrameCallback(this, (long) (mStartDelay * sDurationScale));
if (mStartDelay == 0) {
// If there's no start delay, init the animation and notify start listeners right away
- // Otherwise, postpone this until the first frame after the start delay.
+ // to be consistent with the previous behavior. Otherwise, postpone this until the first
+ // frame after the start delay.
startAnimation();
setCurrentFraction(mSeekFraction == -1 ? 0 : mSeekFraction);
}
@@ -993,7 +1015,7 @@
} else if (!mInitialized) {
initAnimation();
}
- animateValue(mPlayingBackwards ? 0f : 1f);
+ animateValue(shouldPlayBackward(mRepeatCount) ? 0f : 1f);
endAnimation();
}
@@ -1034,11 +1056,10 @@
*/
@Override
public void reverse() {
- mPlayingBackwards = !mPlayingBackwards;
if (mRunning) {
long currentTime = AnimationUtils.currentAnimationTimeMillis();
long currentPlayTime = currentTime - mStartTime;
- long timeLeft = mDuration - currentPlayTime;
+ long timeLeft = getScaledDuration() - currentPlayTime;
mStartTime = currentTime - timeLeft;
mStartTimeCommitted = true; // do not allow start time to be compensated for jank
mReversing = !mReversing;
@@ -1085,10 +1106,8 @@
mRunning = false;
mStarted = false;
mStartListenersCalled = false;
- mPlayingBackwards = false;
mReversing = false;
mLastFrameTime = 0;
- mCurrentIteration = 0;
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
System.identityHashCode(this));
@@ -1106,6 +1125,11 @@
}
initAnimation();
mRunning = true;
+ if (mSeekFraction >= 0) {
+ mOverallFraction = mSeekFraction;
+ } else {
+ mOverallFraction = 0f;
+ }
if (mListeners != null) {
notifyStartListeners();
}
@@ -1151,40 +1175,26 @@
boolean animateBasedOnTime(long currentTime) {
boolean done = false;
if (mRunning) {
- float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
- if (mDuration == 0 && mRepeatCount != INFINITE) {
- // Skip to the end
- mCurrentIteration = mRepeatCount;
- if (!mReversing) {
- mPlayingBackwards = false;
- }
- }
- if (fraction >= 1f) {
- if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
- // Time to repeat
- if (mListeners != null) {
- int numListeners = mListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- mListeners.get(i).onAnimationRepeat(this);
- }
+ final float fraction = getScaledDuration() > 0 ?
+ (float)(currentTime - mStartTime) / getScaledDuration() : 1f;
+ final float lastFraction = mOverallFraction;
+ final boolean newIteration = (int) fraction > (int) lastFraction;
+ final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
+ (mRepeatCount != INFINITE);
+ if (newIteration && !lastIterationFinished) {
+ // Time to repeat
+ if (mListeners != null) {
+ int numListeners = mListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ mListeners.get(i).onAnimationRepeat(this);
}
- if (mRepeatMode == REVERSE) {
- mPlayingBackwards = !mPlayingBackwards;
- }
- mCurrentIteration += (int) fraction;
- fraction = fraction % 1f;
- mStartTime += mDuration;
- // Note: We do not need to update the value of mStartTimeCommitted here
- // since we just added a duration offset.
- } else {
- done = true;
- fraction = Math.min(fraction, 1.0f);
}
+ } else if (lastIterationFinished) {
+ done = true;
}
- if (mPlayingBackwards) {
- fraction = 1f - fraction;
- }
- animateValue(fraction);
+ mOverallFraction = clampFraction(fraction);
+ float currentIterationFraction = getCurrentIterationFraction(mOverallFraction);
+ animateValue(currentIterationFraction);
}
return done;
}
@@ -1207,7 +1217,7 @@
if (mSeekFraction < 0) {
mStartTime = frameTime;
} else {
- long seekTime = (long) (mDuration * mSeekFraction);
+ long seekTime = (long) (getScaledDuration() * mSeekFraction);
mStartTime = frameTime - seekTime;
mSeekFraction = -1;
}
@@ -1285,9 +1295,7 @@
anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(mUpdateListeners);
}
anim.mSeekFraction = -1;
- anim.mPlayingBackwards = false;
anim.mReversing = false;
- anim.mCurrentIteration = 0;
anim.mInitialized = false;
anim.mStarted = false;
anim.mRunning = false;
@@ -1299,6 +1307,7 @@
anim.mAnimationEndRequested = false;
anim.mPauseTime = 0;
anim.mLastFrameTime = 0;
+ anim.mOverallFraction = 0;
anim.mCurrentFraction = 0;
PropertyValuesHolder[] oldValues = mValues;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index faa3a43..b97f947 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -757,9 +757,10 @@
case RESIZE_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- int stackId = data.readInt();
+ final int stackId = data.readInt();
Rect r = Rect.CREATOR.createFromParcel(data);
- resizeStack(stackId, r);
+ final boolean allowResizeInDockedMode = data.readInt() == 1;
+ resizeStack(stackId, r, allowResizeInDockedMode);
reply.writeNoException();
return true;
}
@@ -3554,13 +3555,15 @@
reply.recycle();
}
@Override
- public void resizeStack(int stackId, Rect r) throws RemoteException
+ public void resizeStack(int stackId, Rect r, boolean allowResizeInDockedMode)
+ throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(stackId);
r.writeToParcel(data, 0);
+ data.writeInt(allowResizeInDockedMode ? 1 : 0);
mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f29dba2..e500e15 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1646,7 +1646,8 @@
return false;
}
if (!forceAllowOnExternal
- && app.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
+ && (app.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY
+ || app.installLocation == PackageInfo.INSTALL_LOCATION_UNSPECIFIED)) {
return false;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e23620d..c26a44c 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -143,7 +143,7 @@
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop)
throws RemoteException;
- public void resizeStack(int stackId, Rect bounds) throws RemoteException;
+ public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode) throws RemoteException;
public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException;
public List<StackInfo> getAllStackInfos() throws RemoteException;
public StackInfo getStackInfo(int stackId) throws RemoteException;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e5cfbf3..3f02f17 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -647,20 +647,18 @@
/**
* Open a private file associated with this Context's application package
- * for writing. Creates the file if it doesn't already exist.
- *
- * <p>No permissions are required to invoke this method, since it uses internal
- * storage.
+ * for writing. Creates the file if it doesn't already exist.
+ * <p>
+ * No additional permissions are required for the calling app to read or
+ * write the returned file.
*
* @param name The name of the file to open; can not contain path
- * separators.
- * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
- * default operation, {@link #MODE_APPEND} to append to an existing file,
- * {@link #MODE_WORLD_READABLE} and {@link #MODE_WORLD_WRITEABLE} to control
- * permissions.
- *
+ * separators.
+ * @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
+ * default operation, {@link #MODE_APPEND} to append to an
+ * existing file, {@link #MODE_WORLD_READABLE} and
+ * {@link #MODE_WORLD_WRITEABLE} to control permissions.
* @return The resulting {@link FileOutputStream}.
- *
* @see #MODE_APPEND
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
@@ -693,6 +691,9 @@
/**
* Returns the absolute path on the filesystem where a file created with
* {@link #openFileOutput} is stored.
+ * <p>
+ * The returned path may change over time if the calling app is moved to an
+ * adopted storage device, so only relative paths should be persisted.
*
* @param name The name of the file for which you would like to get
* its path.
@@ -706,14 +707,16 @@
public abstract File getFileStreamPath(String name);
/**
- * Returns the absolute path to the directory on the filesystem where
- * files created with {@link #openFileOutput} are stored.
- *
- * <p>No permissions are required to read or write to the returned path, since this
- * path is internal storage.
+ * Returns the absolute path to the directory on the filesystem where files
+ * created with {@link #openFileOutput} are stored.
+ * <p>
+ * The returned path may change over time if the calling app is moved to an
+ * adopted storage device, so only relative paths should be persisted.
+ * <p>
+ * No additional permissions are required for the calling app to read or
+ * write files under the returned path.
*
* @return The path of the directory holding application files.
- *
* @see #openFileOutput
* @see #getFileStreamPath
* @see #getDir
@@ -722,17 +725,19 @@
/**
* Returns the absolute path to the directory on the filesystem similar to
- * {@link #getFilesDir()}. The difference is that files placed under this
- * directory will be excluded from automatic backup to remote storage. See
+ * {@link #getFilesDir()}. The difference is that files placed under this
+ * directory will be excluded from automatic backup to remote storage. See
* {@link android.app.backup.BackupAgent BackupAgent} for a full discussion
* of the automatic backup mechanism in Android.
+ * <p>
+ * The returned path may change over time if the calling app is moved to an
+ * adopted storage device, so only relative paths should be persisted.
+ * <p>
+ * No additional permissions are required for the calling app to read or
+ * write files under the returned path.
*
- * <p>No permissions are required to read or write to the returned path, since this
- * path is internal storage.
- *
- * @return The path of the directory holding application files that will not be
- * automatically backed up to remote storage.
- *
+ * @return The path of the directory holding application files that will not
+ * be automatically backed up to remote storage.
* @see #openFileOutput
* @see #getFileStreamPath
* @see #getDir
@@ -741,200 +746,256 @@
public abstract File getNoBackupFilesDir();
/**
- * Returns the absolute path to the directory on the primary external filesystem
- * (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory()
- * Environment.getExternalStorageDirectory()}) where the application can
- * place persistent files it owns. These files are internal to the
- * applications, and not typically visible to the user as media.
- *
- * <p>This is like {@link #getFilesDir()} in that these
- * files will be deleted when the application is uninstalled, however there
- * are some important differences:
- *
+ * Returns the absolute path to the directory on the primary shared/external
+ * storage device where the application can place persistent files it owns.
+ * These files are internal to the applications, and not typically visible
+ * to the user as media.
+ * <p>
+ * This is like {@link #getFilesDir()} in that these files will be deleted
+ * when the application is uninstalled, however there are some important
+ * differences:
* <ul>
- * <li>External files are not always available: they will disappear if the
- * user mounts the external storage on a computer or removes it. See the
- * APIs on {@link android.os.Environment} for information in the storage state.
- * <li>There is no security enforced with these files. For example, any application
- * holding {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
+ * <li>Shared storage may not always be available, since removable media can
+ * be ejected by the user. Media state can be checked using
+ * {@link Environment#getExternalStorageState(File)}.
+ * <li>There is no security enforced with these files. For example, any
+ * application holding
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
* these files.
* </ul>
- *
- * <p>Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
+ * <p>
+ * If a shared storage device is emulated (as determined by
+ * {@link Environment#isExternalStorageEmulated(File)}), it's contents are
+ * backed by a private user data partition, which means there is little
+ * benefit to storing data here instead of the private directories returned
+ * by {@link #getFilesDir()}, etc.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to read or write to the returned path; it's always
- * accessible to the calling app. This only applies to paths generated for
- * package name of the calling application. To access paths belonging
- * to other packages, {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE}
- * and/or {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
- *
- * <p>On devices with multiple users (as described by {@link UserManager}),
- * each user has their own isolated external storage. Applications only
- * have access to the external storage for the user they're running as.</p>
- *
- * <p>Here is an example of typical code to manipulate a file in
- * an application's private storage:</p>
- *
+ * accessible to the calling app. This only applies to paths generated for
+ * package name of the calling application. To access paths belonging to
+ * other packages,
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or
+ * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
+ * <p>
+ * On devices with multiple users (as described by {@link UserManager}),
+ * each user has their own isolated shared storage. Applications only have
+ * access to the shared storage for the user they're running as.
+ * <p>
+ * The returned path may change over time if different shared storage media
+ * is inserted, so only relative paths should be persisted.
+ * <p>
+ * Here is an example of typical code to manipulate a file in an
+ * application's shared storage:
+ * </p>
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* private_file}
- *
- * <p>If you supply a non-null <var>type</var> to this function, the returned
- * file will be a path to a sub-directory of the given type. Though these files
- * are not automatically scanned by the media scanner, you can explicitly
- * add them to the media database with
- * {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[],
- * android.media.MediaScannerConnection.OnScanCompletedListener)
- * MediaScannerConnection.scanFile}.
- * Note that this is not the same as
+ * <p>
+ * If you supply a non-null <var>type</var> to this function, the returned
+ * file will be a path to a sub-directory of the given type. Though these
+ * files are not automatically scanned by the media scanner, you can
+ * explicitly add them to the media database with
+ * {@link android.media.MediaScannerConnection#scanFile(Context, String[], String[], android.media.MediaScannerConnection.OnScanCompletedListener)
+ * MediaScannerConnection.scanFile}. Note that this is not the same as
* {@link android.os.Environment#getExternalStoragePublicDirectory
* Environment.getExternalStoragePublicDirectory()}, which provides
- * directories of media shared by all applications. The
- * directories returned here are
- * owned by the application, and their contents will be removed when the
- * application is uninstalled. Unlike
+ * directories of media shared by all applications. The directories returned
+ * here are owned by the application, and their contents will be removed
+ * when the application is uninstalled. Unlike
* {@link android.os.Environment#getExternalStoragePublicDirectory
- * Environment.getExternalStoragePublicDirectory()}, the directory
- * returned here will be automatically created for you.
- *
- * <p>Here is an example of typical code to manipulate a picture in
- * an application's private storage and add it to the media database:</p>
- *
+ * Environment.getExternalStoragePublicDirectory()}, the directory returned
+ * here will be automatically created for you.
+ * <p>
+ * Here is an example of typical code to manipulate a picture in an
+ * application's shared storage and add it to the media database:
+ * </p>
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* private_picture}
*
- * @param type The type of files directory to return. May be null for
- * the root of the files directory or one of
- * the following Environment constants for a subdirectory:
- * {@link android.os.Environment#DIRECTORY_MUSIC},
- * {@link android.os.Environment#DIRECTORY_PODCASTS},
- * {@link android.os.Environment#DIRECTORY_RINGTONES},
- * {@link android.os.Environment#DIRECTORY_ALARMS},
- * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
- * {@link android.os.Environment#DIRECTORY_PICTURES}, or
- * {@link android.os.Environment#DIRECTORY_MOVIES}.
- *
- * @return The path of the directory holding application files
- * on external storage. Returns null if external storage is not currently
- * mounted so it could not ensure the path exists; you will need to call
- * this method again when it is available.
- *
+ * @param type The type of files directory to return. May be {@code null}
+ * for the root of the files directory or one of the following
+ * constants for a subdirectory:
+ * {@link android.os.Environment#DIRECTORY_MUSIC},
+ * {@link android.os.Environment#DIRECTORY_PODCASTS},
+ * {@link android.os.Environment#DIRECTORY_RINGTONES},
+ * {@link android.os.Environment#DIRECTORY_ALARMS},
+ * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
+ * {@link android.os.Environment#DIRECTORY_PICTURES}, or
+ * {@link android.os.Environment#DIRECTORY_MOVIES}.
+ * @return the absolute path to application-specific directory. May return
+ * {@code null} if shared storage is not currently available.
* @see #getFilesDir
- * @see android.os.Environment#getExternalStoragePublicDirectory
+ * @see #getExternalFilesDirs(String)
+ * @see Environment#getExternalStorageState(File)
+ * @see Environment#isExternalStorageEmulated(File)
+ * @see Environment#isExternalStorageRemovable(File)
*/
@Nullable
public abstract File getExternalFilesDir(@Nullable String type);
/**
* Returns absolute paths to application-specific directories on all
- * external storage devices where the application can place persistent files
- * it owns. These files are internal to the application, and not typically
- * visible to the user as media.
+ * shared/external storage devices where the application can place
+ * persistent files it owns. These files are internal to the application,
+ * and not typically visible to the user as media.
* <p>
- * This is like {@link #getFilesDir()} in that these files will be deleted when
- * the application is uninstalled, however there are some important differences:
+ * This is like {@link #getFilesDir()} in that these files will be deleted
+ * when the application is uninstalled, however there are some important
+ * differences:
* <ul>
- * <li>External files are not always available: they will disappear if the
- * user mounts the external storage on a computer or removes it.
- * <li>There is no security enforced with these files.
+ * <li>Shared storage may not always be available, since removable media can
+ * be ejected by the user. Media state can be checked using
+ * {@link Environment#getExternalStorageState(File)}.
+ * <li>There is no security enforced with these files. For example, any
+ * application holding
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
+ * these files.
* </ul>
* <p>
- * External storage devices returned here are considered a permanent part of
- * the device, including both emulated external storage and physical media
- * slots, such as SD cards in a battery compartment. The returned paths do
- * not include transient devices, such as USB flash drives.
+ * If a shared storage device is emulated (as determined by
+ * {@link Environment#isExternalStorageEmulated(File)}), it's contents are
+ * backed by a private user data partition, which means there is little
+ * benefit to storing data here instead of the private directories returned
+ * by {@link #getFilesDir()}, etc.
* <p>
- * An application may store data on any or all of the returned devices. For
+ * Shared storage devices returned here are considered a stable part of the
+ * device, including physical media slots under a protective cover. The
+ * returned paths do not include transient devices, such as USB flash drives
+ * connected to handheld devices.
+ * <p>
+ * An application may store data on any or all of the returned devices. For
* example, an app may choose to store large files on the device with the
* most available space, as measured by {@link StatFs}.
* <p>
- * No permissions are required to read or write to the returned paths; they
- * are always accessible to the calling app. Write access outside of these
- * paths on secondary external storage devices is not available.
+ * No additional permissions are required for the calling app to read or
+ * write files under the returned path. Write access outside of these paths
+ * on secondary external storage devices is not available.
* <p>
- * The first path returned is the same as {@link #getExternalFilesDir(String)}.
- * Returned paths may be {@code null} if a storage device is unavailable.
+ * The returned path may change over time if different shared storage media
+ * is inserted, so only relative paths should be persisted.
*
+ * @param type The type of files directory to return. May be {@code null}
+ * for the root of the files directory or one of the following
+ * constants for a subdirectory:
+ * {@link android.os.Environment#DIRECTORY_MUSIC},
+ * {@link android.os.Environment#DIRECTORY_PODCASTS},
+ * {@link android.os.Environment#DIRECTORY_RINGTONES},
+ * {@link android.os.Environment#DIRECTORY_ALARMS},
+ * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
+ * {@link android.os.Environment#DIRECTORY_PICTURES}, or
+ * {@link android.os.Environment#DIRECTORY_MOVIES}.
+ * @return the absolute paths to application-specific directories. Some
+ * individual paths may be {@code null} if that shared storage is
+ * not currently available. The first path returned is the same as
+ * {@link #getExternalFilesDir(String)}.
* @see #getExternalFilesDir(String)
* @see Environment#getExternalStorageState(File)
+ * @see Environment#isExternalStorageEmulated(File)
+ * @see Environment#isExternalStorageRemovable(File)
*/
public abstract File[] getExternalFilesDirs(String type);
/**
- * Return the primary external storage directory where this application's OBB
- * files (if there are any) can be found. Note if the application does not have
- * any OBB files, this directory may not exist.
+ * Return the primary shared/external storage directory where this
+ * application's OBB files (if there are any) can be found. Note if the
+ * application does not have any OBB files, this directory may not exist.
* <p>
- * This is like {@link #getFilesDir()} in that these files will be deleted when
- * the application is uninstalled, however there are some important differences:
+ * This is like {@link #getFilesDir()} in that these files will be deleted
+ * when the application is uninstalled, however there are some important
+ * differences:
* <ul>
- * <li>External files are not always available: they will disappear if the
- * user mounts the external storage on a computer or removes it.
- * <li>There is no security enforced with these files. For example, any application
- * holding {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
+ * <li>Shared storage may not always be available, since removable media can
+ * be ejected by the user. Media state can be checked using
+ * {@link Environment#getExternalStorageState(File)}.
+ * <li>There is no security enforced with these files. For example, any
+ * application holding
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
* these files.
* </ul>
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to read or write to the returned path; it's always
- * accessible to the calling app. This only applies to paths generated for
- * package name of the calling application. To access paths belonging
- * to other packages, {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE}
- * and/or {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
+ * accessible to the calling app. This only applies to paths generated for
+ * package name of the calling application. To access paths belonging to
+ * other packages,
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or
+ * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
* <p>
* On devices with multiple users (as described by {@link UserManager}),
* multiple users may share the same OBB storage location. Applications
* should ensure that multiple instances running under different users don't
* interfere with each other.
+ *
+ * @return the absolute path to application-specific directory. May return
+ * {@code null} if shared storage is not currently available.
+ * @see #getObbDirs()
+ * @see Environment#getExternalStorageState(File)
+ * @see Environment#isExternalStorageEmulated(File)
+ * @see Environment#isExternalStorageRemovable(File)
*/
public abstract File getObbDir();
/**
* Returns absolute paths to application-specific directories on all
- * external storage devices where the application's OBB files (if there are
- * any) can be found. Note if the application does not have any OBB files,
- * these directories may not exist.
+ * shared/external storage devices where the application's OBB files (if
+ * there are any) can be found. Note if the application does not have any
+ * OBB files, these directories may not exist.
* <p>
- * This is like {@link #getFilesDir()} in that these files will be deleted when
- * the application is uninstalled, however there are some important differences:
+ * This is like {@link #getFilesDir()} in that these files will be deleted
+ * when the application is uninstalled, however there are some important
+ * differences:
* <ul>
- * <li>External files are not always available: they will disappear if the
- * user mounts the external storage on a computer or removes it.
- * <li>There is no security enforced with these files.
+ * <li>Shared storage may not always be available, since removable media can
+ * be ejected by the user. Media state can be checked using
+ * {@link Environment#getExternalStorageState(File)}.
+ * <li>There is no security enforced with these files. For example, any
+ * application holding
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
+ * these files.
* </ul>
* <p>
- * External storage devices returned here are considered a permanent part of
- * the device, including both emulated external storage and physical media
- * slots, such as SD cards in a battery compartment. The returned paths do
- * not include transient devices, such as USB flash drives.
+ * Shared storage devices returned here are considered a stable part of the
+ * device, including physical media slots under a protective cover. The
+ * returned paths do not include transient devices, such as USB flash drives
+ * connected to handheld devices.
* <p>
- * An application may store data on any or all of the returned devices. For
+ * An application may store data on any or all of the returned devices. For
* example, an app may choose to store large files on the device with the
* most available space, as measured by {@link StatFs}.
* <p>
- * No permissions are required to read or write to the returned paths; they
- * are always accessible to the calling app. Write access outside of these
- * paths on secondary external storage devices is not available.
- * <p>
- * The first path returned is the same as {@link #getObbDir()}.
- * Returned paths may be {@code null} if a storage device is unavailable.
+ * No additional permissions are required for the calling app to read or
+ * write files under the returned path. Write access outside of these paths
+ * on secondary external storage devices is not available.
*
+ * @return the absolute paths to application-specific directories. Some
+ * individual paths may be {@code null} if that shared storage is
+ * not currently available. The first path returned is the same as
+ * {@link #getObbDir()}
* @see #getObbDir()
* @see Environment#getExternalStorageState(File)
+ * @see Environment#isExternalStorageEmulated(File)
+ * @see Environment#isExternalStorageRemovable(File)
*/
public abstract File[] getObbDirs();
/**
- * Returns the absolute path to the application specific cache directory
- * on the filesystem. These files will be ones that get deleted first when the
- * device runs low on storage.
- * There is no guarantee when these files will be deleted.
- *
+ * Returns the absolute path to the application specific cache directory on
+ * the filesystem. These files will be ones that get deleted first when the
+ * device runs low on storage. There is no guarantee when these files will
+ * be deleted.
+ * <p>
* <strong>Note: you should not <em>rely</em> on the system deleting these
* files for you; you should always have a reasonable maximum, such as 1 MB,
* for the amount of space you consume with cache files, and prune those
* files when exceeding that space.</strong>
+ * <p>
+ * The returned path may change over time if the calling app is moved to an
+ * adopted storage device, so only relative paths should be persisted.
+ * <p>
+ * Apps require no extra permissions to read or write to the returned path,
+ * since this path lives in their private storage.
*
* @return The path of the directory holding application cache files.
- *
* @see #openFileOutput
* @see #getFileStreamPath
* @see #getDir
@@ -950,6 +1011,9 @@
* This location is optimal for storing compiled or optimized code generated
* by your application at runtime.
* <p>
+ * The returned path may change over time if the calling app is moved to an
+ * adopted storage device, so only relative paths should be persisted.
+ * <p>
* Apps require no extra permissions to read or write to the returned path,
* since this path lives in their private storage.
*
@@ -958,120 +1022,161 @@
public abstract File getCodeCacheDir();
/**
- * Returns the absolute path to the directory on the primary external filesystem
- * (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory()
- * Environment.getExternalStorageDirectory()} where the application can
- * place cache files it owns. These files are internal to the application, and
- * not typically visible to the user as media.
- *
- * <p>This is like {@link #getCacheDir()} in that these
- * files will be deleted when the application is uninstalled, however there
- * are some important differences:
- *
+ * Returns absolute path to application-specific directory on the primary
+ * shared/external storage device where the application can place cache
+ * files it owns. These files are internal to the application, and not
+ * typically visible to the user as media.
+ * <p>
+ * This is like {@link #getCacheDir()} in that these files will be deleted
+ * when the application is uninstalled, however there are some important
+ * differences:
* <ul>
- * <li>The platform does not always monitor the space available in external
- * storage, and thus may not automatically delete these files. Currently
- * the only time files here will be deleted by the platform is when running
- * on {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} or later and
- * {@link android.os.Environment#isExternalStorageEmulated()
- * Environment.isExternalStorageEmulated()} returns true. Note that you should
- * be managing the maximum space you will use for these anyway, just like
- * with {@link #getCacheDir()}.
- * <li>External files are not always available: they will disappear if the
- * user mounts the external storage on a computer or removes it. See the
- * APIs on {@link android.os.Environment} for information in the storage state.
- * <li>There is no security enforced with these files. For example, any application
- * holding {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
+ * <li>The platform does not always monitor the space available in shared
+ * storage, and thus may not automatically delete these files. Apps should
+ * always manage the maximum space used in this location. Currently the only
+ * time files here will be deleted by the platform is when running on
+ * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} or later and
+ * {@link Environment#isExternalStorageEmulated(File)} returns true.
+ * <li>Shared storage may not always be available, since removable media can
+ * be ejected by the user. Media state can be checked using
+ * {@link Environment#getExternalStorageState(File)}.
+ * <li>There is no security enforced with these files. For example, any
+ * application holding
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
* these files.
* </ul>
- *
- * <p>Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
+ * <p>
+ * If a shared storage device is emulated (as determined by
+ * {@link Environment#isExternalStorageEmulated(File)}), it's contents are
+ * backed by a private user data partition, which means there is little
+ * benefit to storing data here instead of the private directory returned by
+ * {@link #getCacheDir()}.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
* are required to read or write to the returned path; it's always
- * accessible to the calling app. This only applies to paths generated for
- * package name of the calling application. To access paths belonging
- * to other packages, {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE}
- * and/or {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
+ * accessible to the calling app. This only applies to paths generated for
+ * package name of the calling application. To access paths belonging to
+ * other packages,
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or
+ * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
+ * <p>
+ * On devices with multiple users (as described by {@link UserManager}),
+ * each user has their own isolated shared storage. Applications only have
+ * access to the shared storage for the user they're running as.
+ * <p>
+ * The returned path may change over time if different shared storage media
+ * is inserted, so only relative paths should be persisted.
*
- * <p>On devices with multiple users (as described by {@link UserManager}),
- * each user has their own isolated external storage. Applications only
- * have access to the external storage for the user they're running as.</p>
- *
- * @return The path of the directory holding application cache files
- * on external storage. Returns null if external storage is not currently
- * mounted so it could not ensure the path exists; you will need to call
- * this method again when it is available.
- *
+ * @return the absolute path to application-specific directory. May return
+ * {@code null} if shared storage is not currently available.
* @see #getCacheDir
+ * @see #getExternalCacheDirs()
+ * @see Environment#getExternalStorageState(File)
+ * @see Environment#isExternalStorageEmulated(File)
+ * @see Environment#isExternalStorageRemovable(File)
*/
@Nullable
public abstract File getExternalCacheDir();
/**
* Returns absolute paths to application-specific directories on all
- * external storage devices where the application can place cache files it
- * owns. These files are internal to the application, and not typically
- * visible to the user as media.
+ * shared/external storage devices where the application can place cache
+ * files it owns. These files are internal to the application, and not
+ * typically visible to the user as media.
* <p>
- * This is like {@link #getCacheDir()} in that these files will be deleted when
- * the application is uninstalled, however there are some important differences:
+ * This is like {@link #getCacheDir()} in that these files will be deleted
+ * when the application is uninstalled, however there are some important
+ * differences:
* <ul>
- * <li>External files are not always available: they will disappear if the
- * user mounts the external storage on a computer or removes it.
- * <li>There is no security enforced with these files.
+ * <li>The platform does not always monitor the space available in shared
+ * storage, and thus may not automatically delete these files. Apps should
+ * always manage the maximum space used in this location. Currently the only
+ * time files here will be deleted by the platform is when running on
+ * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1} or later and
+ * {@link Environment#isExternalStorageEmulated(File)} returns true.
+ * <li>Shared storage may not always be available, since removable media can
+ * be ejected by the user. Media state can be checked using
+ * {@link Environment#getExternalStorageState(File)}.
+ * <li>There is no security enforced with these files. For example, any
+ * application holding
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
+ * these files.
* </ul>
* <p>
- * External storage devices returned here are considered a permanent part of
- * the device, including both emulated external storage and physical media
- * slots, such as SD cards in a battery compartment. The returned paths do
- * not include transient devices, such as USB flash drives.
+ * If a shared storage device is emulated (as determined by
+ * {@link Environment#isExternalStorageEmulated(File)}), it's contents are
+ * backed by a private user data partition, which means there is little
+ * benefit to storing data here instead of the private directory returned by
+ * {@link #getCacheDir()}.
* <p>
- * An application may store data on any or all of the returned devices. For
+ * Shared storage devices returned here are considered a stable part of the
+ * device, including physical media slots under a protective cover. The
+ * returned paths do not include transient devices, such as USB flash drives
+ * connected to handheld devices.
+ * <p>
+ * An application may store data on any or all of the returned devices. For
* example, an app may choose to store large files on the device with the
* most available space, as measured by {@link StatFs}.
* <p>
- * No permissions are required to read or write to the returned paths; they
- * are always accessible to the calling app. Write access outside of these
- * paths on secondary external storage devices is not available.
+ * No additional permissions are required for the calling app to read or
+ * write files under the returned path. Write access outside of these paths
+ * on secondary external storage devices is not available.
* <p>
- * The first path returned is the same as {@link #getExternalCacheDir()}.
- * Returned paths may be {@code null} if a storage device is unavailable.
+ * The returned paths may change over time if different shared storage media
+ * is inserted, so only relative paths should be persisted.
*
+ * @return the absolute paths to application-specific directories. Some
+ * individual paths may be {@code null} if that shared storage is
+ * not currently available. The first path returned is the same as
+ * {@link #getExternalCacheDir()}.
* @see #getExternalCacheDir()
* @see Environment#getExternalStorageState(File)
+ * @see Environment#isExternalStorageEmulated(File)
+ * @see Environment#isExternalStorageRemovable(File)
*/
public abstract File[] getExternalCacheDirs();
/**
* Returns absolute paths to application-specific directories on all
- * external storage devices where the application can place media files.
- * These files are scanned and made available to other apps through
+ * shared/external storage devices where the application can place media
+ * files. These files are scanned and made available to other apps through
* {@link MediaStore}.
* <p>
* This is like {@link #getExternalFilesDirs} in that these files will be
* deleted when the application is uninstalled, however there are some
* important differences:
* <ul>
- * <li>External files are not always available: they will disappear if the
- * user mounts the external storage on a computer or removes it.
- * <li>There is no security enforced with these files.
+ * <li>Shared storage may not always be available, since removable media can
+ * be ejected by the user. Media state can be checked using
+ * {@link Environment#getExternalStorageState(File)}.
+ * <li>There is no security enforced with these files. For example, any
+ * application holding
+ * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} can write to
+ * these files.
* </ul>
* <p>
- * External storage devices returned here are considered a permanent part of
- * the device, including both emulated external storage and physical media
- * slots, such as SD cards in a battery compartment. The returned paths do
- * not include transient devices, such as USB flash drives.
+ * Shared storage devices returned here are considered a stable part of the
+ * device, including physical media slots under a protective cover. The
+ * returned paths do not include transient devices, such as USB flash drives
+ * connected to handheld devices.
* <p>
* An application may store data on any or all of the returned devices. For
* example, an app may choose to store large files on the device with the
* most available space, as measured by {@link StatFs}.
* <p>
- * No permissions are required to read or write to the returned paths; they
- * are always accessible to the calling app. Write access outside of these
- * paths on secondary external storage devices is not available.
+ * No additional permissions are required for the calling app to read or
+ * write files under the returned path. Write access outside of these paths
+ * on secondary external storage devices is not available.
* <p>
- * Returned paths may be {@code null} if a storage device is unavailable.
+ * The returned paths may change over time if different shared storage media
+ * is inserted, so only relative paths should be persisted.
*
+ * @return the absolute paths to application-specific directories. Some
+ * individual paths may be {@code null} if that shared storage is
+ * not currently available.
* @see Environment#getExternalStorageState(File)
+ * @see Environment#isExternalStorageEmulated(File)
+ * @see Environment#isExternalStorageRemovable(File)
*/
public abstract File[] getExternalMediaDirs();
@@ -1094,6 +1199,12 @@
* created through a File object will only be accessible by your own
* application; you can only set the mode of the entire directory, not
* of individual files.
+ * <p>
+ * The returned path may change over time if the calling app is moved to an
+ * adopted storage device, so only relative paths should be persisted.
+ * <p>
+ * Apps require no extra permissions to read or write to the returned path,
+ * since this path lives in their private storage.
*
* @param name Name of the directory to retrieve. This is a directory
* that is created as part of your application data.
@@ -1177,6 +1288,9 @@
/**
* Returns the absolute path on the filesystem where a database created with
* {@link #openOrCreateDatabase} is stored.
+ * <p>
+ * The returned path may change over time if the calling app is moved to an
+ * adopted storage device, so only relative paths should be persisted.
*
* @param name The name of the database for which you would like to get
* its path.
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index a121b4d..3853772 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -67,7 +67,7 @@
* The launch mode style requested by the activity. From the
* {@link android.R.attr#launchMode} attribute, one of
* {@link #LAUNCH_MULTIPLE},
- * {@link #LAUNCH_SINGLE_TOP}, {@link #LAUNCH_SINGLE_TASK}, or
+ * {@link #LAUNCH_SINGLE_TOP}, {@link #LAUNCH_SINGLE_TASK}, or
* {@link #LAUNCH_SINGLE_INSTANCE}.
*/
public int launchMode;
@@ -140,7 +140,7 @@
* Activity. From the "permission" attribute.
*/
public String permission;
-
+
/**
* The affinity this activity has for another task in the system. The
* string here is the name of the task, often the package name of the
@@ -148,13 +148,13 @@
* {@link android.R.attr#taskAffinity} attribute.
*/
public String taskAffinity;
-
+
/**
* If this is an activity alias, this is the real activity class to run
* for it. Otherwise, this is null.
*/
public String targetActivity;
-
+
/**
* Bit in {@link #flags} indicating whether this activity is able to
* run in multiple processes. If
@@ -362,7 +362,7 @@
* the {@link android.R.attr#screenOrientation} attribute.
*/
public static final int SCREEN_ORIENTATION_SENSOR = 4;
-
+
/**
* Constant corresponding to <code>nosensor</code> in
* the {@link android.R.attr#screenOrientation} attribute.
@@ -427,7 +427,7 @@
* The preferred screen orientation this activity would like to run in.
* From the {@link android.R.attr#screenOrientation} attribute, one of
* {@link #SCREEN_ORIENTATION_UNSPECIFIED},
- * {@link #SCREEN_ORIENTATION_LANDSCAPE},
+ * {@link #SCREEN_ORIENTATION_LANDSCAPE},
* {@link #SCREEN_ORIENTATION_PORTRAIT},
* {@link #SCREEN_ORIENTATION_USER},
* {@link #SCREEN_ORIENTATION_BEHIND},
@@ -445,7 +445,7 @@
*/
@ScreenOrientation
public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
-
+
/**
* Bit in {@link #configChanges} that indicates that the activity
* can itself handle changes to the IMSI MCC. Set from the
@@ -552,7 +552,7 @@
* constant starts at the high bits.
*/
public static final int CONFIG_FONT_SCALE = 0x40000000;
-
+
/** @hide
* Unfortunately the constants for config changes in native code are
* different from ActivityInfo. :( Here are the values we should use for the
@@ -702,7 +702,7 @@
*/
public int lockTaskLaunchMode;
- public InitialLayout initialLayout;
+ public Layout layout;
public ActivityInfo() {
}
@@ -724,7 +724,7 @@
maxRecents = orig.maxRecents;
resizeable = orig.resizeable;
lockTaskLaunchMode = orig.lockTaskLaunchMode;
- initialLayout = orig.initialLayout;
+ layout = orig.layout;
}
/**
@@ -771,10 +771,10 @@
}
pw.println(prefix + "resizeable=" + resizeable + " lockTaskLaunchMode="
+ lockTaskLaunchModeToString(lockTaskLaunchMode));
- if (initialLayout != null) {
- pw.println(prefix + "initialLayout=" + initialLayout.width + "|"
- + initialLayout.widthFraction + ", " + initialLayout.height + "|"
- + initialLayout.heightFraction + ", " + initialLayout.gravity);
+ if (layout != null) {
+ pw.println(prefix + "initialLayout=" + layout.width + "|"
+ + layout.widthFraction + ", " + layout.height + "|"
+ + layout.heightFraction + ", " + layout.gravity);
}
super.dumpBack(pw, prefix);
}
@@ -807,13 +807,14 @@
dest.writeInt(maxRecents);
dest.writeInt(resizeable ? 1 : 0);
dest.writeInt(lockTaskLaunchMode);
- if (initialLayout != null) {
+ if (layout != null) {
dest.writeInt(1);
- dest.writeInt(initialLayout.width);
- dest.writeFloat(initialLayout.widthFraction);
- dest.writeInt(initialLayout.height);
- dest.writeFloat(initialLayout.heightFraction);
- dest.writeInt(initialLayout.gravity);
+ dest.writeInt(layout.width);
+ dest.writeFloat(layout.widthFraction);
+ dest.writeInt(layout.height);
+ dest.writeFloat(layout.heightFraction);
+ dest.writeInt(layout.gravity);
+ dest.writeInt(layout.minimalSize);
} else {
dest.writeInt(0);
}
@@ -848,26 +849,28 @@
resizeable = (source.readInt() == 1);
lockTaskLaunchMode = source.readInt();
if (source.readInt() == 1) {
- initialLayout = new InitialLayout(source);
+ layout = new Layout(source);
}
}
- public static final class InitialLayout {
- public InitialLayout(int width, float widthFraction, int height, float heightFraction,
- int gravity) {
+ public static final class Layout {
+ public Layout(int width, float widthFraction, int height, float heightFraction, int gravity,
+ int minimalSize) {
this.width = width;
this.widthFraction = widthFraction;
this.height = height;
this.heightFraction = heightFraction;
this.gravity = gravity;
+ this.minimalSize = minimalSize;
}
- InitialLayout(Parcel source) {
+ Layout(Parcel source) {
width = source.readInt();
widthFraction = source.readFloat();
height = source.readInt();
heightFraction = source.readFloat();
gravity = source.readInt();
+ minimalSize = source.readInt();
}
public final int width;
@@ -875,5 +878,6 @@
public final int height;
public final float heightFraction;
public final int gravity;
+ public final int minimalSize;
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 1a8602b..bf54415 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -128,7 +128,7 @@
public final String name;
public final int sdkVersion;
public final int fileVersion;
-
+
public NewPermissionInfo(String name, int sdkVersion, int fileVersion) {
this.name = name;
this.sdkVersion = sdkVersion;
@@ -215,10 +215,10 @@
final int iconRes;
final int logoRes;
final int bannerRes;
-
+
String tag;
TypedArray sa;
-
+
ParsePackageItemArgs(Package _owner, String[] _outError,
int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes) {
owner = _owner;
@@ -230,14 +230,14 @@
bannerRes = _bannerRes;
}
}
-
+
static class ParseComponentArgs extends ParsePackageItemArgs {
final String[] sepProcesses;
final int processRes;
final int descriptionRes;
final int enabledRes;
int flags;
-
+
ParseComponentArgs(Package _owner, String[] _outError,
int _nameRes, int _labelRes, int _iconRes, int _logoRes, int _bannerRes,
String[] _sepProcesses, int _processRes,
@@ -349,7 +349,7 @@
private ParseComponentArgs mParseActivityAliasArgs;
private ParseComponentArgs mParseServiceArgs;
private ParseComponentArgs mParseProviderArgs;
-
+
/** If set to true, we will only allow package files that exactly match
* the DTD. Otherwise, we try to get as much from the package as we
* can without failing. This should normally be set to false, to
@@ -1456,7 +1456,7 @@
int supportsXLargeScreens = 1;
int resizeable = 1;
int anyDensity = 1;
-
+
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -1612,7 +1612,7 @@
String minCode = null;
int targetVers = 0;
String targetCode = null;
-
+
TypedValue val = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
if (val != null) {
@@ -1623,7 +1623,7 @@
targetVers = minVers = val.data;
}
}
-
+
val = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
if (val != null) {
@@ -1634,7 +1634,7 @@
targetVers = val.data;
}
}
-
+
sa.recycle();
if (minCode != null) {
@@ -1663,7 +1663,7 @@
mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
return null;
}
-
+
if (targetCode != null) {
boolean allowedCodename = false;
for (String codename : SDK_CODENAMES) {
@@ -1730,9 +1730,9 @@
anyDensity);
sa.recycle();
-
+
XmlUtils.skipCurrentTag(parser);
-
+
} else if (tagName.equals("protected-broadcast")) {
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
@@ -1754,12 +1754,12 @@
}
XmlUtils.skipCurrentTag(parser);
-
+
} else if (tagName.equals("instrumentation")) {
if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
return null;
}
-
+
} else if (tagName.equals("original-package")) {
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestOriginalPackage);
@@ -1777,7 +1777,7 @@
sa.recycle();
XmlUtils.skipCurrentTag(parser);
-
+
} else if (tagName.equals("adopt-permissions")) {
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestOriginalPackage);
@@ -1795,12 +1795,12 @@
}
XmlUtils.skipCurrentTag(parser);
-
+
} else if (tagName.equals("uses-gl-texture")) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
continue;
-
+
} else if (tagName.equals("compatible-screens")) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
@@ -1808,12 +1808,12 @@
} else if (tagName.equals("supports-input")) {
XmlUtils.skipCurrentTag(parser);
continue;
-
+
} else if (tagName.equals("eat-comment")) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
continue;
-
+
} else if (RIGID_PARSER) {
outError[0] = "Bad element under <manifest>: "
+ parser.getName();
@@ -2017,7 +2017,7 @@
}
return proc.intern();
}
-
+
private static String buildProcessName(String pkg, String defProc,
CharSequence procSeq, int flags, String[] separateProcesses,
String[] outError) {
@@ -2226,7 +2226,7 @@
}
sa.recycle();
-
+
if (!parseAllMetaData(res, parser, attrs, "<permission-group>", perm,
outError)) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
@@ -2265,7 +2265,7 @@
if (perm.info.group != null) {
perm.info.group = perm.info.group.intern();
}
-
+
perm.info.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestPermission_description,
0);
@@ -2296,7 +2296,7 @@
return null;
}
}
-
+
if (!parseAllMetaData(res, parser, attrs, "<permission>", perm,
outError)) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
@@ -2329,7 +2329,7 @@
}
sa.recycle();
-
+
int index = perm.info.name.indexOf('.');
if (index > 0) {
index = perm.info.name.indexOf('.', index+1);
@@ -2371,9 +2371,9 @@
com.android.internal.R.styleable.AndroidManifestInstrumentation_banner);
mParseInstrumentationArgs.tag = "<instrumentation>";
}
-
+
mParseInstrumentationArgs.sa = sa;
-
+
Instrumentation a = new Instrumentation(mParseInstrumentationArgs,
new InstrumentationInfo());
if (outError[0] != null) {
@@ -2650,10 +2650,10 @@
}
ai.processName = buildProcessName(ai.packageName, null, pname,
flags, mSeparateProcesses, outError);
-
+
ai.enabled = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);
-
+
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
ai.flags |= ApplicationInfo.FLAG_IS_GAME;
@@ -3022,7 +3022,7 @@
outInfo.icon = iconVal;
outInfo.nonLocalizedLabel = null;
}
-
+
int logoVal = sa.getResourceId(logoRes, 0);
if (logoVal != 0) {
outInfo.logo = logoVal;
@@ -3061,11 +3061,11 @@
R.styleable.AndroidManifestActivity_description,
R.styleable.AndroidManifestActivity_enabled);
}
-
+
mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
mParseActivityArgs.sa = sa;
mParseActivityArgs.flags = flags;
-
+
Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
if (outError[0] != null) {
sa.recycle();
@@ -3236,7 +3236,7 @@
outError[0] = "Heavy-weight applications can not have receivers in main process";
}
}
-
+
if (outError[0] != null) {
return null;
}
@@ -3282,8 +3282,8 @@
outError)) == null) {
return null;
}
- } else if (!receiver && parser.getName().equals("initial-layout")) {
- parseInitialLayout(res, attrs, a);
+ } else if (!receiver && parser.getName().equals("layout")) {
+ parseLayout(res, attrs, a);
} else {
if (!RIGID_PARSER) {
Slog.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
@@ -3316,41 +3316,44 @@
return a;
}
- private void parseInitialLayout(Resources res, AttributeSet attrs, Activity a) {
+ private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
TypedArray sw = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestInitialLayout);
+ com.android.internal.R.styleable.AndroidManifestLayout);
int width = -1;
float widthFraction = -1f;
int height = -1;
float heightFraction = -1f;
final int widthType = sw.getType(
- com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth);
+ com.android.internal.R.styleable.AndroidManifestLayout_initialWidth);
if (widthType == TypedValue.TYPE_FRACTION) {
widthFraction = sw.getFraction(
- com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
+ com.android.internal.R.styleable.AndroidManifestLayout_initialWidth,
1, 1, -1);
} else if (widthType == TypedValue.TYPE_DIMENSION) {
width = sw.getDimensionPixelSize(
- com.android.internal.R.styleable.AndroidManifestInitialLayout_activityWidth,
+ com.android.internal.R.styleable.AndroidManifestLayout_initialWidth,
-1);
}
final int heightType = sw.getType(
- com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight);
+ com.android.internal.R.styleable.AndroidManifestLayout_initialHeight);
if (heightType == TypedValue.TYPE_FRACTION) {
heightFraction = sw.getFraction(
- com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
+ com.android.internal.R.styleable.AndroidManifestLayout_initialHeight,
1, 1, -1);
} else if (heightType == TypedValue.TYPE_DIMENSION) {
height = sw.getDimensionPixelSize(
- com.android.internal.R.styleable.AndroidManifestInitialLayout_activityHeight,
+ com.android.internal.R.styleable.AndroidManifestLayout_initialHeight,
-1);
}
int gravity = sw.getInt(
- com.android.internal.R.styleable.AndroidManifestInitialLayout_gravity,
+ com.android.internal.R.styleable.AndroidManifestLayout_gravity,
Gravity.CENTER);
+ int minimalSize = sw.getDimensionPixelSize(
+ com.android.internal.R.styleable.AndroidManifestLayout_minimalSize,
+ -1);
sw.recycle();
- a.info.initialLayout = new ActivityInfo.InitialLayout(width, widthFraction,
- height, heightFraction, gravity);
+ a.info.layout = new ActivityInfo.Layout(width, widthFraction,
+ height, heightFraction, gravity, minimalSize);
}
private Activity parseActivityAlias(Package owner, Resources res,
@@ -3388,10 +3391,10 @@
com.android.internal.R.styleable.AndroidManifestActivityAlias_enabled);
mParseActivityAliasArgs.tag = "<activity-alias>";
}
-
+
mParseActivityAliasArgs.sa = sa;
mParseActivityAliasArgs.flags = flags;
-
+
Activity target = null;
final int NA = owner.activities.size();
@@ -3432,7 +3435,7 @@
info.uiOptions = target.info.uiOptions;
info.parentActivityName = target.info.parentActivityName;
info.maxRecents = target.info.maxRecents;
- info.initialLayout = target.info.initialLayout;
+ info.layout = target.info.layout;
Activity a = new Activity(mParseActivityAliasArgs, info);
if (outError[0] != null) {
@@ -3540,10 +3543,10 @@
com.android.internal.R.styleable.AndroidManifestProvider_enabled);
mParseProviderArgs.tag = "<provider>";
}
-
+
mParseProviderArgs.sa = sa;
mParseProviderArgs.flags = flags;
-
+
Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
if (outError[0] != null) {
sa.recycle();
@@ -3632,7 +3635,7 @@
return null;
}
}
-
+
if (cpname == null) {
outError[0] = "<provider> does not include authorities attribute";
return null;
@@ -3675,7 +3678,7 @@
outInfo.metaData, outError)) == null) {
return false;
}
-
+
} else if (parser.getName().equals("grant-uri-permission")) {
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
@@ -3699,7 +3702,7 @@
if (str != null) {
pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
}
-
+
sa.recycle();
if (pa != null) {
@@ -3746,7 +3749,7 @@
if (writePermission == null) {
writePermission = permission;
}
-
+
boolean havePerm = false;
if (readPermission != null) {
readPermission = readPermission.intern();
@@ -3769,7 +3772,7 @@
return false;
}
}
-
+
String path = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestPathPermission_path, 0);
if (path != null) {
@@ -3852,10 +3855,10 @@
com.android.internal.R.styleable.AndroidManifestService_enabled);
mParseServiceArgs.tag = "<service>";
}
-
+
mParseServiceArgs.sa = sa;
mParseServiceArgs.flags = flags;
-
+
Service s = new Service(mParseServiceArgs, new ServiceInfo());
if (outError[0] != null) {
sa.recycle();
@@ -3912,7 +3915,7 @@
return null;
}
}
-
+
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -4010,7 +4013,7 @@
}
name = name.intern();
-
+
TypedValue v = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestMetaData_resource);
if (v != null && v.resourceId != 0) {
@@ -4152,7 +4155,7 @@
outInfo.icon = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestIntentFilter_icon, 0);
-
+
outInfo.logo = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestIntentFilter_logo, 0);
@@ -4373,7 +4376,7 @@
public ArrayList<String> mOriginalPackages = null;
public String mRealPackage = null;
public ArrayList<String> mAdoptPermissions = null;
-
+
// We store the application meta-data independently to avoid multiple unwanted references
public Bundle mAppMetaData = null;
@@ -4382,7 +4385,7 @@
// The version name declared for this package.
public String mVersionName;
-
+
// The shared user id that this package wants to use.
public String mSharedUserId;
@@ -4604,7 +4607,7 @@
ComponentName componentName;
String componentShortName;
-
+
public Component(Package _owner) {
owner = _owner;
intents = null;
@@ -4636,7 +4639,7 @@
outInfo.icon = iconVal;
outInfo.nonLocalizedLabel = null;
}
-
+
int logoVal = args.sa.getResourceId(args.logoRes, 0);
if (logoVal != 0) {
outInfo.logo = logoVal;
@@ -4676,11 +4679,11 @@
owner.applicationInfo.processName, pname,
args.flags, args.sepProcesses, args.outError);
}
-
+
if (args.descriptionRes != 0) {
outInfo.descriptionRes = args.sa.getResourceId(args.descriptionRes, 0);
}
-
+
outInfo.enabled = args.sa.getBoolean(args.enabledRes, true);
}
@@ -4691,7 +4694,7 @@
componentName = clone.componentName;
componentShortName = clone.componentShortName;
}
-
+
public ComponentName getComponentName() {
if (componentName != null) {
return componentName;
@@ -4716,7 +4719,7 @@
componentShortName = null;
}
}
-
+
public final static class Permission extends Component<IntentInfo> {
public final PermissionInfo info;
public boolean tree;
@@ -4731,7 +4734,7 @@
super(_owner);
info = _info;
}
-
+
public void setPackageName(String packageName) {
super.setPackageName(packageName);
info.packageName = packageName;
@@ -4922,7 +4925,7 @@
info = _info;
info.applicationInfo = args.owner.applicationInfo;
}
-
+
public void setPackageName(String packageName) {
super.setPackageName(packageName);
info.packageName = packageName;
@@ -4976,7 +4979,7 @@
info = _info;
info.applicationInfo = args.owner.applicationInfo;
}
-
+
public void setPackageName(String packageName) {
super.setPackageName(packageName);
info.packageName = packageName;
@@ -5019,7 +5022,7 @@
info.applicationInfo = args.owner.applicationInfo;
syncable = false;
}
-
+
public Provider(Provider existingProvider) {
super(existingProvider);
this.info = existingProvider.info;
@@ -5070,7 +5073,7 @@
super(args, _info);
info = _info;
}
-
+
public void setPackageName(String packageName) {
super.setPackageName(packageName);
info.packageName = packageName;
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index c8b45c7..c6ae14e 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -67,4 +67,6 @@
// Input device vibrator control.
void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token);
void cancelVibrate(int deviceId, IBinder token);
+
+ void setPointerIconShape(int shapeId);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index bae5757..3949d97 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -757,6 +757,22 @@
}
}
+ /**
+ * Changes the mouse pointer's icon shape into the specified id.
+ *
+ * @param iconId The id of the pointer graphic, as a value between
+ * {@link PointerIcon.STYLE_ARROW} and {@link PointerIcon.STYLE_GRABBING}.
+ *
+ * @hide
+ */
+ public void setPointerIconShape(int iconId) {
+ try {
+ mIm.setPointerIconShape(iconId);
+ } catch (RemoteException ex) {
+ // Do nothing.
+ }
+ }
+
private void populateInputDevicesLocked() {
if (mInputDevicesChangedListener == null) {
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 3f40484..a83e722 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -50,12 +50,13 @@
public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2;
/* RULE_* are not masks and they must be exclusive */
+ public static final int RULE_UNKNOWN = -1;
/** All network traffic should be allowed. */
- public static final int RULE_ALLOW_ALL = 0x0;
+ public static final int RULE_ALLOW_ALL = 0;
/** Reject traffic on metered networks. */
- public static final int RULE_REJECT_METERED = 0x1;
+ public static final int RULE_REJECT_METERED = 1;
/** Reject traffic on all networks. */
- public static final int RULE_REJECT_ALL = 0x2;
+ public static final int RULE_REJECT_ALL = 2;
public static final int FIREWALL_RULE_DEFAULT = 0;
public static final int FIREWALL_RULE_ALLOW = 1;
@@ -326,25 +327,4 @@
// nothing found above; we can apply policy to UID
return true;
}
-
- /** {@hide} */
- public static void dumpPolicy(PrintWriter fout, int policy) {
- fout.write("[");
- if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
- fout.write("REJECT_METERED_BACKGROUND");
- }
- fout.write("]");
- }
-
- /** {@hide} */
- public static void dumpRules(PrintWriter fout, int rules) {
- fout.write("[");
- if ((rules & RULE_REJECT_METERED) != 0) {
- fout.write("REJECT_METERED");
- } else if ((rules & RULE_REJECT_ALL) != 0) {
- fout.write("REJECT_ALL");
- }
- fout.write("]");
- }
-
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 85041ad..f7c8662 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -577,7 +577,7 @@
public static final int KITKAT = 19;
/**
- * Android 4.4W: KitKat for watches, snacks on the run.
+ * June 2014: Android 4.4W. KitKat for watches, snacks on the run.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
@@ -595,7 +595,7 @@
public static final int L = 21;
/**
- * Lollipop. A flat one with beautiful shadows. But still tasty.
+ * November 2014: Lollipop. A flat one with beautiful shadows. But still tasty.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
@@ -626,12 +626,38 @@
public static final int LOLLIPOP = 21;
/**
- * Lollipop with an extra sugar coating on the outside!
+ * March 2015: Lollipop with an extra sugar coating on the outside!
*/
public static final int LOLLIPOP_MR1 = 22;
/**
- * M comes after L.
+ * M is for Marshmallow!
+ *
+ * <p>Applications targeting this or a later release will get these
+ * new changes in behavior:</p>
+ * <ul>
+ * <li> Runtime permissions. Dangerous permissions are no longer granted at
+ * install time, but must be requested by the application at runtime through
+ * {@link android.app.Activity#requestPermissions}.</li>
+ * <li> Bluetooth and Wi-Fi scanning now requires holding the location permission.</li>
+ * <li> {@link android.app.AlarmManager#setTimeZone AlarmManager.setTimeZone} will fail if
+ * the given timezone is non-Olson.</li>
+ * <li> Activity transitions will only return shared
+ * elements mapped in the returned view hierarchy back to the calling activity.</li>
+ * <li> {@link android.view.View} allows a number of behaviors that may break
+ * existing apps: Canvas throws an exception if restore() is called too many times,
+ * widgets may return a hint size when returning UNSPECIFIED measure specs, and it
+ * will respect the attributes {@link android.R.attr#foreground},
+ * {@link android.R.attr#foregroundGravity}, {@link android.R.attr#foregroundTint}, and
+ * {@link android.R.attr#foregroundTintMode}.</li>
+ * <li> {@link android.view.MotionEvent#getButtonState MotionEvent.getButtonState}
+ * will no longer report {@link android.view.MotionEvent#BUTTON_PRIMARY}
+ * and {@link android.view.MotionEvent#BUTTON_SECONDARY} as synonyms for
+ * {@link android.view.MotionEvent#BUTTON_STYLUS_PRIMARY} and
+ * {@link android.view.MotionEvent#BUTTON_STYLUS_SECONDARY}.</li>
+ * <li> {@link android.widget.ScrollView} now respects the layout param margins
+ * when measuring.</li>
+ * </ul>
*/
public static final int M = 23;
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 97b85e2..fdd34f5 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -471,7 +471,7 @@
* </tbody>
* </table>
*/
- public String getMemoryStat(String statName) {
+ public String getMemoryStat(String statName) {
switch(statName) {
case "summary.java-heap":
return Integer.toString(getSummaryJavaHeap());
@@ -1538,7 +1538,13 @@
/**
* Retrieves information about this processes memory usages. This information is broken down by
- * how much is in use by dalivk, the native heap, and everything else.
+ * how much is in use by dalvik, the native heap, and everything else.
+ *
+ * <p><b>Note:</b> this method directly retrieves memory information for the give process
+ * from low-level data available to it. It may not be able to retrieve information about
+ * some protected allocations, such as graphics. If you want to be sure you can see
+ * all information about allocations by the process, use instead
+ * {@link android.app.ActivityManager#getProcessMemoryInfo(int[])}.</p>
*/
public static native void getMemoryInfo(MemoryInfo memoryInfo);
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 64d6da5..f346fe7 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -276,8 +276,8 @@
}
/**
- * Return the primary external storage directory. This directory may not
- * currently be accessible if it has been mounted by the user on their
+ * Return the primary shared/external storage directory. This directory may
+ * not currently be accessible if it has been mounted by the user on their
* computer, has been removed from the device, or some other problem has
* happened. You can determine its current state with
* {@link #getExternalStorageState()}.
@@ -291,12 +291,15 @@
* filesystem on a computer.</em>
* <p>
* On devices with multiple users (as described by {@link UserManager}),
- * each user has their own isolated external storage. Applications only have
- * access to the external storage for the user they're running as.
+ * each user has their own isolated shared storage. Applications only have
+ * access to the shared storage for the user they're running as.
* <p>
- * In devices with multiple "external" storage directories, this directory
- * represents the "primary" external storage that the user will interact
+ * In devices with multiple shared/external storage directories, this
+ * directory represents the primary storage that the user will interact
* with. Access to secondary storage is available through
+ * {@link Context#getExternalFilesDirs(String)},
+ * {@link Context#getExternalCacheDirs()}, and
+ * {@link Context#getExternalMediaDirs()}.
* <p>
* Applications should not directly use this top-level directory, in order
* to avoid polluting the user's root namespace. Any files that are private
@@ -315,8 +318,9 @@
* <p>
* Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, if your
* application only needs to store internal data, consider using
- * {@link Context#getExternalFilesDir(String)} or
- * {@link Context#getExternalCacheDir()}, which require no permissions to
+ * {@link Context#getExternalFilesDir(String)},
+ * {@link Context#getExternalCacheDir()}, or
+ * {@link Context#getExternalMediaDirs()}, which require no permissions to
* read or write.
* <p>
* This path may change between platform versions, so applications should
@@ -325,8 +329,7 @@
* Here is an example of typical code to monitor the state of external
* storage:
* <p>
- * {@sample
- * development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* monitor_storage}
*
* @see #getExternalStorageState()
@@ -446,32 +449,32 @@
public static String DIRECTORY_DOCUMENTS = "Documents";
/**
- * Get a top-level public external storage directory for placing files of
- * a particular type. This is where the user will typically place and
- * manage their own files, so you should be careful about what you put here
- * to ensure you don't erase their files or get in the way of their own
+ * Get a top-level shared/external storage directory for placing files of a
+ * particular type. This is where the user will typically place and manage
+ * their own files, so you should be careful about what you put here to
+ * ensure you don't erase their files or get in the way of their own
* organization.
- *
- * <p>On devices with multiple users (as described by {@link UserManager}),
- * each user has their own isolated external storage. Applications only
- * have access to the external storage for the user they're running as.</p>
- *
- * <p>Here is an example of typical code to manipulate a picture on
- * the public external storage:</p>
- *
+ * <p>
+ * On devices with multiple users (as described by {@link UserManager}),
+ * each user has their own isolated shared storage. Applications only have
+ * access to the shared storage for the user they're running as.
+ * </p>
+ * <p>
+ * Here is an example of typical code to manipulate a picture on the public
+ * shared storage:
+ * </p>
* {@sample development/samples/ApiDemos/src/com/example/android/apis/content/ExternalStorage.java
* public_picture}
*
- * @param type The type of storage directory to return. Should be one of
- * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS},
- * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS},
- * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES},
- * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or
- * {@link #DIRECTORY_DCIM}. May not be null.
- *
- * @return Returns the File path for the directory. Note that this
- * directory may not yet exist, so you must make sure it exists before
- * using it such as with {@link File#mkdirs File.mkdirs()}.
+ * @param type The type of storage directory to return. Should be one of
+ * {@link #DIRECTORY_MUSIC}, {@link #DIRECTORY_PODCASTS},
+ * {@link #DIRECTORY_RINGTONES}, {@link #DIRECTORY_ALARMS},
+ * {@link #DIRECTORY_NOTIFICATIONS}, {@link #DIRECTORY_PICTURES},
+ * {@link #DIRECTORY_MOVIES}, {@link #DIRECTORY_DOWNLOADS}, or
+ * {@link #DIRECTORY_DCIM}. May not be null.
+ * @return Returns the File path for the directory. Note that this directory
+ * may not yet exist, so you must make sure it exists before using
+ * it such as with {@link File#mkdirs File.mkdirs()}.
*/
public static File getExternalStoragePublicDirectory(String type) {
throwIfUserRequired();
@@ -623,7 +626,7 @@
public static final String MEDIA_EJECTING = "ejecting";
/**
- * Returns the current state of the primary "external" storage device.
+ * Returns the current state of the primary shared/external storage media.
*
* @see #getExternalStorageDirectory()
* @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED},
@@ -646,8 +649,8 @@
}
/**
- * Returns the current state of the storage device that provides the given
- * path.
+ * Returns the current state of the shared/external storage media at the
+ * given path.
*
* @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED},
* {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING},
@@ -665,7 +668,8 @@
}
/**
- * Returns whether the primary "external" storage device is removable.
+ * Returns whether the primary shared/external storage media is physically
+ * removable.
*
* @return true if the storage device can be removed (such as an SD card),
* or false if the storage device is built in and cannot be
@@ -678,8 +682,8 @@
}
/**
- * Returns whether the storage device that provides the given path is
- * removable.
+ * Returns whether the shared/external storage media at the given path is
+ * physically removable.
*
* @return true if the storage device can be removed (such as an SD card),
* or false if the storage device is built in and cannot be
@@ -697,9 +701,15 @@
}
/**
- * Returns whether the primary "external" storage device is emulated. If
- * true, data stored on this device will be stored on a portion of the
- * internal storage system.
+ * Returns whether the primary shared/external storage media is emulated.
+ * <p>
+ * The contents of emulated storage devices are backed by a private user
+ * data partition, which means there is little benefit to apps storing data
+ * here instead of the private directories returned by
+ * {@link Context#getFilesDir()}, etc.
+ * <p>
+ * This returns true when emulated storage is backed by either internal
+ * storage or an adopted storage device.
*
* @see DevicePolicyManager#setStorageEncryption(android.content.ComponentName,
* boolean)
@@ -711,9 +721,16 @@
}
/**
- * Returns whether the storage device that provides the given path is
- * emulated. If true, data stored on this device will be stored on a portion
- * of the internal storage system.
+ * Returns whether the shared/external storage media at the given path is
+ * emulated.
+ * <p>
+ * The contents of emulated storage devices are backed by a private user
+ * data partition, which means there is little benefit to apps storing data
+ * here instead of the private directories returned by
+ * {@link Context#getFilesDir()}, etc.
+ * <p>
+ * This returns true when emulated storage is backed by either internal
+ * storage or an adopted storage device.
*
* @throws IllegalArgumentException if the path is not a valid storage
* device.
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 4c19ddd..3ade170 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -46,6 +46,7 @@
List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
boolean canAddMoreManagedProfiles(int userId);
UserInfo getProfileParent(int userHandle);
+ boolean isSameProfileGroup(int userId, int otherUserId);
UserInfo getUserInfo(int userHandle);
long getUserCreationTime(int userHandle);
boolean isRestricted();
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 796addc..95da438 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -270,13 +270,24 @@
* Returns true if this UserHandle refers to the owner user; false otherwise.
* @return true if this UserHandle refers to the owner user; false otherwise.
* @hide
- * TODO: find an alternative to this Api.
+ * @deprecated please use {@link #isSystem()} or check for
+ * {@link android.content.pm.UserInfo#isPrimary()}
+ * {@link android.content.pm.UserInfo#isAdmin()} based on your particular use case.
*/
@SystemApi
public boolean isOwner() {
return this.equals(OWNER);
}
+ /**
+ * @return true if this UserHandle refers to the system user; false otherwise.
+ * @hide
+ */
+ @SystemApi
+ public boolean isSystem() {
+ return this.equals(SYSTEM);
+ }
+
/** @hide */
public UserHandle(int h) {
mHandle = h;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d178d20..1c1575e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1093,6 +1093,22 @@
}
/**
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * @param userId one of the two user ids to check.
+ * @param otherUserId one of the two user ids to check.
+ * @return true if the two user ids are in the same profile group.
+ * @hide
+ */
+ public boolean isSameProfileGroup(int userId, int otherUserId) {
+ try {
+ return mService.isSameProfileGroup(userId, otherUserId);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not get user list", re);
+ return false;
+ }
+ }
+
+ /**
* Returns list of the profiles of userHandle including
* userHandle itself.
* Note that this returns only enabled.
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 979c828..2445bc2 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -383,6 +383,7 @@
final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+ filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
mContext.registerReceiver(this, filter);
} else {
mContext.unregisterReceiver(this);
@@ -395,13 +396,7 @@
if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) {
int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
- final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType)
- : (streamType == mStreamType);
- if (mSeekBar != null && streamMatch && streamValue != -1) {
- final boolean muted = mAudioManager.isStreamMute(mStreamType)
- || streamValue == 0;
- mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted);
- }
+ updateVolumeSlider(streamType, streamValue);
} else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
if (mNotificationOrRing) {
mRingerMode = mAudioManager.getRingerModeInternal();
@@ -409,10 +404,24 @@
if (mAffectedByRingerMode) {
updateSlider();
}
+ } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) {
+ int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ int streamVolume = mAudioManager.getStreamVolume(streamType);
+ updateVolumeSlider(streamType, streamVolume);
} else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) {
mZenMode = mNotificationManager.getZenMode();
updateSlider();
}
}
+
+ private void updateVolumeSlider(int streamType, int streamValue) {
+ final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType)
+ : (streamType == mStreamType);
+ if (mSeekBar != null && streamMatch && streamValue != -1) {
+ final boolean muted = mAudioManager.isStreamMute(mStreamType)
+ || streamValue == 0;
+ mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted);
+ }
+ }
}
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index e054a61..2c49d16 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -68,6 +68,7 @@
public static final int[] MINUTE_BUCKETS = generateMinuteBuckets();
private static final int SECONDS_MS = 1000;
private static final int MINUTES_MS = 60 * SECONDS_MS;
+ private static final int DAY_MINUTES = 24 * 60;
private static final int ZERO_VALUE_MS = 10 * SECONDS_MS;
private static final boolean DEFAULT_ALLOW_CALLS = true;
@@ -561,14 +562,6 @@
return tryParseLong(val, defValue);
}
- public ArraySet<String> getAutomaticRuleNames() {
- final ArraySet<String> rt = new ArraySet<String>();
- for (int i = 0; i < automaticRules.size(); i++) {
- rt.add(automaticRules.valueAt(i).name);
- }
- return rt;
- }
-
@Override
public int describeContents() {
return 0;
@@ -661,40 +654,65 @@
boolean shortVersion) {
final long now = System.currentTimeMillis();
final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
- return toTimeCondition(context, now + millis, minutesFromNow, now, userHandle,
- shortVersion);
+ return toTimeCondition(context, now + millis, minutesFromNow, userHandle, shortVersion);
}
- public static Condition toTimeCondition(Context context, long time, int minutes, long now,
+ public static Condition toTimeCondition(Context context, long time, int minutes,
int userHandle, boolean shortVersion) {
- final int num, summaryResId, line1ResId;
+ final int num;
+ String summary, line1, line2;
+ final CharSequence formattedTime = getFormattedTime(context, time, minutes, userHandle);
+ final Resources res = context.getResources();
if (minutes < 60) {
// display as minutes
num = minutes;
- summaryResId = shortVersion ? R.plurals.zen_mode_duration_minutes_summary_short
+ int summaryResId = shortVersion ? R.plurals.zen_mode_duration_minutes_summary_short
: R.plurals.zen_mode_duration_minutes_summary;
- line1ResId = shortVersion ? R.plurals.zen_mode_duration_minutes_short
+ summary = res.getQuantityString(summaryResId, num, num, formattedTime);
+ int line1ResId = shortVersion ? R.plurals.zen_mode_duration_minutes_short
: R.plurals.zen_mode_duration_minutes;
- } else {
+ line1 = res.getQuantityString(line1ResId, num, num, formattedTime);
+ line2 = res.getString(R.string.zen_mode_until, formattedTime);
+ } else if (minutes < DAY_MINUTES) {
// display as hours
num = Math.round(minutes / 60f);
- summaryResId = shortVersion ? R.plurals.zen_mode_duration_hours_summary_short
+ int summaryResId = shortVersion ? R.plurals.zen_mode_duration_hours_summary_short
: R.plurals.zen_mode_duration_hours_summary;
- line1ResId = shortVersion ? R.plurals.zen_mode_duration_hours_short
+ summary = res.getQuantityString(summaryResId, num, num, formattedTime);
+ int line1ResId = shortVersion ? R.plurals.zen_mode_duration_hours_short
: R.plurals.zen_mode_duration_hours;
+ line1 = res.getQuantityString(line1ResId, num, num, formattedTime);
+ line2 = res.getString(R.string.zen_mode_until, formattedTime);
+ } else {
+ // display as day/time
+ summary = line1 = line2 = res.getString(R.string.zen_mode_until, formattedTime);
}
- final String skeleton = DateFormat.is24HourFormat(context, userHandle) ? "Hm" : "hma";
- final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
- final CharSequence formattedTime = DateFormat.format(pattern, time);
- final Resources res = context.getResources();
- final String summary = res.getQuantityString(summaryResId, num, num, formattedTime);
- final String line1 = res.getQuantityString(line1ResId, num, num, formattedTime);
- final String line2 = res.getString(R.string.zen_mode_until, formattedTime);
final Uri id = toCountdownConditionId(time);
return new Condition(id, summary, line1, line2, 0, Condition.STATE_TRUE,
Condition.FLAG_RELEVANT_NOW);
}
+ public static Condition toNextAlarmCondition(Context context, long now, long alarm,
+ int userHandle) {
+ int minutes = Math.round((alarm-now) / (float) MINUTES_MS);
+ final CharSequence formattedTime = getFormattedTime(context, alarm, minutes, userHandle);
+ final Resources res = context.getResources();
+ final String line1 = res.getString(R.string.zen_mode_alarm, formattedTime);
+ final Uri id = toCountdownConditionId(alarm);
+ return new Condition(id, "", line1, "", 0, Condition.STATE_TRUE,
+ Condition.FLAG_RELEVANT_NOW);
+ }
+
+ private static CharSequence getFormattedTime(Context context, long time, int minutes,
+ int userHandle) {
+ String skeleton = DateFormat.is24HourFormat(context, userHandle) ? "Hm" : "hma";
+ if (minutes > DAY_MINUTES) {
+ skeleton = "EEE " + (DateFormat.is24HourFormat(context, userHandle) ? "Hm" : "hma");
+ }
+ final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
+ return DateFormat.format(pattern, time);
+ }
+
// ==== Built-in system conditions ====
public static final String SYSTEM_AUTHORITY = "android";
@@ -900,11 +918,6 @@
return UUID.randomUUID().toString().replace("-", "");
}
- public static String getConditionLine1(Context context, ZenModeConfig config,
- int userHandle, boolean shortVersion) {
- return getConditionLine(context, config, userHandle, true /*useLine1*/, shortVersion);
- }
-
public static String getConditionSummary(Context context, ZenModeConfig config,
int userHandle, boolean shortVersion) {
return getConditionLine(context, config, userHandle, false /*useLine1*/, shortVersion);
@@ -923,8 +936,8 @@
if (time > 0) {
final long now = System.currentTimeMillis();
final long span = time - now;
- c = toTimeCondition(context,
- time, Math.round(span / (float) MINUTES_MS), now, userHandle, shortVersion);
+ c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS),
+ userHandle, shortVersion);
}
final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary;
return TextUtils.isEmpty(rt) ? "" : rt;
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index cc4598d..bae51d3 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -766,6 +766,15 @@
}
/**
+ * Sets the current pointer shape.
+ * @param pointerShape the id of the pointer icon.
+ * @hide
+ */
+ public void setPointerShape(int pointerShape) {
+ InputManager.getInstance().setPointerIconShape(pointerShape);
+ }
+
+ /**
* Provides information about the range of values for a particular {@link MotionEvent} axis.
*
* @see InputDevice#getMotionRange(int)
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index cf35ce5..88e9a95 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -48,6 +48,12 @@
/** Style constant: Null icon. It has no bitmap. */
public static final int STYLE_NULL = 0;
+ /** Style constant: no icons are specified. If all views uses this, then falls back
+ * to the default style, but this is helpful to distinguish a view explicitly want
+ * to have the default icon.
+ */
+ public static final int STYLE_NOT_SPECIFIED = 1;
+
/** Style constant: Arrow icon. (Default mouse pointer) */
public static final int STYLE_ARROW = 1000;
@@ -60,12 +66,74 @@
/** {@hide} Style constant: Spot anchor icon for touchpads. */
public static final int STYLE_SPOT_ANCHOR = 2002;
+ // Style constants for additional predefined icons for mice.
+ /** Style constant: context-menu. */
+ public static final int STYLE_CONTEXT_MENU = 1001;
+
+ /** Style constant: hand. */
+ public static final int STYLE_HAND = 1002;
+
+ /** Style constant: help. */
+ public static final int STYLE_HELP = 1003;
+
+ /** Style constant: wait. */
+ public static final int STYLE_WAIT = 1004;
+
+ /** Style constant: cell. */
+ public static final int STYLE_CELL = 1006;
+
+ /** Style constant: crosshair. */
+ public static final int STYLE_CROSSHAIR = 1007;
+
+ /** Style constant: text. */
+ public static final int STYLE_TEXT = 1008;
+
+ /** Style constant: vertical-text. */
+ public static final int STYLE_VERTICAL_TEXT = 1009;
+
+ /** Style constant: alias (indicating an alias of/shortcut to something is
+ * to be created. */
+ public static final int STYLE_ALIAS = 1010;
+
+ /** Style constant: copy. */
+ public static final int STYLE_COPY = 1011;
+
+ /** Style constant: no-drop. */
+ public static final int STYLE_NO_DROP = 1012;
+
+ /** Style constant: all-scroll. */
+ public static final int STYLE_ALL_SCROLL = 1013;
+
+ /** Style constant: horizontal double arrow mainly for resizing. */
+ public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014;
+
+ /** Style constant: vertical double arrow mainly for resizing. */
+ public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015;
+
+ /** Style constant: diagonal double arrow -- top-right to bottom-left. */
+ public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016;
+
+ /** Style constant: diagonal double arrow -- top-left to bottom-right. */
+ public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017;
+
+ /** Style constant: zoom-in. */
+ public static final int STYLE_ZOOM_IN = 1018;
+
+ /** Style constant: zoom-out. */
+ public static final int STYLE_ZOOM_OUT = 1019;
+
+ /** Style constant: grab. */
+ public static final int STYLE_GRAB = 1020;
+
+ /** Style constant: grabbing. */
+ public static final int STYLE_GRABBING = 1021;
+
// OEM private styles should be defined starting at this range to avoid
// conflicts with any system styles that may be defined in the future.
private static final int STYLE_OEM_FIRST = 10000;
- // The default pointer icon.
- private static final int STYLE_DEFAULT = STYLE_ARROW;
+ /** {@hide} The default pointer icon. */
+ public static final int STYLE_DEFAULT = STYLE_ARROW;
private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);
@@ -434,6 +502,49 @@
return com.android.internal.R.styleable.Pointer_pointerIconSpotTouch;
case STYLE_SPOT_ANCHOR:
return com.android.internal.R.styleable.Pointer_pointerIconSpotAnchor;
+ case STYLE_HAND:
+ return com.android.internal.R.styleable.Pointer_pointerIconHand;
+ case STYLE_CONTEXT_MENU:
+ return com.android.internal.R.styleable.Pointer_pointerIconContextMenu;
+ case STYLE_HELP:
+ return com.android.internal.R.styleable.Pointer_pointerIconHelp;
+ case STYLE_WAIT:
+ // falls back to the default icon because no animation support.
+ return com.android.internal.R.styleable.Pointer_pointerIconArrow;
+ case STYLE_CELL:
+ return com.android.internal.R.styleable.Pointer_pointerIconCell;
+ case STYLE_CROSSHAIR:
+ return com.android.internal.R.styleable.Pointer_pointerIconCrosshair;
+ case STYLE_TEXT:
+ return com.android.internal.R.styleable.Pointer_pointerIconText;
+ case STYLE_VERTICAL_TEXT:
+ return com.android.internal.R.styleable.Pointer_pointerIconVerticalText;
+ case STYLE_ALIAS:
+ return com.android.internal.R.styleable.Pointer_pointerIconAlias;
+ case STYLE_COPY:
+ return com.android.internal.R.styleable.Pointer_pointerIconCopy;
+ case STYLE_ALL_SCROLL:
+ return com.android.internal.R.styleable.Pointer_pointerIconAllScroll;
+ case STYLE_NO_DROP:
+ return com.android.internal.R.styleable.Pointer_pointerIconNodrop;
+ case STYLE_HORIZONTAL_DOUBLE_ARROW:
+ return com.android.internal.R.styleable.Pointer_pointerIconHorizontalDoubleArrow;
+ case STYLE_VERTICAL_DOUBLE_ARROW:
+ return com.android.internal.R.styleable.Pointer_pointerIconVerticalDoubleArrow;
+ case STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW:
+ return com.android.internal.R.styleable.
+ Pointer_pointerIconTopRightDiagonalDoubleArrow;
+ case STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW:
+ return com.android.internal.R.styleable.
+ Pointer_pointerIconTopLeftDiagonalDoubleArrow;
+ case STYLE_ZOOM_IN:
+ return com.android.internal.R.styleable.Pointer_pointerIconZoomIn;
+ case STYLE_ZOOM_OUT:
+ return com.android.internal.R.styleable.Pointer_pointerIconZoomOut;
+ case STYLE_GRAB:
+ return com.android.internal.R.styleable.Pointer_pointerIconGrab;
+ case STYLE_GRABBING:
+ return com.android.internal.R.styleable.Pointer_pointerIconGrabbing;
default:
return 0;
}
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 2a3756d..7747580 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -336,9 +336,6 @@
return mUnscaledDuration;
}
- /**
- * @hide
- */
@Override
public long getTotalDuration() {
return mUnscaledDuration + mUnscaledStartDelay;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2c7a436..4bc2112 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2408,7 +2408,13 @@
* 1 PFLAG3_APPLYING_INSETS
* 1 PFLAG3_FITTING_SYSTEM_WINDOWS
* 1 PFLAG3_NESTED_SCROLLING_ENABLED
- * 1 PFLAG3_ASSIST_BLOCKED
+ * 1 PFLAG3_SCROLL_INDICATOR_TOP
+ * 1 PFLAG3_SCROLL_INDICATOR_BOTTOM
+ * 1 PFLAG3_SCROLL_INDICATOR_LEFT
+ * 1 PFLAG3_SCROLL_INDICATOR_RIGHT
+ * 1 PFLAG3_SCROLL_INDICATOR_START
+ * 1 PFLAG3_SCROLL_INDICATOR_END
+ * 1 PFLAG3_ASSIST_BLOCKED
* |-------|-------|-------|-------|
*/
@@ -2602,7 +2608,7 @@
* <p>Indicates that we are allowing {@link ViewStructure} to traverse
* into this view.<p>
*/
- static final int PFLAG3_ASSIST_BLOCKED = 0x100;
+ static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
/**
* Always allow a user to over-scroll this view, provided it is a
@@ -20989,6 +20995,11 @@
}
}
+ /** @hide */
+ public int getPointerShape(MotionEvent event, float x, float y) {
+ return PointerIcon.STYLE_NOT_SPECIFIED;
+ }
+
//
// Properties
//
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 475ce2f..7c7ad91 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1715,6 +1715,36 @@
return false;
}
+ /** @hide */
+ @Override
+ public int getPointerShape(MotionEvent event, float x, float y) {
+ // Check what the child under the pointer says about the pointer.
+ final int childrenCount = mChildrenCount;
+ if (childrenCount != 0) {
+ final ArrayList<View> preorderedList = buildOrderedChildList();
+ final boolean customOrder = preorderedList == null
+ && isChildrenDrawingOrderEnabled();
+ final View[] children = mChildren;
+ for (int i = childrenCount - 1; i >= 0; i--) {
+ final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
+ final View child = (preorderedList == null)
+ ? children[childIndex] : preorderedList.get(childIndex);
+ PointF point = getLocalPoint();
+ if (isTransformedTouchPointInView(x, y, child, point)) {
+ final int pointerShape = child.getPointerShape(event, point.x, point.y);
+ if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
+ return pointerShape;
+ }
+ break;
+ }
+ }
+ }
+
+ // The pointer is not a child or the child has no preferences, returning the default
+ // implementation.
+ return super.getPointerShape(event, x, y);
+ }
+
/**
* {@inheritDoc}
*/
@@ -4606,7 +4636,6 @@
}
private void removeViewInternal(int index, View view) {
-
if (mTransition != null) {
mTransition.removeChild(this, view);
}
@@ -4699,12 +4728,17 @@
}
private void removeViewsInternal(int start, int count) {
+ final int end = start + count;
+
+ if (start < 0 || count < 0 || end > mChildrenCount) {
+ throw new IndexOutOfBoundsException();
+ }
+
final View focused = mFocused;
final boolean detach = mAttachInfo != null;
boolean clearChildFocus = false;
final View[] children = mChildren;
- final int end = start + count;
for (int i = start; i < end; i++) {
final View view = children[i];
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3d10289..13b6a42 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -37,6 +37,7 @@
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.input.InputManager;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Build;
@@ -324,6 +325,8 @@
private long mFpsPrevTime = -1;
private int mFpsNumFrames;
+ private int mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
+
/**
* see {@link #playSoundEffect(int)}
*/
@@ -4168,6 +4171,30 @@
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
+ if (event.getPointerCount() == 1
+ && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+ if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
+ || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
+ // Other apps or the window manager may change the icon shape outside of
+ // this app, therefore the icon shape has to be reset on enter/exit event.
+ mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
+ }
+
+ final float x = event.getX();
+ final float y = event.getY();
+ if (x >= 0 && x < mView.getWidth() && y >= 0 && y < mView.getHeight()) {
+ int pointerShape = mView.getPointerShape(event, x, y);
+ if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
+ pointerShape = PointerIcon.STYLE_DEFAULT;
+ }
+
+ if (mPointerIconShape != pointerShape) {
+ mPointerIconShape = pointerShape;
+ event.getDevice().setPointerShape(pointerShape);
+ }
+ }
+ }
+
mAttachInfo.mUnbufferedDispatchRequested = false;
boolean handled = mView.dispatchPointerEvent(event);
if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 13544851..d9ec866 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -666,7 +666,7 @@
void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
CharSequence curTitle = wp.getTitle();
if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
- wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
if (wp.token == null) {
View decor = peekDecorView();
if (decor != null) {
@@ -674,24 +674,38 @@
}
}
if (curTitle == null || curTitle.length() == 0) {
- String title;
+ final StringBuilder title = new StringBuilder(32);
if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
- title="Media";
+ title.append("Media");
} else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) {
- title="MediaOvr";
+ title.append("MediaOvr");
} else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- title="Panel";
+ title.append("Panel");
} else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) {
- title="SubPanel";
+ title.append("SubPanel");
} else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL) {
- title="AboveSubPanel";
+ title.append("AboveSubPanel");
} else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) {
- title="AtchDlg";
+ title.append("AtchDlg");
} else {
- title=Integer.toString(wp.type);
+ title.append(wp.type);
}
if (mAppName != null) {
- title += ":" + mAppName;
+ title.append(":").append(mAppName);
+ }
+ wp.setTitle(title);
+ }
+ } else if (wp.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW &&
+ wp.type <= WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
+ // We don't set the app token to this system window because the life cycles should be
+ // independent. If an app creates a system window and then the app goes to the stopped
+ // state, the system window should not be affected (can still show and receive input
+ // events).
+ if (curTitle == null || curTitle.length() == 0) {
+ final StringBuilder title = new StringBuilder(32);
+ title.append("Sys").append(wp.type);
+ if (mAppName != null) {
+ title.append(":").append(mAppName);
}
wp.setTitle(title);
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index aaf6052..d20c729 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -22,6 +22,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
@@ -38,7 +39,7 @@
* instance of it is created by the window manager when it starts up, and allows
* customization of window layering, special window types, key dispatching, and
* layout.
- *
+ *
* <p>Because this provides deep interaction with the system window manager,
* specific methods on this interface can be called from a variety of contexts
* with various restrictions on what they can do. These are encoded through
@@ -47,9 +48,9 @@
* is attached to a method, then it is not called with any locks and may be
* called from the main window manager thread or another thread calling into
* the window manager.
- *
+ *
* <p>The current suffixes are:
- *
+ *
* <dl>
* <dt> Ti <dd> Called from the input thread. This is the thread that
* collects pending input events and dispatches them to the appropriate window.
@@ -71,7 +72,7 @@
* acquired by the window manager while it holds the window lock, so this is
* even more restrictive than <var>Lw</var>.
* </dl>
- *
+ *
* @hide
*/
public interface WindowManagerPolicy {
@@ -138,7 +139,7 @@
* Perform standard frame computation. The result can be obtained with
* getFrame() if so desired. Must be called with the window manager
* lock held.
- *
+ *
* @param parentFrame The frame of the parent container this window
* is in, used for computing its basic position.
* @param displayFrame The frame of the overall display in which this
@@ -168,18 +169,18 @@
/**
* Retrieve the current frame of the window that has been assigned by
* the window manager. Must be called with the window manager lock held.
- *
+ *
* @return Rect The rectangle holding the window frame.
*/
public Rect getFrameLw();
/**
- * Retrieve the current frame of the window that is actually shown.
+ * Retrieve the current position of the window that is actually shown.
* Must be called with the window manager lock held.
- *
- * @return Rect The rectangle holding the shown window frame.
+ *
+ * @return Point The point holding the shown window position.
*/
- public RectF getShownFrameLw();
+ public Point getShownPositionLw();
/**
* Retrieve the frame of the display that this window was last
@@ -206,7 +207,7 @@
* account for screen decorations such as a status bar or soft
* keyboard. Must be called with the
* window manager lock held.
- *
+ *
* @return Rect The rectangle holding the content frame.
*/
public Rect getContentFrameLw();
@@ -218,7 +219,7 @@
* content frame to account for transient UI elements blocking it
* such as an input method's candidates UI. Must be called with the
* window manager lock held.
- *
+ *
* @return Rect The rectangle holding the visible frame.
*/
public Rect getVisibleFrameLw();
@@ -229,12 +230,12 @@
* layout of other windows.
*/
public boolean getGivenInsetsPendingLw();
-
+
/**
* Retrieve the insets given by this window's client for the content
* area of windows behind it. Must be called with the
* window manager lock held.
- *
+ *
* @return Rect The left, top, right, and bottom insets, relative
* to the window's frame, of the actual contents.
*/
@@ -244,7 +245,7 @@
* Retrieve the insets given by this window's client for the visible
* area of windows behind it. Must be called with the
* window manager lock held.
- *
+ *
* @return Rect The left, top, right, and bottom insets, relative
* to the window's frame, of the actual visible area.
*/
@@ -252,7 +253,7 @@
/**
* Retrieve the current LayoutParams of the window.
- *
+ *
* @return WindowManager.LayoutParams The window's internal LayoutParams
* instance.
*/
@@ -298,12 +299,12 @@
public boolean isVoiceInteraction();
/**
- * Return true if, at any point, the application token associated with
- * this window has actually displayed any windows. This is most useful
- * with the "starting up" window to determine if any windows were
- * displayed when it is closed.
- *
- * @return Returns true if one or more windows have been displayed,
+ * Return true if, at any point, the application token associated with
+ * this window has actually displayed any windows. This is most useful
+ * with the "starting up" window to determine if any windows were
+ * displayed when it is closed.
+ *
+ * @return Returns true if one or more windows have been displayed,
* else false.
*/
public boolean hasAppShownWindows();
@@ -314,17 +315,17 @@
* that will remove the surface.
*/
boolean isVisibleLw();
-
+
/**
* Like {@link #isVisibleLw}, but also counts a window that is currently
* "hidden" behind the keyguard as visible. This allows us to apply
* things like window flags that impact the keyguard.
*/
boolean isVisibleOrBehindKeyguardLw();
-
+
/**
- * Is this window currently visible to the user on-screen? It is
- * displayed either if it is visible or it is currently running an
+ * Is this window currently visible to the user on-screen? It is
+ * displayed either if it is visible or it is currently running an
* animation before no longer being visible. Must be called with the
* window manager lock held.
*/
@@ -350,7 +351,7 @@
boolean isDrawnLw();
/**
- * Returns true if this window has been shown on screen at some time in
+ * Returns true if this window has been shown on screen at some time in
* the past. Must be called with the window manager lock held.
*/
public boolean hasDrawnLw();
@@ -362,7 +363,7 @@
* Returns true if {@link #showLw} was last called for the window.
*/
public boolean hideLw(boolean doAnimation);
-
+
/**
* Can be called to undo the effect of {@link #hideLw}, allowing a
* window to be shown as long as the window manager and client would
@@ -479,7 +480,7 @@
// NOTE: screen off reasons are in order of significance, with more
// important ones lower than less important ones.
-
+
/** Screen turned off because of a device admin */
public final int OFF_BECAUSE_OF_ADMIN = 1;
/** Screen turned off because of power button */
@@ -498,10 +499,10 @@
/** When not otherwise specified by the activity's screenOrientation, rotation is set by
* the user. */
public final int USER_ROTATION_LOCKED = 1;
-
+
/**
* Perform initialization of the policy.
- *
+ *
* @param context The system context we are running in.
*/
public void init(Context context, IWindowManager windowManager,
@@ -526,11 +527,11 @@
/**
* Check permissions when adding a window.
- *
+ *
* @param attrs The window's LayoutParams.
* @param outAppOp First element will be filled with the app op corresponding to
* this window, or OP_NONE.
- *
+ *
* @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
* else an error code, usually
* {@link WindowManagerGlobal#ADD_PERMISSION_DENIED}, to abort the add.
@@ -551,21 +552,21 @@
* Sanitize the layout parameters coming from a client. Allows the policy
* to do things like ensure that windows of a specific type can't take
* input focus.
- *
+ *
* @param attrs The window layout parameters to be modified. These values
* are modified in-place.
*/
public void adjustWindowParamsLw(WindowManager.LayoutParams attrs);
-
+
/**
* After the window manager has computed the current configuration based
* on its knowledge of the display and input devices, it gives the policy
* a chance to adjust the information contained in it. If you want to
* leave it as-is, simply do nothing.
- *
+ *
* <p>This method may be called by any thread in the window manager, but
* no internal locks in the window manager will be held.
- *
+ *
* @param config The Configuration being computed, for you to change as
* desired.
* @param keyboardPresence Flags that indicate whether internal or external
@@ -575,13 +576,13 @@
*/
public void adjustConfigurationLw(Configuration config, int keyboardPresence,
int navigationPresence);
-
+
/**
* Assign a window type to a layer. Allows you to control how different
* kinds of windows are ordered on-screen.
- *
+ *
* @param type The type of window being assigned.
- *
+ *
* @return int An arbitrary integer used to order windows, with lower
* numbers below higher ones.
*/
@@ -591,9 +592,9 @@
* Return how to Z-order sub-windows in relation to the window they are
* attached to. Return positive to have them ordered in front, negative for
* behind.
- *
+ *
* @param type The sub-window type code.
- *
+ *
* @return int Layer in relation to the attached window, where positive is
* above and negative is below.
*/
@@ -669,19 +670,19 @@
* manager (using the normal window manager APIs) that will be shown until
* the application displays its own window. This is called without the
* window manager locked so that you can call back into it.
- *
+ *
* @param appToken Token of the application being started.
- * @param packageName The name of the application package being started.
+ * @param packageName The name of the application package being started.
* @param theme Resource defining the application's overall visual theme.
* @param nonLocalizedLabel The default title label of the application if
* no data is found in the resource.
* @param labelRes The resource ID the application would like to use as its name.
* @param icon The resource ID the application would like to use as its icon.
* @param windowFlags Window layout flags.
- *
+ *
* @return Optionally you can return the View that was used to create the
* window, for easy removal in removeStartingWindow.
- *
+ *
* @see #removeStartingWindow
*/
public View addStartingWindow(IBinder appToken, String packageName,
@@ -694,15 +695,15 @@
* that application. You should at this point remove the window from the
* window manager. This is called without the window manager locked so
* that you can call back into it.
- *
+ *
* <p>Note: due to the nature of these functions not being called with the
* window manager locked, you must be prepared for this function to be
* called multiple times and/or an initial time with a null View window
* even if you previously returned one.
- *
+ *
* @param appToken Token of the application that has started.
* @param window Window View that was returned by createStartingWindow.
- *
+ *
* @see #addStartingWindow
*/
public void removeStartingWindow(IBinder appToken, View window);
@@ -711,10 +712,10 @@
* Prepare for a window being added to the window manager. You can throw an
* exception here to prevent the window being added, or do whatever setup
* you need to keep track of the window.
- *
+ *
* @param win The window being added.
- * @param attrs The window's LayoutParams.
- *
+ * @param attrs The window's LayoutParams.
+ *
* @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed, else an
* error code to abort the add.
*/
@@ -724,7 +725,7 @@
/**
* Called when a window is being removed from a window manager. Must not
* throw an exception -- clean up as much as possible.
- *
+ *
* @param win The window being removed.
*/
public void removeWindowLw(WindowState win);
@@ -733,12 +734,12 @@
* Control the animation to run when a window's state changes. Return a
* non-0 number to force the animation to a specific resource ID, or 0
* to use the default animation.
- *
+ *
* @param win The window that is changing.
* @param transit What is happening to the window: {@link #TRANSIT_ENTER},
* {@link #TRANSIT_EXIT}, {@link #TRANSIT_SHOW}, or
* {@link #TRANSIT_HIDE}.
- *
+ *
* @return Resource ID of the actual animation to use, or 0 for none.
*/
public int selectAnimationLw(WindowState win, int transit);
@@ -747,8 +748,8 @@
* Determine the animation to run for a rotation transition based on the
* top fullscreen windows {@link WindowManager.LayoutParams#rotationAnimation}
* and whether it is currently fullscreen and frontmost.
- *
- * @param anim The exiting animation resource id is stored in anim[0], the
+ *
+ * @param anim The exiting animation resource id is stored in anim[0], the
* entering animation resource id is stored in anim[1].
*/
public void selectRotationAnimationLw(int anim[]);
@@ -814,7 +815,7 @@
* <p>Allows you to define
* behavior for keys that can not be overridden by applications.
* This method is called from the input thread, with no locks held.
- *
+ *
* @param win The window that currently has focus. This is where the key
* event will normally go.
* @param event The key event.
@@ -832,7 +833,7 @@
*
* <p>Allows you to define default global behavior for keys that were not handled
* by applications. This method is called from the input thread, with no locks held.
- *
+ *
* @param win The window that currently has focus. This is where the key
* event will normally go.
* @param event The key event.
@@ -844,7 +845,7 @@
/**
* Called when layout of the windows is about to start.
- *
+ *
* @param isDefaultDisplay true if window is on {@link Display#DEFAULT_DISPLAY}.
* @param displayWidth The current full width of the screen.
* @param displayHeight The current full height of the screen.
@@ -872,7 +873,7 @@
* Called for each window attached to the window manager as layout is
* proceeding. The implementation of this function must take care of
* setting the window's frame, either here or in finishLayout().
- *
+ *
* @param win The window being positioned.
* @param attached For sub-windows, the window it is attached to; this
* window will already have had layoutWindow() called on it
@@ -880,7 +881,7 @@
*/
public void layoutWindowLw(WindowState win, WindowState attached);
-
+
/**
* Return the insets for the areas covered by system windows. These values
* are computed on the most recent layout, so they are not guaranteed to
@@ -912,10 +913,10 @@
static final int FINISH_LAYOUT_REDO_WALLPAPER = 0x0004;
/** Need to recompute animations */
static final int FINISH_LAYOUT_REDO_ANIM = 0x0008;
-
+
/**
* Called following layout of all windows before each window has policy applied.
- *
+ *
* @param displayWidth The current full width of the screen.
* @param displayHeight The current full height of the screen.
*/
@@ -936,7 +937,7 @@
* to each window. If in this function you do
* something that may have modified the animation state of another window,
* be sure to return non-zero in order to perform another pass through layout.
- *
+ *
* @return Return any bit set of {@link #FINISH_LAYOUT_REDO_LAYOUT},
* {@link #FINISH_LAYOUT_REDO_CONFIG}, {@link #FINISH_LAYOUT_REDO_WALLPAPER},
* or {@link #FINISH_LAYOUT_REDO_ANIM}.
@@ -1150,7 +1151,7 @@
* the system should go into safe mode.
*/
public void setSafeMode(boolean safeMode);
-
+
/**
* Called when the system is mostly done booting.
*/
@@ -1184,14 +1185,14 @@
* this point the display is active.
*/
public void enableScreenAfterBoot();
-
+
public void setCurrentOrientationLw(@ActivityInfo.ScreenOrientation int newOrientation);
-
+
/**
* Call from application to perform haptic feedback on its window.
*/
public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always);
-
+
/**
* Called when we have started keeping the screen on because a window
* requesting this has become visible.
@@ -1205,21 +1206,21 @@
public void keepScreenOnStoppedLw();
/**
- * Gets the current user rotation mode.
+ * Gets the current user rotation mode.
*
* @return The rotation mode.
*
* @see WindowManagerPolicy#USER_ROTATION_LOCKED
- * @see WindowManagerPolicy#USER_ROTATION_FREE
+ * @see WindowManagerPolicy#USER_ROTATION_FREE
*/
@UserRotationMode
public int getUserRotationMode();
/**
- * Inform the policy that the user has chosen a preferred orientation ("rotation lock").
+ * Inform the policy that the user has chosen a preferred orientation ("rotation lock").
*
* @param mode One of {@link WindowManagerPolicy#USER_ROTATION_LOCKED} or
- * {@link WindowManagerPolicy#USER_ROTATION_FREE}.
+ * {@link WindowManagerPolicy#USER_ROTATION_FREE}.
* @param rotation One of {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
* {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
*/
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 11d0f4a..4ac547a 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -429,7 +429,8 @@
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
- + " mSettingsActivityName=" + mSettingsActivityName);
+ + " mSettingsActivityName=" + mSettingsActivityName
+ + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod);
pw.println(prefix + "mIsDefaultResId=0x"
+ Integer.toHexString(mIsDefaultResId));
pw.println(prefix + "Service:");
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0712052..1aeb9c93 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -116,6 +116,7 @@
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.PointerIcon;
import android.view.View;
import android.view.ViewParent;
import android.view.ViewStructure;
@@ -5905,6 +5906,17 @@
return mLayout != null ? mLayout.getHeight() : 0;
}
+ /**
+ * @hide
+ */
+ @Override
+ public int getPointerShape(MotionEvent event, float x, float y) {
+ if (isTextSelectable() || isTextEditable()) {
+ return PointerIcon.STYLE_TEXT;
+ }
+ return super.getPointerShape(event, x, y);
+ }
+
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
// Note: If the IME is in fullscreen mode and IMS#mExtractEditText is in text action mode,
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 255e23a..f462a47 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1017,7 +1017,15 @@
final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
.setInterpolator(mInterpolator);
mServiceTargetScale[i] = rs;
- rs.startAnimation();
+ }
+
+ // Start the animations in a separate loop.
+ // The process of starting animations will result in
+ // binding views to set up initial values, and we must
+ // have ALL of the new RowScale objects created above before
+ // we get started.
+ for (int i = oldRCount; i < rcount; i++) {
+ mServiceTargetScale[i].startAnimation();
}
}
@@ -1097,17 +1105,19 @@
for (int i = 0; i < mColumnCount; i++) {
final View v = mChooserListAdapter.createView(row);
+ final int column = i;
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- startSelected(holder.itemIndex, false, true);
+ startSelected(holder.itemIndices[column], false, true);
}
});
v.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
showAppDetails(
- mChooserListAdapter.resolveInfoForPosition(holder.itemIndex, true));
+ mChooserListAdapter.resolveInfoForPosition(
+ holder.itemIndices[column], true));
return true;
}
});
@@ -1165,8 +1175,8 @@
final View v = holder.cells[i];
if (start + i <= end) {
v.setVisibility(View.VISIBLE);
- holder.itemIndex = start + i;
- mChooserListAdapter.bindView(holder.itemIndex, v);
+ holder.itemIndices[i] = start + i;
+ mChooserListAdapter.bindView(holder.itemIndices[i], v);
} else {
v.setVisibility(View.GONE);
}
@@ -1197,11 +1207,12 @@
final View[] cells;
final ViewGroup row;
int measuredRowHeight;
- int itemIndex;
+ int[] itemIndices;
public RowViewHolder(ViewGroup row, int cellCount) {
this.row = row;
this.cells = new View[cellCount];
+ this.itemIndices = new int[cellCount];
}
public void measure() {
@@ -1389,7 +1400,7 @@
final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView);
int height = ((RowViewHolder) (v.getTag())).measuredRowHeight;
- offset += (int) (height * mChooserRowAdapter.getRowScale(pos) * chooserTargetRows);
+ offset += (int) (height * mChooserRowAdapter.getRowScale(pos));
if (vt >= 0) {
mCachedViewType = vt;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index aaa89df..9a5cde6 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -70,6 +70,7 @@
private static final String TAG = "Zygote";
private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
+ private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container";
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
@@ -503,7 +504,6 @@
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
- OsConstants.CAP_BLOCK_SUSPEND,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
@@ -515,6 +515,10 @@
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
+ /* Containers run without this capability, so avoid setting it in that case */
+ if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
+ capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
+ }
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index ab372d3..75ad916a 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3705,13 +3705,14 @@
}
/**
- * Returns true if the Window is free floating and has a shadow. Note that non overlapping
- * windows do not have a shadow since it could not be seen anyways (a small screen / tablet
+ * Returns true if the Window is free floating and has a shadow (although at some times
+ * it might not be displaying it, e.g. during a resize). Note that non overlapping windows
+ * do not have a shadow since it could not be seen anyways (a small screen / tablet
* "tiles" the windows side by side but does not overlap them).
* @return Returns true when the window has a shadow created by the non client decor.
**/
private boolean windowHasShadow() {
- return windowHasNonClientDecor() && getElevation() > 0;
+ return windowHasNonClientDecor() && nonClientDecorHasShadow(mWindow.mWorkspaceId);
}
void setWindow(PhoneWindow phoneWindow) {
@@ -5417,7 +5418,7 @@
* @param workspaceId The Id of the workspace which contains this window.
* @Return Returns true if the window should show a shadow.
**/
- private boolean nonClientDecorHasShadow(int workspaceId) {
+ private static boolean nonClientDecorHasShadow(int workspaceId) {
return workspaceId == FREEFORM_WORKSPACE_STACK_ID;
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 614e82f..c94bc64 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/stat.h>
#include <private/android_filesystem_config.h> // for AID_SYSTEM
@@ -171,11 +172,32 @@
exit(1);
}
- execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
- AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
- AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
- ALOGE("failed to execl for idmap: %s", strerror(errno));
- exit(1); // should never get here
+ // Generic idmap parameters
+ const char* argv[7];
+ int argc = 0;
+ struct stat st;
+
+ memset(argv, NULL, sizeof(argv));
+ argv[argc++] = AssetManager::IDMAP_BIN;
+ argv[argc++] = "--scan";
+ argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
+ argv[argc++] = AssetManager::TARGET_APK_PATH;
+ argv[argc++] = AssetManager::IDMAP_DIR;
+
+ // Directories to scan for overlays
+ // /vendor/overlay
+ if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
+ argv[argc++] = AssetManager::OVERLAY_DIR;
+ }
+
+ // Finally, invoke idmap (if any overlay directory exists)
+ if (argc > 5) {
+ execv(AssetManager::IDMAP_BIN, (char* const*)argv);
+ ALOGE("failed to execl for idmap: %s", strerror(errno));
+ exit(1); // should never get here
+ } else {
+ exit(0);
+ }
}
break;
default: // parent
diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h
index 3bfd645..86f288d 100644
--- a/core/jni/android_view_PointerIcon.h
+++ b/core/jni/android_view_PointerIcon.h
@@ -31,6 +31,27 @@
POINTER_ICON_STYLE_CUSTOM = -1,
POINTER_ICON_STYLE_NULL = 0,
POINTER_ICON_STYLE_ARROW = 1000,
+ POINTER_ICON_STYLE_CONTEXT_MENU = 1001,
+ POINTER_ICON_STYLE_HAND = 1002,
+ POINTER_ICON_STYLE_HELP = 1003,
+ POINTER_ICON_STYLE_WAIT = 1004,
+ POINTER_ICON_STYLE_CELL = 1006,
+ POINTER_ICON_STYLE_CROSSHAIR = 1007,
+ POINTER_ICON_STYLE_TEXT = 1008,
+ POINTER_ICON_STYLE_VERTICAL_TEXT = 1009,
+ POINTER_ICON_STYLE_ALIAS = 1010,
+ POINTER_ICON_STYLE_COPY = 1011,
+ POINTER_ICON_STYLE_NO_DROP = 1012,
+ POINTER_ICON_STYLE_ALL_SCROLL = 1013,
+ POINTER_ICON_STYLE_HORIZONTAL_DOUBLE_ARROW = 1014,
+ POINTER_ICON_STYLE_VERTICAL_DOUBLE_ARROW = 1015,
+ POINTER_ICON_STYLE_TOP_RIGHT_DOUBLE_ARROW = 1016,
+ POINTER_ICON_STYLE_TOP_LEFT_DOUBLE_ARROW = 1017,
+ POINTER_ICON_STYLE_ZOOM_IN = 1018,
+ POINTER_ICON_STYLE_ZOOM_OUT = 1019,
+ POINTER_ICON_STYLE_GRAB = 1020,
+ POINTER_ICON_STYLE_GRABBING = 1021,
+
POINTER_ICON_STYLE_SPOT_HOVER = 2000,
POINTER_ICON_STYLE_SPOT_TOUCH = 2001,
POINTER_ICON_STYLE_SPOT_ANCHOR = 2002,
diff --git a/core/res/res/drawable-mdpi/pointer_alias.png b/core/res/res/drawable-mdpi/pointer_alias.png
new file mode 100644
index 0000000..8f61a39
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_alias.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_all_scroll.png b/core/res/res/drawable-mdpi/pointer_all_scroll.png
new file mode 100644
index 0000000..a897ef4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_all_scroll.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_cell.png b/core/res/res/drawable-mdpi/pointer_cell.png
new file mode 100644
index 0000000..b521389
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_cell.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_context_menu.png b/core/res/res/drawable-mdpi/pointer_context_menu.png
new file mode 100644
index 0000000..4e1ba4e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_context_menu.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_copy.png b/core/res/res/drawable-mdpi/pointer_copy.png
new file mode 100644
index 0000000..7d41036
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_copy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_crosshair.png b/core/res/res/drawable-mdpi/pointer_crosshair.png
new file mode 100644
index 0000000..8a06c77
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_crosshair.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_grab.png b/core/res/res/drawable-mdpi/pointer_grab.png
new file mode 100644
index 0000000..0e0ea2e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_grab.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_grabbing.png b/core/res/res/drawable-mdpi/pointer_grabbing.png
new file mode 100644
index 0000000..9deb64c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_grabbing.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_hand.png b/core/res/res/drawable-mdpi/pointer_hand.png
new file mode 100644
index 0000000..c614d9e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_hand.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_help.png b/core/res/res/drawable-mdpi/pointer_help.png
new file mode 100644
index 0000000..d54b2b1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_help.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png
new file mode 100644
index 0000000..a2951a9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_nodrop.png b/core/res/res/drawable-mdpi/pointer_nodrop.png
new file mode 100644
index 0000000..ad13c66
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_nodrop.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_text.png b/core/res/res/drawable-mdpi/pointer_text.png
new file mode 100644
index 0000000..34d1698
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_text.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_top_left_diagonal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_top_left_diagonal_double_arrow.png
new file mode 100644
index 0000000..b0cd92c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_top_left_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png
new file mode 100644
index 0000000..f8d3527
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_vertical_double_arrow.png b/core/res/res/drawable-mdpi/pointer_vertical_double_arrow.png
new file mode 100644
index 0000000..48c9379
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_vertical_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_vertical_text.png b/core/res/res/drawable-mdpi/pointer_vertical_text.png
new file mode 100644
index 0000000..9fcbcba
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_vertical_text.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_zoom_in.png b/core/res/res/drawable-mdpi/pointer_zoom_in.png
new file mode 100644
index 0000000..17c4e66
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_zoom_in.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_zoom_out.png b/core/res/res/drawable-mdpi/pointer_zoom_out.png
new file mode 100644
index 0000000..742f705
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_zoom_out.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_alias.png b/core/res/res/drawable-xhdpi/pointer_alias.png
new file mode 100644
index 0000000..fe0fd25
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_alias.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_all_scroll.png b/core/res/res/drawable-xhdpi/pointer_all_scroll.png
new file mode 100644
index 0000000..e2374ec
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_all_scroll.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_cell.png b/core/res/res/drawable-xhdpi/pointer_cell.png
new file mode 100644
index 0000000..4ca09e3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_cell.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_context_menu.png b/core/res/res/drawable-xhdpi/pointer_context_menu.png
new file mode 100644
index 0000000..05a59f8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_context_menu.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_copy.png b/core/res/res/drawable-xhdpi/pointer_copy.png
new file mode 100644
index 0000000..f28a3e9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_copy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_crosshair.png b/core/res/res/drawable-xhdpi/pointer_crosshair.png
new file mode 100644
index 0000000..86c649c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_crosshair.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_grab.png b/core/res/res/drawable-xhdpi/pointer_grab.png
new file mode 100644
index 0000000..b5c28ba
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_grab.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_grabbing.png b/core/res/res/drawable-xhdpi/pointer_grabbing.png
new file mode 100644
index 0000000..6aba589
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_grabbing.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_hand.png b/core/res/res/drawable-xhdpi/pointer_hand.png
new file mode 100644
index 0000000..486cb24
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_hand.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_help.png b/core/res/res/drawable-xhdpi/pointer_help.png
new file mode 100644
index 0000000..98a6632
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_help.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow.png
new file mode 100644
index 0000000..299ae11
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_nodrop.png b/core/res/res/drawable-xhdpi/pointer_nodrop.png
new file mode 100644
index 0000000..c56bfbb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_nodrop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_text.png b/core/res/res/drawable-xhdpi/pointer_text.png
new file mode 100644
index 0000000..0cebeae
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_text.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png
new file mode 100644
index 0000000..5454a8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow.png
new file mode 100644
index 0000000..a4268e4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow.png
new file mode 100644
index 0000000..95ca954
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_vertical_text.png b/core/res/res/drawable-xhdpi/pointer_vertical_text.png
new file mode 100644
index 0000000..a07d091
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_vertical_text.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_zoom_in.png b/core/res/res/drawable-xhdpi/pointer_zoom_in.png
new file mode 100644
index 0000000..9c29fcb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_zoom_in.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_zoom_out.png b/core/res/res/drawable-xhdpi/pointer_zoom_out.png
new file mode 100644
index 0000000..710552b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_zoom_out.png
Binary files differ
diff --git a/core/res/res/drawable/pointer_alias_icon.xml b/core/res/res/drawable/pointer_alias_icon.xml
new file mode 100644
index 0000000..8ba9301
--- /dev/null
+++ b/core/res/res/drawable/pointer_alias_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_alias"
+ android:hotSpotX="8dp"
+ android:hotSpotY="6dp" />
diff --git a/core/res/res/drawable/pointer_all_scroll_icon.xml b/core/res/res/drawable/pointer_all_scroll_icon.xml
new file mode 100644
index 0000000..e946948
--- /dev/null
+++ b/core/res/res/drawable/pointer_all_scroll_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_all_scroll"
+ android:hotSpotX="11dp"
+ android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_cell_icon.xml b/core/res/res/drawable/pointer_cell_icon.xml
new file mode 100644
index 0000000..da1e320
--- /dev/null
+++ b/core/res/res/drawable/pointer_cell_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_cell"
+ android:hotSpotX="11dp"
+ android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_context_menu_icon.xml b/core/res/res/drawable/pointer_context_menu_icon.xml
new file mode 100644
index 0000000..330b627
--- /dev/null
+++ b/core/res/res/drawable/pointer_context_menu_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_context_menu"
+ android:hotSpotX="4dp"
+ android:hotSpotY="4dp" />
diff --git a/core/res/res/drawable/pointer_copy_icon.xml b/core/res/res/drawable/pointer_copy_icon.xml
new file mode 100644
index 0000000..e299db5
--- /dev/null
+++ b/core/res/res/drawable/pointer_copy_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_copy"
+ android:hotSpotX="9dp"
+ android:hotSpotY="9dp" />
diff --git a/core/res/res/drawable/pointer_crosshair_icon.xml b/core/res/res/drawable/pointer_crosshair_icon.xml
new file mode 100644
index 0000000..3b96a8a
--- /dev/null
+++ b/core/res/res/drawable/pointer_crosshair_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_crosshair"
+ android:hotSpotX="12dp"
+ android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_grab_icon.xml b/core/res/res/drawable/pointer_grab_icon.xml
new file mode 100644
index 0000000..d437b3a
--- /dev/null
+++ b/core/res/res/drawable/pointer_grab_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_grab"
+ android:hotSpotX="8dp"
+ android:hotSpotY="5dp" />
diff --git a/core/res/res/drawable/pointer_grabbing_icon.xml b/core/res/res/drawable/pointer_grabbing_icon.xml
new file mode 100644
index 0000000..38f4c3a
--- /dev/null
+++ b/core/res/res/drawable/pointer_grabbing_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_grabbing"
+ android:hotSpotX="9dp"
+ android:hotSpotY="9dp" />
diff --git a/core/res/res/drawable/pointer_hand_icon.xml b/core/res/res/drawable/pointer_hand_icon.xml
new file mode 100644
index 0000000..3d90b88
--- /dev/null
+++ b/core/res/res/drawable/pointer_hand_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_hand"
+ android:hotSpotX="9dp"
+ android:hotSpotY="4dp" />
diff --git a/core/res/res/drawable/pointer_help_icon.xml b/core/res/res/drawable/pointer_help_icon.xml
new file mode 100644
index 0000000..49ae554
--- /dev/null
+++ b/core/res/res/drawable/pointer_help_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_help"
+ android:hotSpotX="4dp"
+ android:hotSpotY="4dp" />
diff --git a/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml b/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml
new file mode 100644
index 0000000..5a5ad9e
--- /dev/null
+++ b/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_horizontal_double_arrow"
+ android:hotSpotX="11dp"
+ android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_nodrop_icon.xml b/core/res/res/drawable/pointer_nodrop_icon.xml
new file mode 100644
index 0000000..955b40f
--- /dev/null
+++ b/core/res/res/drawable/pointer_nodrop_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_nodrop"
+ android:hotSpotX="9dp"
+ android:hotSpotY="9dp" />
diff --git a/core/res/res/drawable/pointer_text_icon.xml b/core/res/res/drawable/pointer_text_icon.xml
new file mode 100644
index 0000000..d948c89
--- /dev/null
+++ b/core/res/res/drawable/pointer_text_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_text"
+ android:hotSpotX="12dp"
+ android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml b/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml
new file mode 100644
index 0000000..de5efe2
--- /dev/null
+++ b/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_top_left_diagonal_double_arrow"
+ android:hotSpotX="11dp"
+ android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml b/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml
new file mode 100644
index 0000000..e87b526
--- /dev/null
+++ b/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_top_right_diagonal_double_arrow"
+ android:hotSpotX="12dp"
+ android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml b/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml
new file mode 100644
index 0000000..5759079
--- /dev/null
+++ b/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_vertical_double_arrow"
+ android:hotSpotX="11dp"
+ android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_vertical_text_icon.xml b/core/res/res/drawable/pointer_vertical_text_icon.xml
new file mode 100644
index 0000000..3b48dc8
--- /dev/null
+++ b/core/res/res/drawable/pointer_vertical_text_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_vertical_text"
+ android:hotSpotX="12dp"
+ android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_zoom_in_icon.xml b/core/res/res/drawable/pointer_zoom_in_icon.xml
new file mode 100644
index 0000000..e2dcb49
--- /dev/null
+++ b/core/res/res/drawable/pointer_zoom_in_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_zoom_in"
+ android:hotSpotX="10dp"
+ android:hotSpotY="10dp" />
diff --git a/core/res/res/drawable/pointer_zoom_out_icon.xml b/core/res/res/drawable/pointer_zoom_out_icon.xml
new file mode 100644
index 0000000..b805df3
--- /dev/null
+++ b/core/res/res/drawable/pointer_zoom_out_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_zoom_out"
+ android:hotSpotX="10dp"
+ android:hotSpotY="10dp" />
diff --git a/core/res/res/drawable/spinner_background_material.xml b/core/res/res/drawable/spinner_background_material.xml
index d37f5b7..c2a2a26 100644
--- a/core/res/res/drawable/spinner_background_material.xml
+++ b/core/res/res/drawable/spinner_background_material.xml
@@ -17,18 +17,18 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack"
android:paddingStart="0dp"
- android:paddingEnd="24dp"
+ android:paddingEnd="48dp"
android:paddingLeft="0dp"
android:paddingRight="0dp">
<item
- android:gravity="end|center_vertical"
- android:width="24dp"
- android:height="24dp"
+ android:gravity="end|fill_vertical"
+ android:width="48dp"
android:drawable="@drawable/control_background_40dp_material" />
<item
android:drawable="@drawable/ic_spinner_caret"
android:gravity="end|center_vertical"
android:width="24dp"
- android:height="24dp" />
+ android:height="24dp"
+ android:end="12dp" />
</layer-list>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 60f0502..9c420c2 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -143,7 +143,7 @@
<string name="fcError" msgid="3327560126588500777">"Forbindelsesproblemer eller ugyldig funktionskode."</string>
<string name="httpErrorOk" msgid="1191919378083472204">"OK"</string>
<string name="httpError" msgid="7956392511146698522">"Der opstod en netværksfejl."</string>
- <string name="httpErrorLookup" msgid="4711687456111963163">"Webadressen kunne ikke findes."</string>
+ <string name="httpErrorLookup" msgid="4711687456111963163">"Webadressen blev ikke fundet."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"Ordningen for webstedsgodkendelse understøttes ikke."</string>
<string name="httpErrorAuth" msgid="1435065629438044534">"Der kunne ikke godkendes."</string>
<string name="httpErrorProxyAuth" msgid="1788207010559081331">"Godkendelse via proxyserveren mislykkedes."</string>
@@ -155,7 +155,7 @@
<string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Der kunne ikke oprettes en sikker forbindelse."</string>
<string name="httpErrorBadUrl" msgid="3636929722728881972">"Siden kunne ikke åbnes, fordi webadressen er ugyldig."</string>
<string name="httpErrorFile" msgid="2170788515052558676">"Der kunne ikke fås adgang til filen."</string>
- <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Den ønskede fil kunne ikke findes."</string>
+ <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Den ønskede fil blev ikke fundet."</string>
<string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Der behandles for mange anmodninger. Prøv igen senere."</string>
<string name="notification_title" msgid="8967710025036163822">"Loginfejl for <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"Synkroniser"</string>
@@ -248,7 +248,7 @@
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"undersøge indholdet i et vindue, du interagerer med."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"aktivere Udforsk ved berøring"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"De emner, der trykkes på, læses højt, og skærmen kan udforskes ved hjælp af bevægelser."</string>
- <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"aktivere forbedrede webhjælpefunktioner"</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Aktivér udvidede webhjælpefunktioner"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Der installeres muligvis scripts for at gøre appindhold mere tilgængeligt."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"observere tekst, du skriver"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Dette omfatter personlige data såsom kreditkortnumre og adgangskoder."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c13ef14..54100d5 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -223,7 +223,7 @@
<string name="global_action_lockdown" msgid="8751542514724332873">"立即锁定"</string>
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
- <string name="android_system_label" msgid="6577375335728551336">"Android系统"</string>
+ <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
<string name="user_owner_label" msgid="2804351898001038951">"个人"</string>
<string name="managed_profile_label" msgid="6260850669674791528">"工作"</string>
<string name="permgrouplab_contacts" msgid="3657758145679177612">"通讯录"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a6eb68b..b818fe0 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7605,6 +7605,44 @@
<attr name="pointerIconSpotTouch" format="reference" />
<!-- Reference to a pointer icon drawable with STYLE_SPOT_ANCHOR -->
<attr name="pointerIconSpotAnchor" format="reference" />
+ <!-- Reference to a pointer drawable with STYLE_CONTEXT_MENU -->
+ <attr name="pointerIconContextMenu" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_HAND -->
+ <attr name="pointerIconHand" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_HELP -->
+ <attr name="pointerIconHelp" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_CELL -->
+ <attr name="pointerIconCell" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_CROSSHAIR -->
+ <attr name="pointerIconCrosshair" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_TEXT -->
+ <attr name="pointerIconText" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_VERTICAL_TEXT -->
+ <attr name="pointerIconVerticalText" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_ALIAS -->
+ <attr name="pointerIconAlias" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_COPY -->
+ <attr name="pointerIconCopy" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_NODROP -->
+ <attr name="pointerIconNodrop" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_ALL_SCROLL -->
+ <attr name="pointerIconAllScroll" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_HORIZONTAL_DOUBLE_ARROW -->
+ <attr name="pointerIconHorizontalDoubleArrow" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_VERTICAL_DOUBLE_ARROW -->
+ <attr name="pointerIconVerticalDoubleArrow" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW -->
+ <attr name="pointerIconTopRightDiagonalDoubleArrow" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW -->
+ <attr name="pointerIconTopLeftDiagonalDoubleArrow" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_ZOOM_IN -->
+ <attr name="pointerIconZoomIn" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_ZOOM_OUT -->
+ <attr name="pointerIconZoomOut" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_GRAB -->
+ <attr name="pointerIconGrab" format="reference"/>
+ <!-- Reference to a pointer drawable with STYLE_GRABBING -->
+ <attr name="pointerIconGrabbing" format="reference"/>
</declare-styleable>
<declare-styleable name="PointerIcon">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 091d57f..322ac4f 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2093,6 +2093,10 @@
<enum name="hdpi" value="240" />
<!-- An extra high density screen, approximately 320dpi. -->
<enum name="xhdpi" value="320" />
+ <!-- An extra extra high density screen, approximately 480dpi. -->
+ <enum name="xxhdpi" value="480" />
+ <!-- An extra extra extra high density screen, approximately 640dpi. -->
+ <enum name="xxxhdpi" value="640" />
</attr>
</declare-styleable>
@@ -2193,18 +2197,25 @@
<attr name="name" />
</declare-styleable>
- <!-- <code>initial-layout</code> tag allows configuring the initial layout for the activity
- within multi-window environment. -->
- <declare-styleable name="AndroidManifestInitialLayout" parent="AndroidManifestActivity">
+ <!-- <code>layout</code> tag allows configuring the layout for the activity within multi-window
+ environment. -->
+ <declare-styleable name="AndroidManifestLayout" parent="AndroidManifestActivity">
<!-- Initial width of the activity. Can be either a fixed value or fraction, in which case
the width will be constructed as a fraction of the total available width. -->
- <attr name="activityWidth" format="dimension|fraction" />
+ <attr name="initialWidth" format="dimension|fraction" />
<!-- Initial height of the activity. Can be either a fixed value or fraction, in which case
the height will be constructed as a fraction of the total available height. -->
- <attr name="activityHeight" format="dimension|fraction" />
+ <attr name="initialHeight" format="dimension|fraction" />
<!-- Where to initially position the activity inside the available space. Uses constants
defined in {@link android.view.Gravity}. -->
<attr name="gravity" />
+ <!-- Minimal height of the activity.
+
+ <p>NOTE: A task's root activity value is applied to all additional activities launched
+ in the task. That is if the root activity of a task set minimal size, then the system
+ will set the same minimal size on all other activities in the task. It will also
+ ignore any other minimal size attributes of non-root activities. -->
+ <attr name="minimalSize" format="dimension" />
</declare-styleable>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 24d760f..f833719 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -938,6 +938,9 @@
<!-- Is the device capable of hot swapping an UICC Card -->
<bool name="config_hotswapCapable">false</bool>
+ <!-- Component name of the ICC hotswap prompt for restart dialog -->
+ <string name="config_iccHotswapPromptForRestartDialogComponent" translateable="false">@null</string>
+
<!-- Enable puk unlockscreen by default.
If unlock screen is disabled, the puk should be unlocked through Emergency Dialer -->
<bool name="config_enable_puk_unlock_screen">true</bool>
@@ -2318,7 +2321,7 @@
<!-- Flag indicating device support for EAP SIM, AKA, AKA' -->
<bool name="config_eap_sim_based_auth_supported">true</bool>
-
+
<!-- How long history of previous vibrations should be kept for the dumpsys. -->
<integer name="config_previousVibrationsDumpLimit">20</integer>
@@ -2349,4 +2352,8 @@
<!-- Name of the component to handle network policy notifications. If present,
disables NetworkPolicyManagerService's presentation of data-usage notifications. -->
<string translatable="false" name="config_networkPolicyNotificationComponent"></string>
+
+ <!-- The fraction of display size (lower of height and width) that will be used to determine
+ the default minimal size for resizeable tasks. -->
+ <fraction name="config_displayFractionForDefaultMinimalSizeOfResizeableTask">25%</fraction>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f4d0b39..957cb50 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2662,8 +2662,9 @@
<public type="attr" name="listMenuViewStyle" />
<public type="attr" name="subMenuArrow" />
- <public type="attr" name="activityWidth" />
- <public type="attr" name="activityHeight" />
+ <public type="attr" name="initialWidth" />
+ <public type="attr" name="initialHeight" />
+ <public type="attr" name="minimalSize" />
<public type="attr" name="resizeableActivity" />
<public type="attr" name="titleMargin" />
<public type="attr" name="titleMarginStart" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index af5c74d..40cd097 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3993,6 +3993,9 @@
<!-- Zen mode condition - line two: ending time. [CHAR LIMIT=NONE] -->
<string name="zen_mode_until">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string>
+ <!-- Zen mode condition - line one: Until next alarm. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_alarm">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g> (next alarm)</string>
+
<!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
<string name="zen_mode_forever">Until you turn this off</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 11c4cc0..b831df8 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1336,6 +1336,33 @@
<item name="pointerIconSpotHover">@drawable/pointer_spot_hover_icon</item>
<item name="pointerIconSpotTouch">@drawable/pointer_spot_touch_icon</item>
<item name="pointerIconSpotAnchor">@drawable/pointer_spot_anchor_icon</item>
+ <item name="pointerIconHand">@drawable/pointer_hand_icon</item>
+ <item name="pointerIconContextMenu">@drawable/pointer_context_menu_icon</item>
+ <item name="pointerIconHelp">@drawable/pointer_help_icon</item>
+ <item name="pointerIconCell">@drawable/pointer_cell_icon</item>
+ <item name="pointerIconCrosshair">@drawable/pointer_crosshair_icon</item>
+ <item name="pointerIconText">@drawable/pointer_text_icon</item>
+ <item name="pointerIconVerticalText">@drawable/pointer_vertical_text_icon</item>
+ <item name="pointerIconAlias">@drawable/pointer_alias_icon</item>
+ <item name="pointerIconCopy">@drawable/pointer_copy_icon</item>
+ <item name="pointerIconAllScroll">@drawable/pointer_all_scroll_icon</item>
+ <item name="pointerIconNodrop">@drawable/pointer_nodrop_icon</item>
+ <item name="pointerIconHorizontalDoubleArrow">
+ @drawable/pointer_horizontal_double_arrow_icon
+ </item>
+ <item name="pointerIconVerticalDoubleArrow">
+ @drawable/pointer_vertical_double_arrow_icon
+ </item>
+ <item name="pointerIconTopRightDiagonalDoubleArrow">
+ @drawable/pointer_top_right_diagonal_double_arrow_icon
+ </item>
+ <item name="pointerIconTopLeftDiagonalDoubleArrow">
+ @drawable/pointer_top_left_diagonal_double_arrow_icon
+ </item>
+ <item name="pointerIconZoomIn">@drawable/pointer_zoom_in_icon</item>
+ <item name="pointerIconZoomOut">@drawable/pointer_zoom_out_icon</item>
+ <item name="pointerIconGrab">@drawable/pointer_grab_icon</item>
+ <item name="pointerIconGrabbing">@drawable/pointer_grabbing_icon</item>
</style>
<!-- Wifi dialog styles -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06de81d..1239b87 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1686,6 +1686,7 @@
<java-symbol type="id" name="replace_app_icon" />
<java-symbol type="id" name="replace_message" />
<java-symbol type="fraction" name="config_dimBehindFadeDuration" />
+ <java-symbol type="fraction" name="config_displayFractionForDefaultMinimalSizeOfResizeableTask" />
<java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
<java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
<java-symbol type="integer" name="config_autoBrightnessDarkeningLightDebounce"/>
@@ -2078,6 +2079,7 @@
<java-symbol type="string" name="zen_mode_default_events_name" />
<java-symbol type="array" name="config_system_condition_providers" />
<java-symbol type="string" name="muted_by" />
+ <java-symbol type="string" name="zen_mode_alarm" />
<java-symbol type="string" name="select_day" />
<java-symbol type="string" name="select_year" />
@@ -2326,4 +2328,6 @@
<java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" />
<java-symbol type="drawable" name="platlogo_m" />
+
+ <java-symbol type="string" name="config_iccHotswapPromptForRestartDialogComponent" />
</resources>
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index 6d20503..7164747 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -618,7 +618,7 @@
}
@SmallTest
- public void testASeek() throws Throwable {
+ public void testSeek() throws Throwable {
final MyListener l1 = new MyListener();
final MyListener l2 = new MyListener();
final MyUpdateListener updateListener1 = new MyUpdateListener();
@@ -757,6 +757,227 @@
}
+ @SmallTest
+ public void testSeekWhileRunning() throws Throwable {
+ // Seek one animator to the beginning and the other one to the end when they are running.
+ final MyListener l1 = new MyListener();
+ final MyListener l2 = new MyListener();
+ a1.addListener(l1);
+ a2.addListener(l2);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.startCalled);
+ assertFalse(l2.startCalled);
+ assertEquals(0f, a1.getAnimatedFraction());
+ assertEquals(0f, a2.getAnimatedFraction());
+ a1.start();
+ a2.start();
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.endCalled);
+ assertFalse(l2.endCalled);
+ assertTrue(a1.isRunning());
+ assertTrue(a2.isRunning());
+ // During the run, seek one to the beginning, the other to the end
+ a1.setCurrentFraction(0f);
+ a2.setCurrentFraction(1f);
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Check that a2 has finished due to the seeking, but a1 hasn't finished.
+ assertFalse(l1.endCalled);
+ assertTrue(l2.endCalled);
+ assertEquals(1f, a2.getAnimatedFraction());
+ }
+ });
+
+ Thread.sleep(a1.getTotalDuration());
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // By now a1 should finish also.
+ assertTrue(l1.endCalled);
+ assertEquals(1f, a1.getAnimatedFraction());
+ }
+ });
+ }
+
+ @SmallTest
+ public void testZeroDuration() throws Throwable {
+ // Run two animators with zero duration, with one running forward and the other one
+ // backward. Check that the animations start and finish with the correct end fractions.
+ a1.setDuration(0);
+ a2.setDuration(0);
+
+ // Set a fraction on an animation with 0-duration
+ final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
+ a3.setDuration(0);
+ a3.setCurrentFraction(1.0f);
+ assertEquals(1.0f, a3.getAnimatedFraction());
+
+ final MyListener l1 = new MyListener();
+ final MyListener l2 = new MyListener();
+ final MyListener l3 = new MyListener();
+ a1.addListener(l1);
+ a2.addListener(l2);
+ a3.addListener(l3);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.startCalled);
+ assertFalse(l2.startCalled);
+ assertFalse(l3.startCalled);
+ assertFalse(l1.endCalled);
+ assertFalse(l2.endCalled);
+ assertFalse(l3.endCalled);
+ a1.start();
+ a2.reverse();
+ a3.start();
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Check that the animators have started and finished with the right values.
+ assertTrue(l1.startCalled);
+ assertTrue(l2.startCalled);
+ assertTrue(l3.startCalled);
+ assertTrue(l1.endCalled);
+ assertTrue(l2.endCalled);
+ assertTrue(l3.endCalled);
+ assertEquals(1.0f, a1.getAnimatedFraction());
+ assertEquals(0f, a2.getAnimatedFraction());
+ assertEquals(1f, a3.getAnimatedFraction());
+ assertEquals(A1_END_VALUE, a1.getAnimatedValue());
+ assertEquals(A2_START_VALUE, a2.getAnimatedValue());
+ assertEquals(100, a3.getAnimatedValue());
+ }
+ });
+ }
+
+ @SmallTest
+ public void testZeroScale() throws Throwable {
+ // Test whether animations would end properly when the scale is forced to be zero
+ float scale = ValueAnimator.getDurationScale();
+ ValueAnimator.setDurationScale(0f);
+
+ // Run two animators, one of which has a start delay, after setting the duration scale to 0
+ a1.setStartDelay(200);
+ final MyListener l1 = new MyListener();
+ final MyListener l2 = new MyListener();
+ a1.addListener(l1);
+ a2.addListener(l2);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.startCalled);
+ assertFalse(l2.startCalled);
+ assertFalse(l1.endCalled);
+ assertFalse(l2.endCalled);
+
+ a1.start();
+ a2.start();
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(l1.startCalled);
+ assertTrue(l2.startCalled);
+ assertTrue(l1.endCalled);
+ assertTrue(l2.endCalled);
+ }
+ });
+
+ // Restore duration scale
+ ValueAnimator.setDurationScale(scale);
+ }
+
+ @SmallTest
+ public void testReverse() throws Throwable {
+ // Prolong animators duration so that we can do multiple checks during their run
+ final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
+ a1.setDuration(400);
+ a2.setDuration(600);
+ a3.setDuration(400);
+ final MyListener l1 = new MyListener();
+ final MyListener l2 = new MyListener();
+ final MyListener l3 = new MyListener();
+ a1.addListener(l1);
+ a2.addListener(l2);
+ a3.addListener(l3);
+
+ // Reverse three animators, seek one to the beginning and another to the end, and force
+ // to end the third one during reversing.
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(l1.startCalled);
+ assertFalse(l2.startCalled);
+ assertFalse(l3.startCalled);
+ assertFalse(l1.endCalled);
+ assertFalse(l2.endCalled);
+ assertFalse(l3.endCalled);
+ a1.reverse();
+ a2.reverse();
+ a3.reverse();
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(l1.startCalled);
+ assertTrue(l2.startCalled);
+ assertTrue(l3.startCalled);
+
+ a1.setCurrentFraction(0f);
+ a2.setCurrentFraction(1f);
+ a3.end();
+
+ // Check that the fraction has been set, and the getter returns the correct values.
+ assertEquals(1f, a1.getAnimatedFraction());
+ assertEquals(0f, a2.getAnimatedFraction());
+ }
+ });
+ Thread.sleep(POLL_INTERVAL);
+
+ // By now, a2 should have finished due to the seeking. It wouldn't have finished otherwise.
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Check that both animations have started, and a2 has finished.
+ assertFalse(l1.endCalled);
+ assertTrue(l2.endCalled);
+ assertTrue(l3.endCalled);
+ }
+ });
+ Thread.sleep(a1.getTotalDuration());
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Verify that a1 has finished as well.
+ assertTrue(l1.endCalled);
+ assertEquals(0f, a1.getAnimatedFraction());
+ assertEquals(0f, a2.getAnimatedFraction());
+ assertEquals(0f, a3.getAnimatedFraction());
+ }
+ });
+ }
+
class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
boolean wasRunning = false;
long firstRunningFrameTime = -1;
diff --git a/data/keyboards/Vendor_0079_Product_0011.kl b/data/keyboards/Vendor_0079_Product_0011.kl
index 2ae2a01..32f8c82 100644
--- a/data/keyboards/Vendor_0079_Product_0011.kl
+++ b/data/keyboards/Vendor_0079_Product_0011.kl
@@ -12,10 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Classic NES Controller
+# Classic [S]NES Controller
+key 288 BUTTON_X
key 289 BUTTON_A
key 290 BUTTON_B
+key 291 BUTTON_Y
+key 292 BUTTON_L1
+key 293 BUTTON_R1
key 297 BUTTON_START
key 296 BUTTON_SELECT
diff --git a/docs/html/guide/topics/manifest/compatible-screens-element.jd b/docs/html/guide/topics/manifest/compatible-screens-element.jd
index 3606b15..de921d2 100644
--- a/docs/html/guide/topics/manifest/compatible-screens-element.jd
+++ b/docs/html/guide/topics/manifest/compatible-screens-element.jd
@@ -9,7 +9,7 @@
<pre>
<<a href="#compatible-screens">compatible-screens</a>>
<<a href="#screen">screen</a> android:<a href="#screenSize">screenSize</a>=["small" | "normal" | "large" | "xlarge"]
- android:<a href="#screenDensity">screenDensity</a>=["ldpi" | "mdpi" | "hdpi" | "xhdpi"] />
+ android:<a href="#screenDensity">screenDensity</a>=["ldpi" | "mdpi" | "hdpi" | "xhdpi" | "xxhdpi" | "xxxhdpi"] />
...
</compatible-screens>
</pre>
@@ -94,11 +94,9 @@
<li>{@code mdpi}</li>
<li>{@code hdpi}</li>
<li>{@code xhdpi}</li>
+ <li>{@code xxhdpi}</li>
+ <li>{@code xxxhdpi}</li>
</ul>
- <p class="note"><strong>Note:</strong> This attribute currently does not accept
- {@code xxhdpi} as a valid value, but you can instead specify {@code 480}
- as the value, which is the approximate threshold for xhdpi screens.</p>
-
<p>For information about the different screen densities, see <a
href="{@docRoot}guide/practices/screens_support.html#range">Supporting Multiple Screens</a>.</p>
</dd>
@@ -110,8 +108,8 @@
<dt>example</dt>
<dd>
<p>If your application is compatible with only small and normal screens, regardless
-of screen density, then you must specify eight different {@code <screen>} elements,
-because each screen size has four different density configurations. You must declare each one of
+of screen density, then you must specify twelve different {@code <screen>} elements,
+because each screen size has six different density configurations. You must declare each one of
these; any combination of size and density that you do <em>not</em> specify is considered a screen
configuration with which your application is <em>not</em> compatible. Here's what the manifest
entry looks like if your application is compatible with only small and normal screens:</p>
@@ -125,11 +123,15 @@
<screen android:screenSize="small" android:screenDensity="mdpi" />
<screen android:screenSize="small" android:screenDensity="hdpi" />
<screen android:screenSize="small" android:screenDensity="xhdpi" />
+ <screen android:screenSize="small" android:screenDensity="xxhdpi" />
+ <screen android:screenSize="small" android:screenDensity="xxxhdpi" />
<!-- all normal size screens -->
<screen android:screenSize="normal" android:screenDensity="ldpi" />
<screen android:screenSize="normal" android:screenDensity="mdpi" />
<screen android:screenSize="normal" android:screenDensity="hdpi" />
<screen android:screenSize="normal" android:screenDensity="xhdpi" />
+ <screen android:screenSize="normal" android:screenDensity="xxhdpi" />
+ <screen android:screenSize="normal" android:screenDensity="xxxhdpi" />
</compatible-screens>
<application ... >
...
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index dc258db..0375a2f 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -42,9 +42,9 @@
JDK 6 or higher (the JRE alone is not sufficient)—JDK 7 is required when
developing for Android 5.0 and higher. To check if you
have JDK installed (and which version), open a terminal and type <code>javac -version</code>.
-If the JDK is not available or the version is lower than 6,
-<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" class="external-link"
->go download JDK</a>.</p>
+If the JDK is not available or the version is lower than version 6, download the
+<a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html" class="external-link"
+>Java SE Development Kit 7</a>.</p>
<div class="procedure-box">
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index e0d8ccc..3bd17fa 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -19,6 +19,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.io.PrintWriter;
+
/**
* Point holds two integer coordinates
@@ -95,6 +97,11 @@
return "Point(" + x + ", " + y + ")";
}
+ /** @hide */
+ public void printShortString(PrintWriter pw) {
+ pw.println("["); pw.print(x); pw.print(","); pw.print(y); pw.print("]");
+ }
+
/**
* Parcelable interface methods
*/
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 8011b59..6f548bc 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,6 +2,8 @@
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+HWUI_NEW_OPS := false
+
hwui_src_files := \
font/CacheTexture.cpp \
font/Font.cpp \
@@ -85,6 +87,17 @@
-Wall -Wno-unused-parameter -Wunreachable-code \
-ffast-math -O3 -Werror
+
+ifeq (true, $(HWUI_NEW_OPS))
+ hwui_src_files += \
+ BakedOpRenderer.cpp \
+ OpReorderer.cpp \
+ RecordingCanvas.cpp
+
+ hwui_cflags += -DHWUI_NEW_OPS
+
+endif
+
ifndef HWUI_COMPILE_SYMBOLS
hwui_cflags += -fvisibility=hidden
endif
@@ -172,6 +185,13 @@
unit_tests/LinearAllocatorTests.cpp \
unit_tests/StringUtilsTests.cpp
+ifeq (true, $(HWUI_NEW_OPS))
+ LOCAL_SRC_FILES += \
+ unit_tests/BakedOpStateTests.cpp \
+ unit_tests/RecordingCanvasTests.cpp \
+ unit_tests/OpReordererTests.cpp
+endif
+
include $(BUILD_NATIVE_TEST)
# ------------------------
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
new file mode 100644
index 0000000..4d9f9b4
--- /dev/null
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#include "BakedOpRenderer.h"
+
+#include "Caches.h"
+#include "Glop.h"
+#include "GlopBuilder.h"
+#include "renderstate/RenderState.h"
+#include "utils/GLUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+Texture* BakedOpRenderer::Info::getTexture(const SkBitmap* bitmap) {
+ Texture* texture = renderState.assetAtlas().getEntryTexture(bitmap);
+ if (!texture) {
+ return caches.textureCache.get(bitmap);
+ }
+ return texture;
+}
+
+void BakedOpRenderer::Info::renderGlop(const BakedOpState& state, const Glop& glop) {
+ bool useScissor = state.computedState.clipSideFlags != OpClipSideFlags::None;
+ renderState.scissor().setEnabled(useScissor);
+ if (useScissor) {
+ const Rect& clip = state.computedState.clipRect;
+ renderState.scissor().set(clip.left, viewportHeight - clip.bottom,
+ clip.getWidth(), clip.getHeight());
+ }
+ renderState.render(glop, orthoMatrix);
+ didDraw = true;
+}
+
+void BakedOpRenderer::startFrame(Info& info) {
+ info.renderState.setViewport(info.viewportWidth, info.viewportHeight);
+ info.renderState.blend().syncEnabled();
+ Caches::getInstance().clearGarbage();
+
+ if (!info.opaque) {
+ // TODO: partial invalidate!
+ info.renderState.scissor().setEnabled(false);
+ glClear(GL_COLOR_BUFFER_BIT);
+ info.didDraw = true;
+ }
+}
+void BakedOpRenderer::endFrame(Info& info) {
+ info.caches.pathCache.trim();
+ info.caches.tessellationCache.trim();
+
+#if DEBUG_OPENGL
+ GLUtils::dumpGLErrors();
+#endif
+
+#if DEBUG_MEMORY_USAGE
+ info.caches.dumpMemoryUsage();
+#else
+ if (Properties::debugLevel & kDebugMemory) {
+ info.caches.dumpMemoryUsage();
+ }
+#endif
+}
+
+void BakedOpRenderer::onRenderNodeOp(Info*, const RenderNodeOp&, const BakedOpState&) {
+ LOG_ALWAYS_FATAL("unsupported operation");
+}
+
+void BakedOpRenderer::onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+ info->caches.textureState().activateTexture(0); // TODO: should this be automatic, and/or elsewhere?
+ Texture* texture = info->getTexture(op.bitmap);
+ if (!texture) return;
+ const AutoTexture autoCleanup(texture);
+
+ const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType)
+ ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
+ Glop glop;
+ GlopBuilder(info->renderState, info->caches, &glop)
+ .setRoundRectClipState(state.roundRectClipState)
+ .setMeshTexturedUnitQuad(texture->uvMapper)
+ .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
+ .setTransform(state.computedState.transform, TransformFlags::None)
+ .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
+ .build();
+ info->renderGlop(state, glop);
+}
+
+void BakedOpRenderer::onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+ Glop glop;
+ GlopBuilder(info->renderState, info->caches, &glop)
+ .setRoundRectClipState(state.roundRectClipState)
+ .setMeshUnitQuad()
+ .setFillPaint(*op.paint, state.alpha)
+ .setTransform(state.computedState.transform, TransformFlags::None)
+ .setModelViewMapUnitToRect(op.unmappedBounds)
+ .build();
+ info->renderGlop(state, glop);
+}
+
+void BakedOpRenderer::onSimpleRectsOp(Info* info, const SimpleRectsOp& op, const BakedOpState& state) {
+ Glop glop;
+ GlopBuilder(info->renderState, info->caches, &glop)
+ .setRoundRectClipState(state.roundRectClipState)
+ .setMeshIndexedQuads(&op.vertices[0], op.vertexCount / 4)
+ .setFillPaint(*op.paint, state.alpha)
+ .setTransform(state.computedState.transform, TransformFlags::None)
+ .setModelViewOffsetRect(0, 0, op.unmappedBounds)
+ .build();
+ info->renderGlop(state, glop);
+}
+
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
new file mode 100644
index 0000000..b8b4426
--- /dev/null
+++ b/libs/hwui/BakedOpRenderer.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_BAKED_OP_RENDERER_H
+#define ANDROID_HWUI_BAKED_OP_RENDERER_H
+
+#include "BakedOpState.h"
+#include "Matrix.h"
+
+namespace android {
+namespace uirenderer {
+
+class Caches;
+struct Glop;
+class RenderState;
+
+class BakedOpRenderer {
+public:
+ class Info {
+ public:
+ Info(Caches& caches, RenderState& renderState, int viewportWidth, int viewportHeight, bool opaque)
+ : renderState(renderState)
+ , caches(caches)
+ , opaque(opaque)
+ , viewportWidth(viewportWidth)
+ , viewportHeight(viewportHeight) {
+ orthoMatrix.loadOrtho(viewportWidth, viewportHeight);
+ }
+
+ Texture* getTexture(const SkBitmap* bitmap);
+
+ void renderGlop(const BakedOpState& state, const Glop& glop);
+ RenderState& renderState;
+ Caches& caches;
+
+ bool didDraw = false;
+ bool opaque;
+
+
+ // where should these live? layer state object?
+ int viewportWidth;
+ int viewportHeight;
+ Matrix4 orthoMatrix;
+ };
+
+ static void startFrame(Info& info);
+ static void endFrame(Info& info);
+
+ /**
+ * Declare all "onBitmapOp(...)" style function for every op type.
+ *
+ * These functions will perform the actual rendering of the individual operations in OpenGL,
+ * given the transform/clip and other state built into the BakedOpState object passed in.
+ */
+ #define BAKED_OP_RENDERER_METHOD(Type) static void on##Type(Info* info, const Type& op, const BakedOpState& state);
+ MAP_OPS(BAKED_OP_RENDERER_METHOD);
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_BAKED_OP_RENDERER_H
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
new file mode 100644
index 0000000..e2201ca
--- /dev/null
+++ b/libs/hwui/BakedOpState.h
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_BAKED_OP_STATE_H
+#define ANDROID_HWUI_BAKED_OP_STATE_H
+
+#include "Matrix.h"
+#include "RecordedOp.h"
+#include "Rect.h"
+#include "Snapshot.h"
+
+namespace android {
+namespace uirenderer {
+
+namespace OpClipSideFlags {
+ enum {
+ None = 0x0,
+ Left = 0x1,
+ Top = 0x2,
+ Right = 0x4,
+ Bottom = 0x8,
+ Full = 0xF,
+ // ConservativeFull = 0x1F needed?
+ };
+}
+
+/**
+ * Holds the resolved clip, transform, and bounds of a recordedOp, when replayed with a snapshot
+ */
+class ResolvedRenderState {
+public:
+ // TODO: remove the mapRects/matrix multiply when snapshot & recorded transforms are translates
+ ResolvedRenderState(const Snapshot& snapshot, const RecordedOp& recordedOp) {
+ /* TODO: benchmark a fast path for translate-only matrices, such as:
+ if (CC_LIKELY(snapshot.transform->getType() == Matrix4::kTypeTranslate
+ && recordedOp.localMatrix.getType() == Matrix4::kTypeTranslate)) {
+ float translateX = snapshot.transform->getTranslateX() + recordedOp.localMatrix.getTranslateX();
+ float translateY = snapshot.transform->getTranslateY() + recordedOp.localMatrix.getTranslateY();
+ transform.loadTranslate(translateX, translateY, 0);
+
+ // resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
+ clipRect = recordedOp.localClipRect;
+ clipRect.translate(translateX, translateY);
+ clipRect.doIntersect(snapshot.getClipRect());
+ clipRect.snapToPixelBoundaries();
+
+ // resolvedClippedBounds = intersect(resolvedMatrix * opBounds, resolvedClipRect)
+ clippedBounds = recordedOp.unmappedBounds;
+ clippedBounds.translate(translateX, translateY);
+ } ... */
+
+ // resolvedMatrix = parentMatrix * localMatrix
+ transform.loadMultiply(*snapshot.transform, recordedOp.localMatrix);
+
+ // resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
+ clipRect = recordedOp.localClipRect;
+ snapshot.transform->mapRect(clipRect);
+ clipRect.doIntersect(snapshot.getClipRect());
+ clipRect.snapToPixelBoundaries();
+
+ // resolvedClippedBounds = intersect(resolvedMatrix * opBounds, resolvedClipRect)
+ clippedBounds = recordedOp.unmappedBounds;
+ transform.mapRect(clippedBounds);
+
+ if (clipRect.left > clippedBounds.left) clipSideFlags |= OpClipSideFlags::Left;
+ if (clipRect.top > clippedBounds.top) clipSideFlags |= OpClipSideFlags::Top;
+ if (clipRect.right < clippedBounds.right) clipSideFlags |= OpClipSideFlags::Right;
+ if (clipRect.bottom < clippedBounds.bottom) clipSideFlags |= OpClipSideFlags::Bottom;
+ clippedBounds.doIntersect(clipRect);
+
+ /**
+ * TODO: once we support complex clips, we may want to reject to avoid that work where
+ * possible. Should we:
+ * 1 - quickreject based on clippedBounds, quick early (duplicating logic in resolvedOp)
+ * 2 - merge stuff into tryConstruct factory method, so it can handle quickRejection
+ * and early return null in one place.
+ */
+ }
+ Matrix4 transform;
+ Rect clipRect;
+ int clipSideFlags = 0;
+ Rect clippedBounds;
+};
+
+/**
+ * Self-contained op wrapper, containing all resolved state required to draw the op.
+ *
+ * Stashed pointers within all point to longer lived objects, with no ownership implied.
+ */
+class BakedOpState {
+public:
+ static BakedOpState* tryConstruct(LinearAllocator& allocator,
+ const Snapshot& snapshot, const RecordedOp& recordedOp) {
+ BakedOpState* bakedOp = new (allocator) BakedOpState(
+ snapshot, recordedOp);
+ if (bakedOp->computedState.clippedBounds.isEmpty()) {
+ // bounds are empty, so op is rejected
+ allocator.rewindIfLastAlloc(bakedOp);
+ return nullptr;
+ }
+ return bakedOp;
+ }
+
+ static void* operator new(size_t size, LinearAllocator& allocator) {
+ return allocator.alloc(size);
+ }
+
+ // computed state:
+ const ResolvedRenderState computedState;
+
+ // simple state (straight pointer/value storage):
+ const float alpha;
+ const RoundRectClipState* roundRectClipState;
+ const ProjectionPathMask* projectionPathMask;
+ const RecordedOp* op;
+
+private:
+ BakedOpState(const Snapshot& snapshot, const RecordedOp& recordedOp)
+ : computedState(snapshot, recordedOp)
+ , alpha(snapshot.alpha)
+ , roundRectClipState(snapshot.roundRectClipState)
+ , projectionPathMask(snapshot.projectionPathMask)
+ , op(&recordedOp) {}
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_BAKED_OP_STATE_H
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 0c29a9e..a1825c5 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -528,7 +528,7 @@
int insertBatchIndex = mBatches.size();
if (!mBatches.empty()) {
if (state->mBounds.isEmpty()) {
- // don't know the bounds for op, so add to last batch and start from scratch on next op
+ // don't know the bounds for op, so create new batch and start from scratch on next op
DrawBatch* b = new DrawBatch(deferInfo);
b->add(op, state, deferInfo.opaqueOverBounds);
mBatches.push_back(b);
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 7873fbd..2d5979f 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -49,7 +49,7 @@
class DeferredDisplayState {
public:
- /** static void* operator new(size_t size); PURPOSELY OMITTED **/
+ static void* operator new(size_t size) = delete;
static void* operator new(size_t size, LinearAllocator& allocator) {
return allocator.alloc(size);
}
@@ -61,7 +61,6 @@
bool mClipValid;
Rect mClip;
int mClipSideFlags; // specifies which sides of the bounds are clipped, unclipped if cleared
- bool mClipped;
mat4 mMatrix;
float mAlpha;
const RoundRectClipState* mRoundRectClipState;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index ee51da2..793d8c0 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -21,7 +21,13 @@
#include "Debug.h"
#include "DisplayList.h"
+#include "RenderNode.h"
+
+#if HWUI_NEW_OPS
+#include "RecordedOp.h"
+#else
#include "DisplayListOp.h"
+#endif
namespace android {
namespace uirenderer {
@@ -61,8 +67,8 @@
regions.clear();
}
-size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
- mReferenceHolders.push_back(op->renderNode());
+size_t DisplayListData::addChild(NodeOpType* op) {
+ mReferenceHolders.push_back(op->renderNode);
size_t index = mChildren.size();
mChildren.push_back(op);
return index;
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 0bdb816..80ff96a 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -55,12 +55,19 @@
class Rect;
class Layer;
-class ClipRectOp;
-class SaveLayerOp;
-class SaveOp;
-class RestoreToCountOp;
+#if HWUI_NEW_OPS
+struct RecordedOp;
+struct RenderNodeOp;
+
+typedef RecordedOp BaseOpType;
+typedef RenderNodeOp NodeOpType;
+#else
class DrawRenderNodeOp;
+typedef DisplayListOp BaseOpType;
+typedef DrawRenderNodeOp NodeOpType;
+#endif
+
/**
* Holds data used in the playback a tree of DisplayLists.
*/
@@ -107,6 +114,7 @@
*/
class DisplayListData {
friend class DisplayListCanvas;
+ friend class RecordingCanvas;
public:
struct Chunk {
// range of included ops in DLD::displayListOps
@@ -139,11 +147,14 @@
Vector<Functor*> functors;
const std::vector<Chunk>& getChunks() const {
- return chunks;
+ return chunks;
+ }
+ const std::vector<BaseOpType*>& getOps() const {
+ return ops;
}
- size_t addChild(DrawRenderNodeOp* childOp);
- const std::vector<DrawRenderNodeOp*>& children() { return mChildren; }
+ size_t addChild(NodeOpType* childOp);
+ const std::vector<NodeOpType*>& children() { return mChildren; }
void ref(VirtualLightRefBase* prop) {
mReferenceHolders.push_back(prop);
@@ -157,10 +168,12 @@
}
private:
+ std::vector<BaseOpType*> ops;
+
std::vector< sp<VirtualLightRefBase> > mReferenceHolders;
// list of children display lists for quick, non-drawing traversal
- std::vector<DrawRenderNodeOp*> mChildren;
+ std::vector<NodeOpType*> mChildren;
std::vector<Chunk> chunks;
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 77bde86..a1adb80 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -514,8 +514,12 @@
}
size_t DisplayListCanvas::addOpAndUpdateChunk(DisplayListOp* op) {
- int insertIndex = mDisplayListData->displayListOps.size();
- mDisplayListData->displayListOps.push_back(op);
+ int insertIndex = mDisplayListData->ops.size();
+#if HWUI_NEW_OPS
+ LOG_ALWAYS_FATAL("unsupported");
+#else
+ mDisplayListData->ops.push_back(op);
+#endif
if (mDeferredBarrierType != kBarrier_None) {
// op is first in new chunk
mDisplayListData->chunks.emplace_back();
@@ -558,16 +562,18 @@
size_t DisplayListCanvas::addRenderNodeOp(DrawRenderNodeOp* op) {
int opIndex = addDrawOp(op);
+#if !HWUI_NEW_OPS
int childIndex = mDisplayListData->addChild(op);
// update the chunk's child indices
DisplayListData::Chunk& chunk = mDisplayListData->chunks.back();
chunk.endChildIndex = childIndex + 1;
- if (op->renderNode()->stagingProperties().isProjectionReceiver()) {
+ if (op->renderNode->stagingProperties().isProjectionReceiver()) {
// use staging property, since recording on UI thread
mDisplayListData->projectionReceiveIndex = opIndex;
}
+#endif
return opIndex;
}
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index ddfc533f..1f6282d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1397,25 +1397,26 @@
class DrawRenderNodeOp : public DrawBoundedOp {
friend class RenderNode; // grant RenderNode access to info of child
friend class DisplayListData; // grant DisplayListData access to info of child
+ friend class DisplayListCanvas;
public:
DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple)
: DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), nullptr)
- , mRenderNode(renderNode)
+ , renderNode(renderNode)
, mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple())
, mTransformFromParent(transformFromParent)
, mSkipInOrderDraw(false) {}
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
bool useQuickReject) override {
- if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
- mRenderNode->defer(deferStruct, level + 1);
+ if (renderNode->isRenderable() && !mSkipInOrderDraw) {
+ renderNode->defer(deferStruct, level + 1);
}
}
virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
bool useQuickReject) override {
- if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
- mRenderNode->replay(replayStruct, level + 1);
+ if (renderNode->isRenderable() && !mSkipInOrderDraw) {
+ renderNode->replay(replayStruct, level + 1);
}
}
@@ -1424,18 +1425,16 @@
}
virtual void output(int level, uint32_t logFlags) const override {
- OP_LOG("Draw RenderNode %p %s", mRenderNode, mRenderNode->getName());
- if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
- mRenderNode->output(level + 1);
+ OP_LOG("Draw RenderNode %p %s", renderNode, renderNode->getName());
+ if (renderNode && (logFlags & kOpLogFlag_Recurse)) {
+ renderNode->output(level + 1);
}
}
virtual const char* name() override { return "DrawRenderNode"; }
- RenderNode* renderNode() { return mRenderNode; }
-
private:
- RenderNode* mRenderNode;
+ RenderNode* renderNode;
/**
* This RenderNode was drawn into a DisplayList with the canvas in a state that will likely
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index fa166ae..d2da851 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -461,12 +461,12 @@
// Transform
////////////////////////////////////////////////////////////////////////////////
-void GlopBuilder::setTransform(const Matrix4& canvas,
- const int transformFlags) {
+GlopBuilder& GlopBuilder::setTransform(const Matrix4& canvas, const int transformFlags) {
TRIGGER_STAGE(kTransformStage);
mOutGlop->transform.canvas = canvas;
mOutGlop->transform.transformFlags = transformFlags;
+ return *this;
}
////////////////////////////////////////////////////////////////////////////////
@@ -632,5 +632,42 @@
mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds);
}
+void GlopBuilder::dump(const Glop& glop) {
+ ALOGD("Glop Mesh");
+ const Glop::Mesh& mesh = glop.mesh;
+ ALOGD(" primitive mode: %d", mesh.primitiveMode);
+ ALOGD(" indices: buffer obj %x, indices %p", mesh.indices.bufferObject, mesh.indices.indices);
+
+ const Glop::Mesh::Vertices& vertices = glop.mesh.vertices;
+ ALOGD(" vertices: buffer obj %x, flags %x, pos %p, tex %p, clr %p, stride %d",
+ vertices.bufferObject, vertices.attribFlags,
+ vertices.position, vertices.texCoord, vertices.color, vertices.stride);
+ ALOGD(" element count: %d", mesh.elementCount);
+
+ ALOGD("Glop Fill");
+ const Glop::Fill& fill = glop.fill;
+ ALOGD(" program %p", fill.program);
+ if (fill.texture.texture) {
+ ALOGD(" texture %p, target %d, filter %d, clamp %d",
+ fill.texture.texture, fill.texture.target, fill.texture.filter, fill.texture.clamp);
+ if (fill.texture.textureTransform) {
+ fill.texture.textureTransform->dump("texture transform");
+ }
+ }
+ ALOGD_IF(fill.colorEnabled, " color (argb) %.2f %.2f %.2f %.2f",
+ fill.color.a, fill.color.r, fill.color.g, fill.color.b);
+ ALOGD_IF(fill.filterMode != ProgramDescription::ColorFilterMode::None,
+ " filterMode %d", (int)fill.filterMode);
+ ALOGD_IF(fill.skiaShaderData.skiaShaderType, " shader type %d",
+ fill.skiaShaderData.skiaShaderType);
+
+ ALOGD("Glop transform");
+ glop.transform.modelView.dump("model view");
+ glop.transform.canvas.dump("canvas");
+
+ ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst);
+ ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds));
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 8d05570..6f5802e 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -71,9 +71,9 @@
GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) {
- setTransform(*snapshot.transform, transformFlags);
- return *this;
+ return setTransform(*snapshot.transform, transformFlags);
}
+ GlopBuilder& setTransform(const Matrix4& canvas, const int transformFlags);
GlopBuilder& setModelViewMapUnitToRect(const Rect destination);
GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination);
@@ -98,11 +98,12 @@
GlopBuilder& setRoundRectClipState(const RoundRectClipState* roundRectClipState);
void build();
+
+ static void dump(const Glop& glop);
private:
void setFill(int color, float alphaScale,
SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
const SkShader* shader, const SkColorFilter* colorFilter);
- void setTransform(const Matrix4& canvas, const int transformFlags);
enum StageFlags {
kInitialStage = 0,
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index ed517ac..c017638 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -126,6 +126,9 @@
void loadMultiply(const Matrix4& u, const Matrix4& v);
void loadOrtho(float left, float right, float bottom, float top, float near, float far);
+ void loadOrtho(int width, int height) {
+ loadOrtho(0, width, height, 0, -1, 1);
+ }
uint8_t getType() const;
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
new file mode 100644
index 0000000..2e02306
--- /dev/null
+++ b/libs/hwui/OpReorderer.cpp
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ */
+
+#include "OpReorderer.h"
+
+#include "utils/PaintUtils.h"
+#include "RenderNode.h"
+
+#include "SkCanvas.h"
+#include "utils/Trace.h"
+
+namespace android {
+namespace uirenderer {
+
+class BatchBase {
+
+public:
+ BatchBase(batchid_t batchId, BakedOpState* op, bool merging)
+ : mBatchId(batchId)
+ , mMerging(merging) {
+ mBounds = op->computedState.clippedBounds;
+ mOps.push_back(op);
+ }
+
+ bool intersects(const Rect& rect) const {
+ if (!rect.intersects(mBounds)) return false;
+
+ for (const BakedOpState* op : mOps) {
+ if (rect.intersects(op->computedState.clippedBounds)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ batchid_t getBatchId() const { return mBatchId; }
+ bool isMerging() const { return mMerging; }
+
+ const std::vector<BakedOpState*>& getOps() const { return mOps; }
+
+ void dump() const {
+ ALOGD(" Batch %p, merging %d, bounds " RECT_STRING, this, mMerging, RECT_ARGS(mBounds));
+ }
+protected:
+ batchid_t mBatchId;
+ Rect mBounds;
+ std::vector<BakedOpState*> mOps;
+ bool mMerging;
+};
+
+class OpBatch : public BatchBase {
+public:
+ static void* operator new(size_t size, LinearAllocator& allocator) {
+ return allocator.alloc(size);
+ }
+
+ OpBatch(batchid_t batchId, BakedOpState* op)
+ : BatchBase(batchId, op, false) {
+ }
+
+ void batchOp(BakedOpState* op) {
+ mBounds.unionWith(op->computedState.clippedBounds);
+ mOps.push_back(op);
+ }
+};
+
+class MergingOpBatch : public BatchBase {
+public:
+ static void* operator new(size_t size, LinearAllocator& allocator) {
+ return allocator.alloc(size);
+ }
+
+ MergingOpBatch(batchid_t batchId, BakedOpState* op)
+ : BatchBase(batchId, op, true) {
+ }
+
+ /*
+ * Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds
+ * and clip side flags. Positive bounds delta means new bounds fit in old.
+ */
+ static inline bool checkSide(const int currentFlags, const int newFlags, const int side,
+ float boundsDelta) {
+ bool currentClipExists = currentFlags & side;
+ bool newClipExists = newFlags & side;
+
+ // if current is clipped, we must be able to fit new bounds in current
+ if (boundsDelta > 0 && currentClipExists) return false;
+
+ // if new is clipped, we must be able to fit current bounds in new
+ if (boundsDelta < 0 && newClipExists) return false;
+
+ return true;
+ }
+
+ static bool paintIsDefault(const SkPaint& paint) {
+ return paint.getAlpha() == 255
+ && paint.getColorFilter() == nullptr
+ && paint.getShader() == nullptr;
+ }
+
+ static bool paintsAreEquivalent(const SkPaint& a, const SkPaint& b) {
+ return a.getAlpha() == b.getAlpha()
+ && a.getColorFilter() == b.getColorFilter()
+ && a.getShader() == b.getShader();
+ }
+
+ /*
+ * Checks if a (mergeable) op can be merged into this batch
+ *
+ * If true, the op's multiDraw must be guaranteed to handle both ops simultaneously, so it is
+ * important to consider all paint attributes used in the draw calls in deciding both a) if an
+ * op tries to merge at all, and b) if the op can merge with another set of ops
+ *
+ * False positives can lead to information from the paints of subsequent merged operations being
+ * dropped, so we make simplifying qualifications on the ops that can merge, per op type.
+ */
+ bool canMergeWith(BakedOpState* op) const {
+ bool isTextBatch = getBatchId() == OpBatchType::Text
+ || getBatchId() == OpBatchType::ColorText;
+
+ // Overlapping other operations is only allowed for text without shadow. For other ops,
+ // multiDraw isn't guaranteed to overdraw correctly
+ if (!isTextBatch || PaintUtils::hasTextShadow(op->op->paint)) {
+ if (intersects(op->computedState.clippedBounds)) return false;
+ }
+
+ const BakedOpState* lhs = op;
+ const BakedOpState* rhs = mOps[0];
+
+ if (!MathUtils::areEqual(lhs->alpha, rhs->alpha)) return false;
+
+ // Identical round rect clip state means both ops will clip in the same way, or not at all.
+ // As the state objects are const, we can compare their pointers to determine mergeability
+ if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
+ if (lhs->projectionPathMask != rhs->projectionPathMask) return false;
+
+ /* Clipping compatibility check
+ *
+ * Exploits the fact that if a op or batch is clipped on a side, its bounds will equal its
+ * clip for that side.
+ */
+ const int currentFlags = mClipSideFlags;
+ const int newFlags = op->computedState.clipSideFlags;
+ if (currentFlags != OpClipSideFlags::None || newFlags != OpClipSideFlags::None) {
+ const Rect& opBounds = op->computedState.clippedBounds;
+ float boundsDelta = mBounds.left - opBounds.left;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Left, boundsDelta)) return false;
+ boundsDelta = mBounds.top - opBounds.top;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Top, boundsDelta)) return false;
+
+ // right and bottom delta calculation reversed to account for direction
+ boundsDelta = opBounds.right - mBounds.right;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Right, boundsDelta)) return false;
+ boundsDelta = opBounds.bottom - mBounds.bottom;
+ if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Bottom, boundsDelta)) return false;
+ }
+
+ const SkPaint* newPaint = op->op->paint;
+ const SkPaint* oldPaint = mOps[0]->op->paint;
+
+ if (newPaint == oldPaint) {
+ // if paints are equal, then modifiers + paint attribs don't need to be compared
+ return true;
+ } else if (newPaint && !oldPaint) {
+ return paintIsDefault(*newPaint);
+ } else if (!newPaint && oldPaint) {
+ return paintIsDefault(*oldPaint);
+ }
+ return paintsAreEquivalent(*newPaint, *oldPaint);
+ }
+
+ void mergeOp(BakedOpState* op) {
+ mBounds.unionWith(op->computedState.clippedBounds);
+ mOps.push_back(op);
+
+ const int newClipSideFlags = op->computedState.clipSideFlags;
+ mClipSideFlags |= newClipSideFlags;
+
+ const Rect& opClip = op->computedState.clipRect;
+ if (newClipSideFlags & OpClipSideFlags::Left) mClipRect.left = opClip.left;
+ if (newClipSideFlags & OpClipSideFlags::Top) mClipRect.top = opClip.top;
+ if (newClipSideFlags & OpClipSideFlags::Right) mClipRect.right = opClip.right;
+ if (newClipSideFlags & OpClipSideFlags::Bottom) mClipRect.bottom = opClip.bottom;
+ }
+
+private:
+ int mClipSideFlags = 0;
+ Rect mClipRect;
+};
+
+class NullClient: public CanvasStateClient {
+ void onViewportInitialized() override {}
+ void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
+ GLuint getTargetFbo() const override { return 0; }
+};
+static NullClient sNullClient;
+
+OpReorderer::OpReorderer()
+ : mCanvasState(sNullClient) {
+}
+
+void OpReorderer::defer(const SkRect& clip, int viewportWidth, int viewportHeight,
+ const std::vector< sp<RenderNode> >& nodes) {
+ mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
+ clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
+ Vector3());
+ for (const sp<RenderNode>& node : nodes) {
+ if (node->nothingToDraw()) continue;
+
+ // TODO: dedupe this code with onRenderNode()
+ mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
+ if (node->applyViewProperties(mCanvasState)) {
+ // not rejected do ops...
+ const DisplayListData& data = node->getDisplayListData();
+ deferImpl(data.getChunks(), data.getOps());
+ }
+ mCanvasState.restore();
+ }
+}
+
+void OpReorderer::defer(int viewportWidth, int viewportHeight,
+ const std::vector<DisplayListData::Chunk>& chunks, const std::vector<RecordedOp*>& ops) {
+ ATRACE_NAME("prepare drawing commands");
+ mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
+ 0, 0, viewportWidth, viewportHeight, Vector3());
+ deferImpl(chunks, ops);
+}
+
+/**
+ * Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods.
+ *
+ * This allows opIds embedded in the RecordedOps to be used for dispatching to these lambdas. E.g. a
+ * BitmapOp op then would be dispatched to OpReorderer::onBitmapOp(const BitmapOp&)
+ */
+#define OP_RECIEVER(Type) \
+ [](OpReorderer& reorderer, const RecordedOp& op) { reorderer.on##Type(static_cast<const Type&>(op)); },
+void OpReorderer::deferImpl(const std::vector<DisplayListData::Chunk>& chunks,
+ const std::vector<RecordedOp*>& ops) {
+ static std::function<void(OpReorderer& reorderer, const RecordedOp&)> receivers[] = {
+ MAP_OPS(OP_RECIEVER)
+ };
+ for (const DisplayListData::Chunk& chunk : chunks) {
+ for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
+ const RecordedOp* op = ops[opIndex];
+ receivers[op->opId](*this, *op);
+ }
+ }
+}
+
+void OpReorderer::replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers) {
+ ATRACE_NAME("flush drawing commands");
+ for (const BatchBase* batch : mBatches) {
+ // TODO: different behavior based on batch->isMerging()
+ for (const BakedOpState* op : batch->getOps()) {
+ receivers[op->op->opId](arg, *op->op, *op);
+ }
+ }
+}
+
+BakedOpState* OpReorderer::bakeOpState(const RecordedOp& recordedOp) {
+ return BakedOpState::tryConstruct(mAllocator, *mCanvasState.currentSnapshot(), recordedOp);
+}
+
+void OpReorderer::onRenderNodeOp(const RenderNodeOp& op) {
+ if (op.renderNode->nothingToDraw()) {
+ return;
+ }
+ mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
+
+ // apply state from RecordedOp
+ mCanvasState.concatMatrix(op.localMatrix);
+ mCanvasState.clipRect(op.localClipRect.left, op.localClipRect.top,
+ op.localClipRect.right, op.localClipRect.bottom, SkRegion::kIntersect_Op);
+
+ // apply RenderProperties state
+ if (op.renderNode->applyViewProperties(mCanvasState)) {
+ // not rejected do ops...
+ const DisplayListData& data = op.renderNode->getDisplayListData();
+ deferImpl(data.getChunks(), data.getOps());
+ }
+ mCanvasState.restore();
+}
+
+static batchid_t tessellatedBatchId(const SkPaint& paint) {
+ return paint.getPathEffect()
+ ? OpBatchType::AlphaMaskTexture
+ : (paint.isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices);
+}
+
+void OpReorderer::onBitmapOp(const BitmapOp& op) {
+ BakedOpState* bakedStateOp = bakeOpState(op);
+ if (!bakedStateOp) return; // quick rejected
+
+ mergeid_t mergeId = (mergeid_t) op.bitmap->getGenerationID();
+ // TODO: AssetAtlas
+
+ deferMergeableOp(bakedStateOp, OpBatchType::Bitmap, mergeId);
+}
+
+void OpReorderer::onRectOp(const RectOp& op) {
+ BakedOpState* bakedStateOp = bakeOpState(op);
+ if (!bakedStateOp) return; // quick rejected
+ deferUnmergeableOp(bakedStateOp, tessellatedBatchId(*op.paint));
+}
+
+void OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) {
+ BakedOpState* bakedStateOp = bakeOpState(op);
+ if (!bakedStateOp) return; // quick rejected
+ deferUnmergeableOp(bakedStateOp, OpBatchType::Vertices);
+}
+
+// iterate back toward target to see if anything drawn since should overlap the new op
+// if no target, merging ops still interate to find similar batch to insert after
+void OpReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds,
+ BatchBase** targetBatch, size_t* insertBatchIndex) const {
+ for (int i = mBatches.size() - 1; i >= mEarliestBatchIndex; i--) {
+ BatchBase* overBatch = mBatches[i];
+
+ if (overBatch == *targetBatch) break;
+
+ // TODO: also consider shader shared between batch types
+ if (batchId == overBatch->getBatchId()) {
+ *insertBatchIndex = i + 1;
+ if (!*targetBatch) break; // found insert position, quit
+ }
+
+ if (overBatch->intersects(clippedBounds)) {
+ // NOTE: it may be possible to optimize for special cases where two operations
+ // of the same batch/paint could swap order, such as with a non-mergeable
+ // (clipped) and a mergeable text operation
+ *targetBatch = nullptr;
+ break;
+ }
+ }
+}
+
+void OpReorderer::deferUnmergeableOp(BakedOpState* op, batchid_t batchId) {
+ OpBatch* targetBatch = mBatchLookup[batchId];
+
+ size_t insertBatchIndex = mBatches.size();
+ if (targetBatch) {
+ locateInsertIndex(batchId, op->computedState.clippedBounds,
+ (BatchBase**)(&targetBatch), &insertBatchIndex);
+ }
+
+ if (targetBatch) {
+ targetBatch->batchOp(op);
+ } else {
+ // new non-merging batch
+ targetBatch = new (mAllocator) OpBatch(batchId, op);
+ mBatchLookup[batchId] = targetBatch;
+ mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
+ }
+}
+
+// insertion point of a new batch, will hopefully be immediately after similar batch
+// (generally, should be similar shader)
+void OpReorderer::deferMergeableOp(BakedOpState* op, batchid_t batchId, mergeid_t mergeId) {
+ MergingOpBatch* targetBatch = nullptr;
+
+ // Try to merge with any existing batch with same mergeId
+ auto getResult = mMergingBatches[batchId].find(mergeId);
+ if (getResult != mMergingBatches[batchId].end()) {
+ targetBatch = getResult->second;
+ if (!targetBatch->canMergeWith(op)) {
+ targetBatch = nullptr;
+ }
+ }
+
+ size_t insertBatchIndex = mBatches.size();
+ locateInsertIndex(batchId, op->computedState.clippedBounds,
+ (BatchBase**)(&targetBatch), &insertBatchIndex);
+
+ if (targetBatch) {
+ targetBatch->mergeOp(op);
+ } else {
+ // new merging batch
+ targetBatch = new (mAllocator) MergingOpBatch(batchId, op);
+ mMergingBatches[batchId].insert(std::make_pair(mergeId, targetBatch));
+
+ mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
+ }
+}
+
+void OpReorderer::dump() {
+ for (const BatchBase* batch : mBatches) {
+ batch->dump();
+ }
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
new file mode 100644
index 0000000..395a1ba
--- /dev/null
+++ b/libs/hwui/OpReorderer.h
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_OP_REORDERER_H
+#define ANDROID_HWUI_OP_REORDERER_H
+
+#include "BakedOpState.h"
+#include "CanvasState.h"
+#include "DisplayList.h"
+#include "RecordedOp.h"
+
+#include <vector>
+#include <unordered_map>
+
+struct SkRect;
+
+namespace android {
+namespace uirenderer {
+
+class BakedOpState;
+class BatchBase;
+class MergingOpBatch;
+class OpBatch;
+class Rect;
+
+typedef int batchid_t;
+typedef const void* mergeid_t;
+
+namespace OpBatchType {
+ enum {
+ None = 0, // Don't batch
+ Bitmap,
+ Patch,
+ AlphaVertices,
+ Vertices,
+ AlphaMaskTexture,
+ Text,
+ ColorText,
+
+ Count // must be last
+ };
+}
+
+class OpReorderer {
+public:
+ OpReorderer();
+
+ // TODO: not final, just presented this way for simplicity. Layers too?
+ void defer(const SkRect& clip, int viewportWidth, int viewportHeight,
+ const std::vector< sp<RenderNode> >& nodes);
+
+ void defer(int viewportWidth, int viewportHeight,
+ const std::vector<DisplayListData::Chunk>& chunks, const std::vector<RecordedOp*>& ops);
+ typedef std::function<void(void*, const RecordedOp&, const BakedOpState&)> BakedOpReceiver;
+
+ /**
+ * replayBakedOps() is templated based on what class will recieve ops being replayed.
+ *
+ * It constructs a lookup array of lambdas, which allows a recorded BakeOpState to use
+ * state->op->opId to lookup a receiver that will be called when the op is replayed.
+ *
+ * For example a BitmapOp would resolve, via the lambda lookup, to calling:
+ *
+ * StaticReceiver::onBitmapOp(Arg* arg, const BitmapOp& op, const BakedOpState& state);
+ */
+#define BAKED_OP_RECEIVER(Type) \
+ [](void* internalArg, const RecordedOp& op, const BakedOpState& state) { \
+ StaticReceiver::on##Type(static_cast<Arg*>(internalArg), static_cast<const Type&>(op), state); \
+ },
+ template <typename StaticReceiver, typename Arg>
+ void replayBakedOps(Arg* arg) {
+ static BakedOpReceiver receivers[] = {
+ MAP_OPS(BAKED_OP_RECEIVER)
+ };
+ StaticReceiver::startFrame(*arg);
+ replayBakedOpsImpl((void*)arg, receivers);
+ StaticReceiver::endFrame(*arg);
+ }
+private:
+ BakedOpState* bakeOpState(const RecordedOp& recordedOp);
+
+ void deferImpl(const std::vector<DisplayListData::Chunk>& chunks,
+ const std::vector<RecordedOp*>& ops);
+
+ void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers);
+
+ /**
+ * Declares all OpReorderer::onXXXXOp() methods for every RecordedOp type.
+ *
+ * These private methods are called from within deferImpl to defer each individual op
+ * type differently.
+ */
+#define INTERNAL_OP_HANDLER(Type) \
+ void on##Type(const Type& op);
+ MAP_OPS(INTERNAL_OP_HANDLER)
+
+ // iterate back toward target to see if anything drawn since should overlap the new op
+ // if no target, merging ops still iterate to find similar batch to insert after
+ void locateInsertIndex(int batchId, const Rect& clippedBounds,
+ BatchBase** targetBatch, size_t* insertBatchIndex) const;
+
+ void deferUnmergeableOp(BakedOpState* op, batchid_t batchId);
+
+ // insertion point of a new batch, will hopefully be immediately after similar batch
+ // (generally, should be similar shader)
+ void deferMergeableOp(BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
+
+ void dump();
+
+ std::vector<BatchBase*> mBatches;
+
+ /**
+ * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
+ * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
+ * collide, which avoids the need to resolve mergeid collisions.
+ */
+ std::unordered_map<mergeid_t, MergingOpBatch*> mMergingBatches[OpBatchType::Count];
+
+ // Maps batch ids to the most recent *non-merging* batch of that id
+ OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };
+ CanvasState mCanvasState;
+
+ // contains ResolvedOps and Batches
+ LinearAllocator mAllocator;
+
+ int mEarliestBatchIndex = 0;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_OP_REORDERER_H
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
new file mode 100644
index 0000000..a69f030
--- /dev/null
+++ b/libs/hwui/RecordedOp.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_RECORDED_OP_H
+#define ANDROID_HWUI_RECORDED_OP_H
+
+#include "utils/LinearAllocator.h"
+#include "Rect.h"
+#include "Matrix.h"
+
+#include "SkXfermode.h"
+
+class SkBitmap;
+class SkPaint;
+
+namespace android {
+namespace uirenderer {
+
+class RenderNode;
+struct Vertex;
+
+/**
+ * The provided macro is executed for each op type in order, with the results separated by commas.
+ *
+ * This serves as the authoritative list of ops, used for generating ID enum, and ID based LUTs.
+ */
+#define MAP_OPS(OP_FN) \
+ OP_FN(BitmapOp) \
+ OP_FN(RectOp) \
+ OP_FN(RenderNodeOp) \
+ OP_FN(SimpleRectsOp)
+
+// Generate OpId enum
+#define IDENTITY_FN(Type) Type,
+namespace RecordedOpId {
+ enum {
+ MAP_OPS(IDENTITY_FN)
+ Count,
+ };
+}
+static_assert(RecordedOpId::BitmapOp == 0,
+ "First index must be zero for LUTs to work");
+
+#define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect, const SkPaint* paint
+#define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect
+#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, paint)
+#define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, nullptr)
+
+struct RecordedOp {
+ /* ID from RecordedOpId - generally used for jumping into function tables */
+ const int opId;
+
+ /* bounds in *local* space, without accounting for DisplayList transformation */
+ const Rect unmappedBounds;
+
+ /* transform in recording space (vs DisplayList origin) */
+ const Matrix4 localMatrix;
+
+ /* clip in recording space */
+ const Rect localClipRect;
+
+ /* optional paint, stored in base object to simplify merging logic */
+ const SkPaint* paint;
+protected:
+ RecordedOp(unsigned int opId, BASE_PARAMS)
+ : opId(opId)
+ , unmappedBounds(unmappedBounds)
+ , localMatrix(localMatrix)
+ , localClipRect(localClipRect)
+ , paint(paint) {}
+};
+
+struct RenderNodeOp : RecordedOp {
+ RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
+ : SUPER_PAINTLESS(RenderNodeOp)
+ , renderNode(renderNode) {}
+ RenderNode * renderNode; // not const, since drawing modifies it (somehow...)
+};
+
+struct BitmapOp : RecordedOp {
+ BitmapOp(BASE_PARAMS, const SkBitmap* bitmap)
+ : SUPER(BitmapOp)
+ , bitmap(bitmap) {}
+ const SkBitmap* bitmap;
+ // TODO: asset atlas/texture id lookup?
+};
+
+struct RectOp : RecordedOp {
+ RectOp(BASE_PARAMS)
+ : SUPER(RectOp) {}
+};
+
+struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
+ SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
+ : SUPER(SimpleRectsOp)
+ , vertices(vertices)
+ , vertexCount(vertexCount) {}
+ Vertex* vertices;
+ const size_t vertexCount;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_RECORDED_OP_H
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
new file mode 100644
index 0000000..c4debd6
--- /dev/null
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -0,0 +1,402 @@
+/*
+ * 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.
+ */
+
+#include "RecordingCanvas.h"
+
+#include "RecordedOp.h"
+#include "RenderNode.h"
+
+namespace android {
+namespace uirenderer {
+
+RecordingCanvas::RecordingCanvas(size_t width, size_t height)
+ : mState(*this)
+ , mResourceCache(ResourceCache::getInstance()) {
+ reset(width, height);
+}
+
+RecordingCanvas::~RecordingCanvas() {
+ LOG_ALWAYS_FATAL_IF(mDisplayListData,
+ "Destroyed a RecordingCanvas during a record!");
+}
+
+void RecordingCanvas::reset(int width, int height) {
+ LOG_ALWAYS_FATAL_IF(mDisplayListData,
+ "prepareDirty called a second time during a recording!");
+ mDisplayListData = new DisplayListData();
+
+ mState.initializeSaveStack(width, height, 0, 0, width, height, Vector3());
+
+ mDeferredBarrierType = kBarrier_InOrder;
+ mState.setDirtyClip(false);
+ mRestoreSaveCount = -1;
+}
+
+DisplayListData* RecordingCanvas::finishRecording() {
+ mPaintMap.clear();
+ mRegionMap.clear();
+ mPathMap.clear();
+ DisplayListData* data = mDisplayListData;
+ mDisplayListData = nullptr;
+ mSkiaCanvasProxy.reset(nullptr);
+ return data;
+}
+
+SkCanvas* RecordingCanvas::asSkCanvas() {
+ LOG_ALWAYS_FATAL_IF(!mDisplayListData,
+ "attempting to get an SkCanvas when we are not recording!");
+ if (!mSkiaCanvasProxy) {
+ mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
+ }
+
+ // SkCanvas instances default to identity transform, but should inherit
+ // the state of this Canvas; if this code was in the SkiaCanvasProxy
+ // constructor, we couldn't cache mSkiaCanvasProxy.
+ SkMatrix parentTransform;
+ getMatrix(&parentTransform);
+ mSkiaCanvasProxy.get()->setMatrix(parentTransform);
+
+ return mSkiaCanvasProxy.get();
+}
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas state operations
+// ----------------------------------------------------------------------------
+// Save (layer)
+int RecordingCanvas::save(SkCanvas::SaveFlags flags) {
+ return mState.save((int) flags);
+}
+
+void RecordingCanvas::RecordingCanvas::restore() {
+ if (mRestoreSaveCount < 0) {
+ restoreToCount(getSaveCount() - 1);
+ return;
+ }
+
+ mRestoreSaveCount--;
+ mState.restore();
+}
+
+void RecordingCanvas::restoreToCount(int saveCount) {
+ mRestoreSaveCount = saveCount;
+ mState.restoreToCount(saveCount);
+}
+
+int RecordingCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+ SkCanvas::SaveFlags flags) {
+ LOG_ALWAYS_FATAL("TODO");
+ return 0;
+}
+
+// Matrix
+void RecordingCanvas::rotate(float degrees) {
+ if (degrees == 0) return;
+
+ mState.rotate(degrees);
+}
+
+void RecordingCanvas::scale(float sx, float sy) {
+ if (sx == 1 && sy == 1) return;
+
+ mState.scale(sx, sy);
+}
+
+void RecordingCanvas::skew(float sx, float sy) {
+ mState.skew(sx, sy);
+}
+
+void RecordingCanvas::translate(float dx, float dy) {
+ if (dx == 0 && dy == 0) return;
+
+ mState.translate(dx, dy, 0);
+}
+
+// Clip
+bool RecordingCanvas::getClipBounds(SkRect* outRect) const {
+ Rect bounds = mState.getLocalClipBounds();
+ *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ return !(outRect->isEmpty());
+}
+bool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
+ return mState.quickRejectConservative(left, top, right, bottom);
+}
+bool RecordingCanvas::quickRejectPath(const SkPath& path) const {
+ SkRect bounds = path.getBounds();
+ return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
+}
+bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+ return mState.clipRect(left, top, right, bottom, op);
+}
+bool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
+ return mState.clipPath(path, op);
+}
+bool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
+ return mState.clipRegion(region, op);
+}
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas draw operations
+// ----------------------------------------------------------------------------
+void RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setXfermodeMode(mode);
+ drawPaint(paint);
+}
+
+void RecordingCanvas::drawPaint(const SkPaint& paint) {
+ // TODO: more efficient recording?
+ Matrix4 identity;
+ identity.loadIdentity();
+
+ addOp(new (alloc()) RectOp(
+ mState.getRenderTargetClipBounds(),
+ identity,
+ mState.getRenderTargetClipBounds(),
+ refPaint(&paint)));
+}
+
+// Geometry
+void RecordingCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
+ addOp(new (alloc()) RectOp(
+ Rect(left, top, right, bottom),
+ *(mState.currentSnapshot()->transform),
+ mState.getRenderTargetClipBounds(),
+ refPaint(&paint)));
+}
+
+void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
+ if (rects == nullptr) return;
+
+ Vertex* rectData = (Vertex*) mDisplayListData->allocator.alloc(vertexCount * sizeof(Vertex));
+ Vertex* vertex = rectData;
+
+ float left = FLT_MAX;
+ float top = FLT_MAX;
+ float right = FLT_MIN;
+ float bottom = FLT_MIN;
+ for (int index = 0; index < vertexCount; index += 4) {
+ float l = rects[index + 0];
+ float t = rects[index + 1];
+ float r = rects[index + 2];
+ float b = rects[index + 3];
+
+ Vertex::set(vertex++, l, t);
+ Vertex::set(vertex++, r, t);
+ Vertex::set(vertex++, l, b);
+ Vertex::set(vertex++, r, b);
+
+ left = std::min(left, l);
+ top = std::min(top, t);
+ right = std::max(right, r);
+ bottom = std::max(bottom, b);
+ }
+ addOp(new (alloc()) SimpleRectsOp(
+ Rect(left, top, right, bottom),
+ *(mState.currentSnapshot()->transform),
+ mState.getRenderTargetClipBounds(),
+ refPaint(paint), rectData, vertexCount));
+}
+
+void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
+ if (paint.getStyle() == SkPaint::kFill_Style
+ && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
+ int count = 0;
+ Vector<float> rects;
+ SkRegion::Iterator it(region);
+ while (!it.done()) {
+ const SkIRect& r = it.rect();
+ rects.push(r.fLeft);
+ rects.push(r.fTop);
+ rects.push(r.fRight);
+ rects.push(r.fBottom);
+ count += 4;
+ it.next();
+ }
+ drawSimpleRects(rects.array(), count, &paint);
+ } else {
+ SkRegion::Iterator it(region);
+ while (!it.done()) {
+ const SkIRect& r = it.rect();
+ drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
+ it.next();
+ }
+ }
+}
+void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
+ float rx, float ry, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
+ float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+
+// Bitmap-based
+void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
+ save(SkCanvas::kMatrix_SaveFlag);
+ translate(left, top);
+ drawBitmap(&bitmap, paint);
+ restore();
+}
+
+void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+ const SkPaint* paint) {
+ if (matrix.isIdentity()) {
+ drawBitmap(&bitmap, paint);
+ } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
+ && MathUtils::isPositive(matrix.getScaleX())
+ && MathUtils::isPositive(matrix.getScaleY())) {
+ // SkMatrix::isScaleTranslate() not available in L
+ SkRect src;
+ SkRect dst;
+ bitmap.getBounds(&src);
+ matrix.mapRect(&dst, src);
+ drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
+ dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+ } else {
+ save(SkCanvas::kMatrix_SaveFlag);
+ concat(matrix);
+ drawBitmap(&bitmap, paint);
+ restore();
+ }
+}
+void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+ float srcRight, float srcBottom, float dstLeft, float dstTop,
+ float dstRight, float dstBottom, const SkPaint* paint) {
+ if (srcLeft == 0 && srcTop == 0
+ && srcRight == bitmap.width()
+ && srcBottom == bitmap.height()
+ && (srcBottom - srcTop == dstBottom - dstTop)
+ && (srcRight - srcLeft == dstRight - dstLeft)) {
+ // transform simple rect to rect drawing case into position bitmap ops, since they merge
+ save(SkCanvas::kMatrix_SaveFlag);
+ translate(dstLeft, dstTop);
+ drawBitmap(&bitmap, paint);
+ restore();
+ } else {
+ LOG_ALWAYS_FATAL("TODO!");
+ }
+}
+void RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+ const float* vertices, const int* colors, const SkPaint* paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+
+// Text
+void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int count,
+ const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
+ float boundsRight, float boundsBottom, float totalAdvance) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawPosText(const uint16_t* text, const float* positions, int count,
+ int posCount, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+ float hOffset, float vOffset, const SkPaint& paint) {
+ LOG_ALWAYS_FATAL("TODO!");
+}
+
+void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
+ addOp(new (alloc()) BitmapOp(
+ Rect(0, 0, bitmap->width(), bitmap->height()),
+ *(mState.currentSnapshot()->transform),
+ mState.getRenderTargetClipBounds(),
+ refPaint(paint), refBitmap(*bitmap)));
+}
+void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
+ RenderNodeOp* op = new (alloc()) RenderNodeOp(
+ Rect(0, 0, renderNode->getWidth(), renderNode->getHeight()), // are these safe? they're theoretically dynamic
+ *(mState.currentSnapshot()->transform),
+ mState.getRenderTargetClipBounds(),
+ renderNode);
+ int opIndex = addOp(op);
+ int childIndex = mDisplayListData->addChild(op);
+
+ // update the chunk's child indices
+ DisplayListData::Chunk& chunk = mDisplayListData->chunks.back();
+ chunk.endChildIndex = childIndex + 1;
+
+ if (renderNode->stagingProperties().isProjectionReceiver()) {
+ // use staging property, since recording on UI thread
+ mDisplayListData->projectionReceiveIndex = opIndex;
+ }
+}
+
+size_t RecordingCanvas::addOp(RecordedOp* op) {
+ // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
+ int insertIndex = mDisplayListData->ops.size();
+ mDisplayListData->ops.push_back(op);
+ if (mDeferredBarrierType != kBarrier_None) {
+ // op is first in new chunk
+ mDisplayListData->chunks.emplace_back();
+ DisplayListData::Chunk& newChunk = mDisplayListData->chunks.back();
+ newChunk.beginOpIndex = insertIndex;
+ newChunk.endOpIndex = insertIndex + 1;
+ newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
+
+ int nextChildIndex = mDisplayListData->children().size();
+ newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
+ mDeferredBarrierType = kBarrier_None;
+ } else {
+ // standard case - append to existing chunk
+ mDisplayListData->chunks.back().endOpIndex = insertIndex + 1;
+ }
+ return insertIndex;
+}
+
+void RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
+ if (!shader) return;
+
+ // If this paint has an SkShader that has an SkBitmap add
+ // it to the bitmap pile
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader->asABitmap(&bitmap, nullptr, xy) == SkShader::kDefault_BitmapType) {
+ refBitmap(bitmap);
+ return;
+ }
+ SkShader::ComposeRec rec;
+ if (shader->asACompose(&rec)) {
+ refBitmapsInShader(rec.fShaderA);
+ refBitmapsInShader(rec.fShaderB);
+ return;
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
new file mode 100644
index 0000000..ed299e5
--- /dev/null
+++ b/libs/hwui/RecordingCanvas.h
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_RECORDING_CANVAS_H
+#define ANDROID_HWUI_RECORDING_CANVAS_H
+
+#include "Canvas.h"
+#include "CanvasState.h"
+#include "DisplayList.h"
+#include "utils/LinearAllocator.h"
+#include "utils/NinePatch.h"
+#include "ResourceCache.h"
+#include "SkiaCanvasProxy.h"
+#include "Snapshot.h"
+
+#include "SkDrawFilter.h"
+#include <vector>
+
+namespace android {
+namespace uirenderer {
+
+class OpReceiver;
+struct RecordedOp;
+
+class RecordingCanvas: public Canvas, public CanvasStateClient {
+public:
+ RecordingCanvas(size_t width, size_t height);
+ virtual ~RecordingCanvas();
+
+ void reset(int width, int height);
+ DisplayListData* finishRecording();
+
+// ----------------------------------------------------------------------------
+// MISC HWUI OPERATIONS - TODO: CATEGORIZE
+// ----------------------------------------------------------------------------
+ void insertReorderBarrier(bool enableReorder) {}
+ void drawRenderNode(RenderNode* renderNode);
+
+// ----------------------------------------------------------------------------
+// CanvasStateClient interface
+// ----------------------------------------------------------------------------
+ virtual void onViewportInitialized() override {}
+ virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override {}
+ virtual GLuint getTargetFbo() const override { return -1; }
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas interface
+// ----------------------------------------------------------------------------
+ virtual SkCanvas* asSkCanvas() override;
+
+ virtual void setBitmap(const SkBitmap& bitmap) override {
+ LOG_ALWAYS_FATAL("RecordingCanvas is not backed by a bitmap.");
+ }
+
+ virtual bool isOpaque() override { return false; }
+ virtual int width() override { return mState.getWidth(); }
+ virtual int height() override { return mState.getHeight(); }
+
+ virtual void setHighContrastText(bool highContrastText) override {
+ mHighContrastText = highContrastText;
+ }
+ virtual bool isHighContrastText() override { return mHighContrastText; }
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas state operations
+// ----------------------------------------------------------------------------
+ // Save (layer)
+ virtual int getSaveCount() const override { return mState.getSaveCount(); }
+ virtual int save(SkCanvas::SaveFlags flags) override;
+ virtual void restore() override;
+ virtual void restoreToCount(int saveCount) override;
+
+ virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+ SkCanvas::SaveFlags flags) override;
+ virtual int saveLayerAlpha(float left, float top, float right, float bottom,
+ int alpha, SkCanvas::SaveFlags flags) override {
+ SkPaint paint;
+ paint.setAlpha(alpha);
+ return saveLayer(left, top, right, bottom, &paint, flags);
+ }
+
+ // Matrix
+ virtual void getMatrix(SkMatrix* outMatrix) const override { mState.getMatrix(outMatrix); }
+ virtual void setMatrix(const SkMatrix& matrix) override { mState.setMatrix(matrix); }
+
+ virtual void concat(const SkMatrix& matrix) override { mState.concatMatrix(matrix); }
+ virtual void rotate(float degrees) override;
+ virtual void scale(float sx, float sy) override;
+ virtual void skew(float sx, float sy) override;
+ virtual void translate(float dx, float dy) override;
+
+ // Clip
+ virtual bool getClipBounds(SkRect* outRect) const override;
+ virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
+ virtual bool quickRejectPath(const SkPath& path) const override;
+
+ virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) override;
+ virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
+ virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
+
+ // Misc
+ virtual SkDrawFilter* getDrawFilter() override { return mDrawFilter.get(); }
+ virtual void setDrawFilter(SkDrawFilter* filter) override {
+ mDrawFilter.reset(SkSafeRef(filter));
+ }
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas draw operations
+// ----------------------------------------------------------------------------
+ virtual void drawColor(int color, SkXfermode::Mode mode) override;
+ virtual void drawPaint(const SkPaint& paint) override;
+
+ // Geometry
+ virtual void drawPoint(float x, float y, const SkPaint& paint) override {
+ float points[2] = { x, y };
+ drawPoints(points, 2, paint);
+ }
+ virtual void drawPoints(const float* points, int count, const SkPaint& paint) override;
+ virtual void drawLine(float startX, float startY, float stopX, float stopY,
+ const SkPaint& paint) override {
+ float points[4] = { startX, startY, stopX, stopY };
+ drawLines(points, 4, paint);
+ }
+ virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
+ virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
+ virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override;
+ virtual void drawRoundRect(float left, float top, float right, float bottom,
+ float rx, float ry, const SkPaint& paint) override;
+ virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
+ virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint) override;
+ virtual void drawArc(float left, float top, float right, float bottom,
+ float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override;
+ virtual void drawPath(const SkPath& path, const SkPaint& paint) override;
+ virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
+ const float* verts, const float* tex, const int* colors,
+ const uint16_t* indices, int indexCount, const SkPaint& paint) override
+ { /* RecordingCanvas does not support drawVertices(); ignore */ }
+
+ // Bitmap-based
+ virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) override;
+ virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+ const SkPaint* paint) override;
+ virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+ float srcRight, float srcBottom, float dstLeft, float dstTop,
+ float dstRight, float dstBottom, const SkPaint* paint) override;
+ virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+ const float* vertices, const int* colors, const SkPaint* paint) override;
+ virtual void drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ const SkPaint* paint) override;
+
+ // Text
+ virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
+ const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
+ float boundsRight, float boundsBottom, float totalAdvance) override;
+ virtual void drawPosText(const uint16_t* text, const float* positions, int count,
+ int posCount, const SkPaint& paint) override;
+ virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+ float hOffset, float vOffset, const SkPaint& paint) override;
+ virtual bool drawTextAbsolutePos() const override { return false; }
+
+private:
+ enum DeferredBarrierType {
+ kBarrier_None,
+ kBarrier_InOrder,
+ kBarrier_OutOfOrder,
+ };
+
+ void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
+ void drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint);
+
+
+ size_t addOp(RecordedOp* op);
+// ----------------------------------------------------------------------------
+// lazy object copy
+// ----------------------------------------------------------------------------
+ LinearAllocator& alloc() { return mDisplayListData->allocator; }
+
+ void refBitmapsInShader(const SkShader* shader);
+
+ template<class T>
+ inline const T* refBuffer(const T* srcBuffer, int32_t count) {
+ if (!srcBuffer) return nullptr;
+
+ T* dstBuffer = (T*) mDisplayListData->allocator.alloc(count * sizeof(T));
+ memcpy(dstBuffer, srcBuffer, count * sizeof(T));
+ return dstBuffer;
+ }
+
+ inline char* refText(const char* text, size_t byteLength) {
+ return (char*) refBuffer<uint8_t>((uint8_t*)text, byteLength);
+ }
+
+ inline const SkPath* refPath(const SkPath* path) {
+ if (!path) return nullptr;
+
+ // The points/verbs within the path are refcounted so this copy operation
+ // is inexpensive and maintains the generationID of the original path.
+ const SkPath* cachedPath = new SkPath(*path);
+ mDisplayListData->pathResources.push_back(cachedPath);
+ return cachedPath;
+ }
+
+ inline const SkPaint* refPaint(const SkPaint* paint) {
+ if (!paint) return nullptr;
+
+ // If there is a draw filter apply it here and store the modified paint
+ // so that we don't need to modify the paint every time we access it.
+ SkTLazy<SkPaint> filteredPaint;
+ if (mDrawFilter.get()) {
+ filteredPaint.set(*paint);
+ mDrawFilter->filter(filteredPaint.get(), SkDrawFilter::kPaint_Type);
+ paint = filteredPaint.get();
+ }
+
+ // compute the hash key for the paint and check the cache.
+ const uint32_t key = paint->getHash();
+ const SkPaint* cachedPaint = mPaintMap.valueFor(key);
+ // In the unlikely event that 2 unique paints have the same hash we do a
+ // object equality check to ensure we don't erroneously dedup them.
+ if (cachedPaint == nullptr || *cachedPaint != *paint) {
+ cachedPaint = new SkPaint(*paint);
+ std::unique_ptr<const SkPaint> copy(cachedPaint);
+ mDisplayListData->paints.push_back(std::move(copy));
+
+ // replaceValueFor() performs an add if the entry doesn't exist
+ mPaintMap.replaceValueFor(key, cachedPaint);
+ refBitmapsInShader(cachedPaint->getShader());
+ }
+
+ return cachedPaint;
+ }
+
+ inline const SkRegion* refRegion(const SkRegion* region) {
+ if (!region) {
+ return region;
+ }
+
+ const SkRegion* cachedRegion = mRegionMap.valueFor(region);
+ // TODO: Add generation ID to SkRegion
+ if (cachedRegion == nullptr) {
+ std::unique_ptr<const SkRegion> copy(new SkRegion(*region));
+ cachedRegion = copy.get();
+ mDisplayListData->regions.push_back(std::move(copy));
+
+ // replaceValueFor() performs an add if the entry doesn't exist
+ mRegionMap.replaceValueFor(region, cachedRegion);
+ }
+
+ return cachedRegion;
+ }
+
+ inline const SkBitmap* refBitmap(const SkBitmap& bitmap) {
+ // Note that this assumes the bitmap is immutable. There are cases this won't handle
+ // correctly, such as creating the bitmap from scratch, drawing with it, changing its
+ // contents, and drawing again. The only fix would be to always copy it the first time,
+ // which doesn't seem worth the extra cycles for this unlikely case.
+ SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
+ alloc().autoDestroy(localBitmap);
+ mDisplayListData->bitmapResources.push_back(localBitmap);
+ return localBitmap;
+ }
+
+ inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
+ mDisplayListData->patchResources.push_back(patch);
+ mResourceCache.incrementRefcount(patch);
+ return patch;
+ }
+
+ DefaultKeyedVector<uint32_t, const SkPaint*> mPaintMap;
+ DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
+ DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
+
+ CanvasState mState;
+ std::unique_ptr<SkiaCanvasProxy> mSkiaCanvasProxy;
+ ResourceCache& mResourceCache;
+ DeferredBarrierType mDeferredBarrierType = kBarrier_None;
+ DisplayListData* mDisplayListData = nullptr;
+ bool mHighContrastText = false;
+ SkAutoTUnref<SkDrawFilter> mDrawFilter;
+ int mRestoreSaveCount = -1;
+}; // class RecordingCanvas
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_RECORDING_CANVAS_H
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index bf1b4d0..28586fa 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -25,6 +25,9 @@
#include "DamageAccumulator.h"
#include "Debug.h"
+#if HWUI_NEW_OPS
+#include "RecordedOp.h"
+#endif
#include "DisplayListOp.h"
#include "LayerRenderer.h"
#include "OpenGLRenderer.h"
@@ -46,8 +49,8 @@
mLayer->wasBuildLayered ? "true" : "false");
}
if (mDisplayListData) {
- for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
- mDisplayListData->children()[i]->mRenderNode->debugDumpLayers(prefix);
+ for (auto&& child : mDisplayListData->children()) {
+ child->renderNode->debugDumpLayers(prefix);
}
}
}
@@ -94,12 +97,16 @@
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
properties().debugOutputProperties(level);
- int flags = DisplayListOp::kOpLogFlag_Recurse;
+
if (mDisplayListData) {
+#if HWUI_NEW_OPS
+ LOG_ALWAYS_FATAL("op dumping unsupported");
+#else
// TODO: consider printing the chunk boundaries here
- for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
- mDisplayListData->displayListOps[i]->output(level, flags);
+ for (auto&& op : mDisplayListData->getOps()) {
+ op->output(level, DisplayListOp::kOpLogFlag_Recurse);
}
+#endif
}
ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, getName());
@@ -172,7 +179,7 @@
pnode->clear_children();
if (mDisplayListData) {
for (auto&& child : mDisplayListData->children()) {
- child->mRenderNode->copyTo(pnode->add_children());
+ child->renderNode->copyTo(pnode->add_children());
}
}
}
@@ -332,6 +339,10 @@
info.damageAccumulator->popTransform();
}
+void RenderNode::syncProperties() {
+ mProperties = mStagingProperties;
+}
+
void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) {
// Push the animators first so that setupStartValueIfNecessary() is called
// before properties() is trampled by stagingProperties(), as they are
@@ -343,7 +354,7 @@
mDirtyPropertyFields = 0;
damageSelf(info);
info.damageAccumulator->popTransform();
- mProperties = mStagingProperties;
+ syncProperties();
applyLayerPropertiesToLayer(info);
// We could try to be clever and only re-damage if the matrix changed.
// However, we don't need to worry about that. The cost of over-damaging
@@ -364,35 +375,39 @@
mLayer->setBlend(props.needsBlending());
}
+void RenderNode::syncDisplayList() {
+ // Make sure we inc first so that we don't fluctuate between 0 and 1,
+ // which would thrash the layer cache
+ if (mStagingDisplayListData) {
+ for (auto&& child : mStagingDisplayListData->children()) {
+ child->renderNode->incParentRefCount();
+ }
+ }
+ deleteDisplayListData();
+ mDisplayListData = mStagingDisplayListData;
+ mStagingDisplayListData = nullptr;
+ if (mDisplayListData) {
+ for (size_t i = 0; i < mDisplayListData->functors.size(); i++) {
+ (*mDisplayListData->functors[i])(DrawGlInfo::kModeSync, nullptr);
+ }
+ }
+}
+
void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
if (mNeedsDisplayListDataSync) {
mNeedsDisplayListDataSync = false;
- // Make sure we inc first so that we don't fluctuate between 0 and 1,
- // which would thrash the layer cache
- if (mStagingDisplayListData) {
- for (size_t i = 0; i < mStagingDisplayListData->children().size(); i++) {
- mStagingDisplayListData->children()[i]->mRenderNode->incParentRefCount();
- }
- }
// Damage with the old display list first then the new one to catch any
// changes in isRenderable or, in the future, bounds
damageSelf(info);
- deleteDisplayListData();
- mDisplayListData = mStagingDisplayListData;
- mStagingDisplayListData = nullptr;
- if (mDisplayListData) {
- for (size_t i = 0; i < mDisplayListData->functors.size(); i++) {
- (*mDisplayListData->functors[i])(DrawGlInfo::kModeSync, nullptr);
- }
- }
+ syncDisplayList();
damageSelf(info);
}
}
void RenderNode::deleteDisplayListData() {
if (mDisplayListData) {
- for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
- mDisplayListData->children()[i]->mRenderNode->decParentRefCount();
+ for (auto&& child : mDisplayListData->children()) {
+ child->renderNode->decParentRefCount();
}
}
delete mDisplayListData;
@@ -407,13 +422,17 @@
info.prepareTextures = cache.prefetchAndMarkInUse(
info.canvasContext, subtree->bitmapResources[i]);
}
- for (size_t i = 0; i < subtree->children().size(); i++) {
- DrawRenderNodeOp* op = subtree->children()[i];
- RenderNode* childNode = op->mRenderNode;
+ for (auto&& op : subtree->children()) {
+ RenderNode* childNode = op->renderNode;
+#if HWUI_NEW_OPS
+ info.damageAccumulator->pushTransform(&op->localMatrix);
+ bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
+#else
info.damageAccumulator->pushTransform(&op->mTransformFromParent);
bool childFunctorsNeedLayer = functorsNeedLayer
// Recorded with non-rect clip, or canvas-rotated by parent
|| op->mRecordedWithPotentialStencilClip;
+#endif
childNode->prepareTreeImpl(info, childFunctorsNeedLayer);
info.damageAccumulator->popTransform();
}
@@ -426,8 +445,8 @@
mLayer = nullptr;
}
if (mDisplayListData) {
- for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
- mDisplayListData->children()[i]->mRenderNode->destroyHardwareResources();
+ for (auto&& child : mDisplayListData->children()) {
+ child->renderNode->destroyHardwareResources();
}
if (mNeedsDisplayListDataSync) {
// Next prepare tree we are going to push a new display list, so we can
@@ -449,6 +468,34 @@
}
}
+bool RenderNode::applyViewProperties(CanvasState& canvasState) const {
+ const Outline& outline = properties().getOutline();
+ if (properties().getAlpha() <= 0
+ || (outline.getShouldClip() && outline.isEmpty())
+ || properties().getScaleX() == 0
+ || properties().getScaleY() == 0) {
+ return false; // rejected
+ }
+
+ if (properties().getLeft() != 0 || properties().getTop() != 0) {
+ canvasState.translate(properties().getLeft(), properties().getTop());
+ }
+ if (properties().getStaticMatrix()) {
+ canvasState.concatMatrix(*properties().getStaticMatrix());
+ } else if (properties().getAnimationMatrix()) {
+ canvasState.concatMatrix(*properties().getAnimationMatrix());
+ }
+ if (properties().hasTransformMatrix()) {
+ if (properties().isTransformTranslateOnly()) {
+ canvasState.translate(properties().getTranslationX(), properties().getTranslationY());
+ } else {
+ canvasState.concatMatrix(*properties().getTransformMatrix());
+ }
+ }
+ return !canvasState.quickRejectConservative(
+ 0, 0, properties().getWidth(), properties().getHeight());
+}
+
/*
* For property operations, we pass a savecount of 0, since the operations aren't part of the
* displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
@@ -580,6 +627,7 @@
* which are flagged to not draw in the standard draw loop.
*/
void RenderNode::computeOrdering() {
+#if !HWUI_NEW_OPS
ATRACE_CALL();
mProjectedNodes.clear();
@@ -588,14 +636,16 @@
if (mDisplayListData == nullptr) return;
for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
- childOp->mRenderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity());
+ childOp->renderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity());
}
+#endif
}
void RenderNode::computeOrderingImpl(
DrawRenderNodeOp* opState,
std::vector<DrawRenderNodeOp*>* compositedChildrenOfProjectionSurface,
const mat4* transformFromProjectionSurface) {
+#if !HWUI_NEW_OPS
mProjectedNodes.clear();
if (mDisplayListData == nullptr || mDisplayListData->isEmpty()) return;
@@ -619,7 +669,7 @@
bool haveAppliedPropertiesToProjection = false;
for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
- RenderNode* child = childOp->mRenderNode;
+ RenderNode* child = childOp->renderNode;
std::vector<DrawRenderNodeOp*>* projectionChildren = nullptr;
const mat4* projectionTransform = nullptr;
@@ -642,6 +692,7 @@
child->computeOrderingImpl(childOp, projectionChildren, projectionTransform);
}
}
+#endif
}
class DeferOperationHandler {
@@ -701,11 +752,12 @@
void RenderNode::buildZSortedChildList(const DisplayListData::Chunk& chunk,
std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
+#if !HWUI_NEW_OPS
if (chunk.beginChildIndex == chunk.endChildIndex) return;
for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
- RenderNode* child = childOp->mRenderNode;
+ RenderNode* child = childOp->renderNode;
float childZ = child->properties().getZ();
if (!MathUtils::isZero(childZ) && chunk.reorderChildren) {
@@ -719,6 +771,7 @@
// Z sort any 3d children (stable-ness makes z compare fall back to standard drawing order)
std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
+#endif
}
template <class T>
@@ -824,7 +877,7 @@
while (shadowIndex < endIndex || drawIndex < endIndex) {
if (shadowIndex < endIndex) {
DrawRenderNodeOp* casterOp = zTranslatedNodes[shadowIndex].value;
- RenderNode* caster = casterOp->mRenderNode;
+ RenderNode* caster = casterOp->renderNode;
const float casterZ = zTranslatedNodes[shadowIndex].key;
// attempt to render the shadow if the caster about to be drawn is its caster,
// OR if its caster's Z value is similar to the previous potential caster
@@ -867,9 +920,14 @@
// Transform renderer to match background we're projecting onto
// (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
const DisplayListOp* op =
- (mDisplayListData->displayListOps[mDisplayListData->projectionReceiveIndex]);
+#if HWUI_NEW_OPS
+ nullptr;
+ LOG_ALWAYS_FATAL("unsupported");
+#else
+ (mDisplayListData->getOps()[mDisplayListData->projectionReceiveIndex]);
+#endif
const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op);
- const RenderProperties& backgroundProps = backgroundOp->mRenderNode->properties();
+ const RenderProperties& backgroundProps = backgroundOp->renderNode->properties();
renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
// If the projection reciever has an outline, we mask projected content to it
@@ -948,6 +1006,9 @@
setViewProperties<T>(renderer, handler);
}
+#if HWUI_NEW_OPS
+ LOG_ALWAYS_FATAL("legacy op traversal not supported");
+#else
bool quickRejected = properties().getClipToBounds()
&& renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
if (!quickRejected) {
@@ -969,9 +1030,8 @@
issueOperationsOf3dChildren(ChildrenSelectMode::NegativeZChildren,
initialTransform, zTranslatedNodes, renderer, handler);
-
for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
- DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
+ DisplayListOp *op = mDisplayListData->getOps()[opIndex];
#if DEBUG_DISPLAY_LIST
op->output(handler.level() + 1);
#endif
@@ -988,6 +1048,7 @@
}
}
}
+#endif
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (handler.level() + 1) * 2, "", restoreTo);
handler(new (alloc) RestoreToCountOp(restoreTo),
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 88fc608..ff673ba 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -29,8 +29,8 @@
#include "AnimatorManager.h"
#include "Debug.h"
-#include "Matrix.h"
#include "DisplayList.h"
+#include "Matrix.h"
#include "RenderProperties.h"
#include <vector>
@@ -43,6 +43,7 @@
namespace android {
namespace uirenderer {
+class CanvasState;
class DisplayListOp;
class DisplayListCanvas;
class OpenGLRenderer;
@@ -74,6 +75,7 @@
* attached.
*/
class RenderNode : public VirtualLightRefBase {
+friend class TestUtils; // allow TestUtils to access syncDisplayList / syncProperties
public:
enum DirtyPropertyMask {
GENERIC = 1 << 1,
@@ -176,8 +178,25 @@
AnimatorManager& animators() { return mAnimatorManager; }
+ // Returns false if the properties dictate the subtree contained in this RenderNode won't render
+ bool applyViewProperties(CanvasState& canvasState) const;
+
void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
+ bool nothingToDraw() const {
+ const Outline& outline = properties().getOutline();
+ return mDisplayListData == nullptr
+ || properties().getAlpha() <= 0
+ || (outline.getShouldClip() && outline.isEmpty())
+ || properties().getScaleX() == 0
+ || properties().getScaleY() == 0;
+ }
+
+ // Only call if RenderNode has DisplayListData...
+ const DisplayListData& getDisplayListData() const {
+ return *mDisplayListData;
+ }
+
private:
typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
@@ -235,6 +254,10 @@
const char* mText;
};
+
+ void syncProperties();
+ void syncDisplayList();
+
void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
void pushStagingPropertiesChanges(TreeInfo& info);
void pushStagingDisplayListChanges(TreeInfo& info);
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/microbench/DisplayListCanvasBench.cpp
index 7b6be7a..fd42adb 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/microbench/DisplayListCanvasBench.cpp
@@ -18,12 +18,22 @@
#include <utils/Singleton.h>
#include "DisplayList.h"
+#if HWUI_NEW_OPS
+#include "RecordingCanvas.h"
+#else
#include "DisplayListCanvas.h"
+#endif
#include "microbench/MicroBench.h"
using namespace android;
using namespace android::uirenderer;
+#if HWUI_NEW_OPS
+typedef RecordingCanvas TestCanvas;
+#else
+typedef DisplayListCanvas TestCanvas;
+#endif
+
BENCHMARK_NO_ARG(BM_DisplayListData_alloc);
void BM_DisplayListData_alloc::Run(int iters) {
StartBenchmarkTiming();
@@ -48,7 +58,7 @@
BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_empty);
void BM_DisplayListCanvas_record_empty::Run(int iters) {
- DisplayListCanvas canvas(100, 100);
+ TestCanvas canvas(100, 100);
canvas.finishRecording();
StartBenchmarkTiming();
@@ -62,7 +72,7 @@
BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_saverestore);
void BM_DisplayListCanvas_record_saverestore::Run(int iters) {
- DisplayListCanvas canvas(100, 100);
+ TestCanvas canvas(100, 100);
canvas.finishRecording();
StartBenchmarkTiming();
@@ -80,7 +90,7 @@
BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_translate);
void BM_DisplayListCanvas_record_translate::Run(int iters) {
- DisplayListCanvas canvas(100, 100);
+ TestCanvas canvas(100, 100);
canvas.finishRecording();
StartBenchmarkTiming();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 38f6e53..238cf06 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -28,6 +28,11 @@
#include "renderstate/Stencil.h"
#include "protos/hwui.pb.h"
+#if HWUI_NEW_OPS
+#include "BakedOpRenderer.h"
+#include "OpReorderer.h"
+#endif
+
#include <cutils/properties.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <private/hwui/DrawGlInfo.h>
@@ -121,9 +126,11 @@
bool CanvasContext::initialize(ANativeWindow* window) {
setSurface(window);
+#if !HWUI_NEW_OPS
if (mCanvas) return false;
mCanvas = new OpenGLRenderer(mRenderThread.renderState());
mCanvas->initProperties();
+#endif
return true;
}
@@ -162,11 +169,13 @@
}
void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
+#if !HWUI_NEW_OPS
bool success = layerUpdater->apply();
LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
if (layerUpdater->backingLayer()->deferredUpdateScheduled) {
mCanvas->pushLayerUpdate(layerUpdater->backingLayer());
}
+#endif
}
static bool wasSkipped(FrameInfo* info) {
@@ -239,8 +248,10 @@
}
void CanvasContext::draw() {
+#if !HWUI_NEW_OPS
LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
"drawRenderNode called on a context with no canvas or surface!");
+#endif
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -254,10 +265,12 @@
mCurrentFrameInfo->markIssueDrawCommandsStart();
Frame frame = mEglManager.beginFrame(mEglSurface);
- if (frame.width() != mCanvas->getViewportWidth()
- || frame.height() != mCanvas->getViewportHeight()) {
+
+ if (frame.width() != lastFrameWidth || frame.height() != lastFrameHeight) {
// can't rely on prior content of window if viewport size changes
dirty.setEmpty();
+ lastFrameWidth = frame.width();
+ lastFrameHeight = frame.height();
} else if (mHaveNewSurface || frame.bufferAge() == 0) {
// New surface needs a full draw
dirty.setEmpty();
@@ -303,6 +316,18 @@
mDamageHistory.next() = screenDirty;
mEglManager.damageFrame(frame, dirty);
+
+#if HWUI_NEW_OPS
+ OpReorderer reorderer;
+ reorderer.defer(dirty, frame.width(), frame.height(), mRenderNodes);
+ BakedOpRenderer::Info info(Caches::getInstance(), mRenderThread.renderState(),
+ frame.width(), frame.height(), mOpaque);
+ // TODO: profiler().draw(mCanvas);
+ reorderer.replayBakedOps<BakedOpRenderer>(&info);
+
+ bool drew = info.didDraw;
+
+#else
mCanvas->prepareDirty(frame.width(), frame.height(),
dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
@@ -413,7 +438,7 @@
profiler().draw(mCanvas);
bool drew = mCanvas->finish();
-
+#endif
// Even if we decided to cancel the frame, from the perspective of jank
// metrics the frame was swapped at this point
mCurrentFrameInfo->markSwapBuffers();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e0cbabd..16956e6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -141,6 +141,9 @@
void freePrefetechedLayers();
+ int lastFrameWidth = 0;
+ int lastFrameHeight = 0;
+
RenderThread& mRenderThread;
EglManager& mEglManager;
sp<ANativeWindow> mNativeWindow;
diff --git a/libs/hwui/tests/TreeContentAnimation.cpp b/libs/hwui/tests/TreeContentAnimation.cpp
index a59261c..891af91 100644
--- a/libs/hwui/tests/TreeContentAnimation.cpp
+++ b/libs/hwui/tests/TreeContentAnimation.cpp
@@ -20,6 +20,7 @@
#include <AnimationContext.h>
#include <DisplayListCanvas.h>
+#include <RecordingCanvas.h>
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>
#include <renderthread/RenderTask.h>
@@ -39,6 +40,13 @@
using namespace android::uirenderer::renderthread;
using namespace android::uirenderer::test;
+#if HWUI_NEW_OPS
+typedef RecordingCanvas TestCanvas;
+#else
+typedef DisplayListCanvas TestCanvas;
+#endif
+
+
class ContextFactory : public IContextFactory {
public:
virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
@@ -46,13 +54,13 @@
}
};
-static DisplayListCanvas* startRecording(RenderNode* node) {
- DisplayListCanvas* renderer = new DisplayListCanvas(
+static TestCanvas* startRecording(RenderNode* node) {
+ TestCanvas* renderer = new TestCanvas(
node->stagingProperties().getWidth(), node->stagingProperties().getHeight());
return renderer;
}
-static void endRecording(DisplayListCanvas* renderer, RenderNode* node) {
+static void endRecording(TestCanvas* renderer, RenderNode* node) {
node->setStagingDisplayList(renderer->finishRecording());
delete renderer;
}
@@ -67,7 +75,7 @@
frameCount = fc;
}
}
- virtual void createContent(int width, int height, DisplayListCanvas* renderer) = 0;
+ virtual void createContent(int width, int height, TestCanvas* renderer) = 0;
virtual void doFrame(int frameNr) = 0;
template <class T>
@@ -102,7 +110,7 @@
android::uirenderer::Rect DUMMY;
- DisplayListCanvas* renderer = startRecording(rootNode);
+ TestCanvas* renderer = startRecording(rootNode);
animation.createContent(width, height, renderer);
endRecording(renderer, rootNode);
@@ -132,7 +140,7 @@
class ShadowGridAnimation : public TreeContentAnimation {
public:
std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
+ void createContent(int width, int height, TestCanvas* renderer) override {
renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
renderer->insertReorderBarrier(true);
@@ -163,7 +171,7 @@
node->mutateStagingProperties().mutableOutline().setShouldClip(true);
node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
- DisplayListCanvas* renderer = startRecording(node.get());
+ TestCanvas* renderer = startRecording(node.get());
renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
endRecording(renderer, node.get());
return node;
@@ -179,7 +187,7 @@
class ShadowGrid2Animation : public TreeContentAnimation {
public:
std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
+ void createContent(int width, int height, TestCanvas* renderer) override {
renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
renderer->insertReorderBarrier(true);
@@ -210,7 +218,7 @@
node->mutateStagingProperties().mutableOutline().setShouldClip(true);
node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
- DisplayListCanvas* renderer = startRecording(node.get());
+ TestCanvas* renderer = startRecording(node.get());
renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
endRecording(renderer, node.get());
return node;
@@ -226,7 +234,7 @@
class RectGridAnimation : public TreeContentAnimation {
public:
sp<RenderNode> card;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
+ void createContent(int width, int height, TestCanvas* renderer) override {
renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
renderer->insertReorderBarrier(true);
@@ -247,7 +255,7 @@
node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- DisplayListCanvas* renderer = startRecording(node.get());
+ TestCanvas* renderer = startRecording(node.get());
renderer->drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
SkRegion region;
@@ -275,7 +283,7 @@
class OvalAnimation : public TreeContentAnimation {
public:
sp<RenderNode> card;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
+ void createContent(int width, int height, TestCanvas* renderer) override {
renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
renderer->insertReorderBarrier(true);
@@ -297,7 +305,7 @@
node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- DisplayListCanvas* renderer = startRecording(node.get());
+ TestCanvas* renderer = startRecording(node.get());
SkPaint paint;
paint.setAntiAlias(true);
@@ -317,7 +325,7 @@
class PartialDamageTest : public TreeContentAnimation {
public:
std::vector< sp<RenderNode> > cards;
- void createContent(int width, int height, DisplayListCanvas* renderer) override {
+ void createContent(int width, int height, TestCanvas* renderer) override {
static SkColor COLORS[] = {
0xFFF44336,
0xFF9C27B0,
@@ -342,7 +350,7 @@
cards[0]->mutateStagingProperties().setTranslationY(curFrame);
cards[0]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- DisplayListCanvas* renderer = startRecording(cards[0].get());
+ TestCanvas* renderer = startRecording(cards[0].get());
renderer->drawColor(interpolateColor(curFrame / 150.0f, 0xFFF44336, 0xFFF8BBD0),
SkXfermode::kSrcOver_Mode);
endRecording(renderer, cards[0].get());
@@ -370,7 +378,7 @@
node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- DisplayListCanvas* renderer = startRecording(node.get());
+ TestCanvas* renderer = startRecording(node.get());
renderer->drawColor(color, SkXfermode::kSrcOver_Mode);
endRecording(renderer, node.get());
return node;
@@ -383,3 +391,43 @@
"EGL_KHR_partial_update is supported by the device & are enabled in hwui.",
TreeContentAnimation::run<PartialDamageTest>
});
+
+
+class SimpleRectGridAnimation : public TreeContentAnimation {
+public:
+ sp<RenderNode> card;
+ void createContent(int width, int height, TestCanvas* renderer) override {
+ SkPaint paint;
+ paint.setColor(0xFF00FFFF);
+ renderer->drawRect(0, 0, width, height, paint);
+
+ card = createCard(40, 40, 200, 200);
+ renderer->drawRenderNode(card.get());
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+private:
+ sp<RenderNode> createCard(int x, int y, int width, int height) {
+ sp<RenderNode> node = new RenderNode();
+ node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
+ node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+ TestCanvas* renderer = startRecording(node.get());
+ SkPaint paint;
+ paint.setColor(0xFFFF00FF);
+ renderer->drawRect(0, 0, width, height, paint);
+
+ endRecording(renderer, node.get());
+ return node;
+ }
+};
+static Benchmark _SimpleRectGrid(BenchmarkInfo{
+ "simplerectgrid",
+ "A simple collection of rects. "
+ "Low CPU/GPU load.",
+ TreeContentAnimation::run<SimpleRectGridAnimation>
+});
diff --git a/libs/hwui/unit_tests/BakedOpStateTests.cpp b/libs/hwui/unit_tests/BakedOpStateTests.cpp
new file mode 100644
index 0000000..82aebea
--- /dev/null
+++ b/libs/hwui/unit_tests/BakedOpStateTests.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <BakedOpState.h>
+#include <RecordedOp.h>
+#include <unit_tests/TestUtils.h>
+
+namespace android {
+namespace uirenderer {
+
+TEST(ResolvedRenderState, resolution) {
+ Matrix4 identity;
+ identity.loadIdentity();
+
+ Matrix4 translate10x20;
+ translate10x20.loadTranslate(10, 20, 0);
+
+ SkPaint paint;
+ RectOp recordedOp(Rect(30, 40, 100, 200), translate10x20, Rect(0, 0, 100, 200), &paint);
+ {
+ // recorded with transform, no parent transform
+ auto parentSnapshot = TestUtils::makeSnapshot(identity, Rect(0, 0, 100, 200));
+ ResolvedRenderState state(*parentSnapshot, recordedOp);
+ EXPECT_MATRIX_APPROX_EQ(state.transform, translate10x20);
+ EXPECT_EQ(state.clipRect, Rect(0, 0, 100, 200));
+ EXPECT_EQ(state.clippedBounds, Rect(40, 60, 100, 200)); // translated and also clipped
+ }
+ {
+ // recorded with transform and parent transform
+ auto parentSnapshot = TestUtils::makeSnapshot(translate10x20, Rect(0, 0, 100, 200));
+ ResolvedRenderState state(*parentSnapshot, recordedOp);
+
+ Matrix4 expectedTranslate;
+ expectedTranslate.loadTranslate(20, 40, 0);
+ EXPECT_MATRIX_APPROX_EQ(state.transform, expectedTranslate);
+
+ // intersection of parent & transformed child clip
+ EXPECT_EQ(state.clipRect, Rect(10, 20, 100, 200));
+
+ // translated and also clipped
+ EXPECT_EQ(state.clippedBounds, Rect(50, 80, 100, 200));
+ }
+}
+
+TEST(BakedOpState, constructAndReject) {
+ LinearAllocator allocator;
+
+ Matrix4 identity;
+ identity.loadIdentity();
+
+ Matrix4 translate100x0;
+ translate100x0.loadTranslate(100, 0, 0);
+
+ SkPaint paint;
+ {
+ RectOp rejectOp(Rect(30, 40, 100, 200), translate100x0, Rect(0, 0, 100, 200), &paint);
+ auto snapshot = TestUtils::makeSnapshot(identity, Rect(0, 0, 100, 200));
+ BakedOpState* bakedOp = BakedOpState::tryConstruct(allocator, *snapshot, rejectOp);
+
+ EXPECT_EQ(bakedOp, nullptr); // rejected by clip, so not constructed
+ EXPECT_LE(allocator.usedSize(), 8u); // no significant allocation space used for rejected op
+ }
+ {
+ RectOp successOp(Rect(30, 40, 100, 200), identity, Rect(0, 0, 100, 200), &paint);
+ auto snapshot = TestUtils::makeSnapshot(identity, Rect(0, 0, 100, 200));
+ BakedOpState* bakedOp = BakedOpState::tryConstruct(allocator, *snapshot, successOp);
+
+ EXPECT_NE(bakedOp, nullptr); // NOT rejected by clip, so will be constructed
+ EXPECT_GT(allocator.usedSize(), 64u); // relatively large alloc for non-rejected op
+ }
+}
+
+#define UNSUPPORTED_OP(Info, Type) \
+ static void on##Type(Info*, const Type&, const BakedOpState&) { FAIL(); }
+
+class Info {
+public:
+ int index = 0;
+};
+
+}
+}
diff --git a/libs/hwui/unit_tests/ClipAreaTests.cpp b/libs/hwui/unit_tests/ClipAreaTests.cpp
index 0c5e5e7..d6192df 100644
--- a/libs/hwui/unit_tests/ClipAreaTests.cpp
+++ b/libs/hwui/unit_tests/ClipAreaTests.cpp
@@ -101,10 +101,9 @@
EXPECT_FALSE(area.isEmpty());
EXPECT_FALSE(area.isSimple());
EXPECT_FALSE(area.isRectangleList());
+
Rect clipRect(area.getClipRect());
- clipRect.dump("clipRect");
Rect expected(0, 0, r * 2, r * 2);
- expected.dump("expected");
EXPECT_EQ(expected, clipRect);
SkRegion clipRegion(area.getClipRegion());
auto skRect(clipRegion.getBounds());
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/unit_tests/OpReordererTests.cpp
new file mode 100644
index 0000000..cbfbb23
--- /dev/null
+++ b/libs/hwui/unit_tests/OpReordererTests.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <BakedOpState.h>
+#include <OpReorderer.h>
+#include <RecordedOp.h>
+#include <RecordingCanvas.h>
+#include <unit_tests/TestUtils.h>
+
+#include <unordered_map>
+
+namespace android {
+namespace uirenderer {
+
+#define UNSUPPORTED_OP(Info, Type) \
+ static void on##Type(Info*, const Type&, const BakedOpState&) { FAIL(); }
+
+class Info {
+public:
+ int index = 0;
+};
+
+class SimpleReceiver {
+public:
+ static void onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+ EXPECT_EQ(1, info->index++);
+ }
+ static void onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+ EXPECT_EQ(0, info->index++);
+ }
+ UNSUPPORTED_OP(Info, RenderNodeOp)
+ UNSUPPORTED_OP(Info, SimpleRectsOp)
+ static void startFrame(Info& info) {}
+ static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, simple) {
+ auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ SkBitmap bitmap = TestUtils::createSkBitmap(25, 25);
+ canvas.drawRect(0, 0, 100, 200, SkPaint());
+ canvas.drawBitmap(bitmap, 10, 10, nullptr);
+ });
+
+ OpReorderer reorderer;
+ reorderer.defer(200, 200, dld->getChunks(), dld->getOps());
+
+ Info info;
+ reorderer.replayBakedOps<SimpleReceiver>(&info);
+}
+
+
+static int SIMPLE_BATCHING_LOOPS = 5;
+class SimpleBatchingReceiver {
+public:
+ static void onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+ EXPECT_TRUE(info->index++ >= SIMPLE_BATCHING_LOOPS);
+ }
+ static void onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+ EXPECT_TRUE(info->index++ < SIMPLE_BATCHING_LOOPS);
+ }
+ UNSUPPORTED_OP(Info, RenderNodeOp)
+ UNSUPPORTED_OP(Info, SimpleRectsOp)
+ static void startFrame(Info& info) {}
+ static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, simpleBatching) {
+ auto dld = TestUtils::createDLD<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ SkBitmap bitmap = TestUtils::createSkBitmap(10, 10);
+
+ // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
+ // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ for (int i = 0; i < SIMPLE_BATCHING_LOOPS; i++) {
+ canvas.translate(0, 10);
+ canvas.drawRect(0, 0, 10, 10, SkPaint());
+ canvas.drawBitmap(bitmap, 5, 0, nullptr);
+ }
+ canvas.restore();
+ });
+
+ OpReorderer reorderer;
+ reorderer.defer(200, 200, dld->getChunks(), dld->getOps());
+
+ Info info;
+ reorderer.replayBakedOps<SimpleBatchingReceiver>(&info);
+ EXPECT_EQ(2 * SIMPLE_BATCHING_LOOPS, info.index); // 2 x loops ops, because no merging (TODO: force no merging)
+}
+
+class RenderNodeReceiver {
+public:
+ UNSUPPORTED_OP(Info, BitmapOp)
+ static void onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+ switch(info->index++) {
+ case 0:
+ EXPECT_EQ(Rect(0, 0, 200, 200), state.computedState.clippedBounds);
+ EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
+ break;
+ case 1:
+ EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds);
+ EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
+ break;
+ default:
+ FAIL();
+ }
+ }
+ UNSUPPORTED_OP(Info, RenderNodeOp)
+ UNSUPPORTED_OP(Info, SimpleRectsOp)
+ static void startFrame(Info& info) {}
+ static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, renderNode) {
+ sp<RenderNode> child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, [](RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
+
+ RenderNode* childPtr = child.get();
+ sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [childPtr](RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(0, 0, 200, 200, paint);
+
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ canvas.translate(40, 40);
+ canvas.drawRenderNode(childPtr);
+ canvas.restore();
+ });
+
+ TestUtils::syncNodePropertiesAndDisplayList(child);
+ TestUtils::syncNodePropertiesAndDisplayList(parent);
+
+ std::vector< sp<RenderNode> > nodes;
+ nodes.push_back(parent.get());
+
+ OpReorderer reorderer;
+ reorderer.defer(SkRect::MakeWH(200, 200), 200, 200, nodes);
+
+ Info info;
+ reorderer.replayBakedOps<RenderNodeReceiver>(&info);
+}
+
+class ClippedReceiver {
+public:
+ static void onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+ EXPECT_EQ(0, info->index++);
+ EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds);
+ EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect);
+ EXPECT_TRUE(state.computedState.transform.isIdentity());
+ }
+ UNSUPPORTED_OP(Info, RectOp)
+ UNSUPPORTED_OP(Info, RenderNodeOp)
+ UNSUPPORTED_OP(Info, SimpleRectsOp)
+ static void startFrame(Info& info) {}
+ static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, clipped) {
+ sp<RenderNode> node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [](RecordingCanvas& canvas) {
+ SkBitmap bitmap = TestUtils::createSkBitmap(200, 200);
+ canvas.drawBitmap(bitmap, 0, 0, nullptr);
+ });
+ TestUtils::syncNodePropertiesAndDisplayList(node);
+ std::vector< sp<RenderNode> > nodes;
+ nodes.push_back(node.get());
+
+ OpReorderer reorderer;
+ reorderer.defer(SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
+ 200, 200, nodes);
+
+ Info info;
+ reorderer.replayBakedOps<ClippedReceiver>(&info);
+}
+
+}
+}
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
new file mode 100644
index 0000000..c813833
--- /dev/null
+++ b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <RecordedOp.h>
+#include <RecordingCanvas.h>
+#include <unit_tests/TestUtils.h>
+
+namespace android {
+namespace uirenderer {
+
+static void playbackOps(const std::vector<DisplayListData::Chunk>& chunks,
+ const std::vector<RecordedOp*>& ops, std::function<void(const RecordedOp&)> opReciever) {
+ for (const DisplayListData::Chunk& chunk : chunks) {
+ for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
+ opReciever(*ops[opIndex]);
+ }
+ }
+}
+
+TEST(RecordingCanvas, emptyPlayback) {
+ auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ canvas.restore();
+ });
+ playbackOps(dld->getChunks(), dld->getOps(), [](const RecordedOp& op) { FAIL(); });
+}
+
+TEST(RecordingCanvas, testSimpleRectRecord) {
+ auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ canvas.drawRect(10, 20, 90, 180, SkPaint());
+ });
+
+ int count = 0;
+ playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+ count++;
+ ASSERT_EQ(RecordedOpId::RectOp, op.opId);
+ ASSERT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
+ ASSERT_EQ(Rect(10, 20, 90, 180), op.unmappedBounds);
+ });
+ ASSERT_EQ(1, count); // only one observed
+}
+
+TEST(RecordingCanvas, backgroundAndImage) {
+ auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ SkBitmap bitmap;
+ bitmap.setInfo(SkImageInfo::MakeUnknown(25, 25));
+ SkPaint paint;
+ paint.setColor(SK_ColorBLUE);
+
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ {
+ // a background!
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ canvas.drawRect(0, 0, 100, 200, paint);
+ canvas.restore();
+ }
+ {
+ // an image!
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ canvas.translate(25, 25);
+ canvas.scale(2, 2);
+ canvas.drawBitmap(bitmap, 0, 0, nullptr);
+ canvas.restore();
+ }
+ canvas.restore();
+ });
+
+ int count = 0;
+ playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+ if (count == 0) {
+ ASSERT_EQ(RecordedOpId::RectOp, op.opId);
+ ASSERT_NE(nullptr, op.paint);
+ EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
+ EXPECT_EQ(Rect(0, 0, 100, 200), op.unmappedBounds);
+ EXPECT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
+
+ Matrix4 expectedMatrix;
+ expectedMatrix.loadIdentity();
+ EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
+ } else {
+ ASSERT_EQ(RecordedOpId::BitmapOp, op.opId);
+ EXPECT_EQ(nullptr, op.paint);
+ EXPECT_EQ(Rect(0, 0, 25, 25), op.unmappedBounds);
+ EXPECT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
+
+ Matrix4 expectedMatrix;
+ expectedMatrix.loadTranslate(25, 25, 0);
+ expectedMatrix.scale(2, 2, 1);
+ EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
+ }
+ count++;
+ });
+ ASSERT_EQ(2, count); // two draws observed
+}
+
+}
+}
diff --git a/libs/hwui/unit_tests/TestUtils.h b/libs/hwui/unit_tests/TestUtils.h
new file mode 100644
index 0000000..9b7d1b9
--- /dev/null
+++ b/libs/hwui/unit_tests/TestUtils.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+#ifndef TEST_UTILS_H
+#define TEST_UTILS_H
+
+#include <Matrix.h>
+#include <Snapshot.h>
+#include <RenderNode.h>
+
+#include <memory>
+
+namespace android {
+namespace uirenderer {
+
+#define EXPECT_MATRIX_APPROX_EQ(a, b) \
+ EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
+
+class TestUtils {
+public:
+ static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) {
+ for (int i = 0; i < 16; i++) {
+ if (!MathUtils::areEqual(a[i], b[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
+ std::unique_ptr<Snapshot> snapshot(new Snapshot());
+ snapshot->clip(clip.left, clip.top, clip.right, clip.bottom, SkRegion::kReplace_Op);
+ *(snapshot->transform) = transform;
+ return snapshot;
+ }
+
+ static SkBitmap createSkBitmap(int width, int height) {
+ SkBitmap bitmap;
+ bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
+ return bitmap;
+ }
+
+ template<class CanvasType>
+ static std::unique_ptr<DisplayListData> createDLD(int width, int height,
+ std::function<void(CanvasType& canvas)> canvasCallback) {
+ CanvasType canvas(width, height);
+ canvasCallback(canvas);
+ return std::unique_ptr<DisplayListData>(canvas.finishRecording());
+ }
+
+ template<class CanvasType>
+ static sp<RenderNode> createNode(int left, int top, int right, int bottom,
+ std::function<void(CanvasType& canvas)> canvasCallback) {
+ sp<RenderNode> node = new RenderNode();
+ node->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
+ node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+ CanvasType canvas(
+ node->stagingProperties().getWidth(), node->stagingProperties().getHeight());
+ canvasCallback(canvas);
+ node->setStagingDisplayList(canvas.finishRecording());
+ return node;
+ }
+
+ static void syncNodePropertiesAndDisplayList(sp<RenderNode>& node) {
+ node->syncProperties();
+ node->syncDisplayList();
+ }
+}; // class TestUtils
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* TEST_UTILS_H */
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index d00236e..db53713 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -20,6 +20,7 @@
#include <SkColorFilter.h>
#include <SkDrawLooper.h>
+#include <SkShader.h>
#include <SkXfermode.h>
namespace android {
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 1152737..0f86bc6 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -78,6 +78,7 @@
mLocked.pointerAlpha = 0.0f; // pointer is initially faded
mLocked.pointerSprite = mSpriteController->createSprite();
mLocked.pointerIconChanged = false;
+ mLocked.requestedPointerShape = 0;
mLocked.buttonState = 0;
@@ -231,6 +232,10 @@
void PointerController::setPresentation(Presentation presentation) {
AutoMutex _l(mLock);
+ if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
+ mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources);
+ }
+
if (mLocked.presentation != presentation) {
mLocked.presentation = presentation;
mLocked.presentationChanged = true;
@@ -391,6 +396,15 @@
updatePointerLocked();
}
+void PointerController::updatePointerShape(int iconId) {
+ AutoMutex _l(mLock);
+ if (mLocked.requestedPointerShape != iconId) {
+ mLocked.requestedPointerShape = iconId;
+ mLocked.presentationChanged = true;
+ updatePointerLocked();
+ }
+}
+
void PointerController::setPointerIcon(const SpriteIcon& icon) {
AutoMutex _l(mLock);
@@ -497,8 +511,22 @@
}
if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
- mLocked.pointerSprite->setIcon(mLocked.presentation == PRESENTATION_POINTER
- ? mLocked.pointerIcon : mResources.spotAnchor);
+ if (mLocked.presentation == PRESENTATION_POINTER) {
+ if (mLocked.requestedPointerShape == 0) {
+ mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
+ } else {
+ std::map<int, SpriteIcon>::const_iterator iter =
+ mLocked.additionalMouseResources.find(mLocked.requestedPointerShape);
+ if (iter != mLocked.additionalMouseResources.end()) {
+ mLocked.pointerSprite->setIcon(iter->second);
+ } else {
+ ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerShape);
+ mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
+ }
+ }
+ } else {
+ mLocked.pointerSprite->setIcon(mResources.spotAnchor);
+ }
mLocked.pointerIconChanged = false;
mLocked.presentationChanged = false;
}
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index b9e4ce7..308ff12 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -19,6 +19,8 @@
#include "SpriteController.h"
+#include <map>
+
#include <ui/DisplayInfo.h>
#include <input/Input.h>
#include <inputflinger/PointerControllerInterface.h>
@@ -40,7 +42,6 @@
SpriteIcon spotAnchor;
};
-
/*
* Pointer controller policy interface.
*
@@ -57,6 +58,7 @@
public:
virtual void loadPointerResources(PointerResources* outResources) = 0;
+ virtual void loadAdditionalMouseResources(std::map<int, SpriteIcon>* outResources) = 0;
};
@@ -93,6 +95,7 @@
const uint32_t* spotIdToIndex, BitSet32 spotIdBits);
virtual void clearSpots();
+ void updatePointerShape(int iconId);
void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
void setPointerIcon(const SpriteIcon& icon);
void setInactivityTimeout(InactivityTimeout inactivityTimeout);
@@ -155,6 +158,10 @@
SpriteIcon pointerIcon;
bool pointerIconChanged;
+ std::map<int, SpriteIcon> additionalMouseResources;
+
+ int32_t requestedPointerShape;
+
int32_t buttonState;
Vector<Spot*> spots;
diff --git a/media/java/android/mtp/MtpEvent.java b/media/java/android/mtp/MtpEvent.java
index 0fa7d93..4c8a742 100644
--- a/media/java/android/mtp/MtpEvent.java
+++ b/media/java/android/mtp/MtpEvent.java
@@ -18,13 +18,33 @@
/**
* This class encapsulates information about a MTP event.
+ * Event constants are defined by the USB-IF MTP specification.
*/
public class MtpEvent {
- private int mEventCode;
+ public static final int EVENT_UNDEFINED = 0x4000;
+ public static final int EVENT_CANCEL_TRANSACTION = 0x4001;
+ public static final int EVENT_OBJECT_ADDED = 0x4002;
+ public static final int EVENT_OBJECT_REMOVED = 0x4003;
+ public static final int EVENT_STORE_ADDED = 0x4004;
+ public static final int EVENT_STORE_REMOVED = 0x4005;
+ public static final int EVENT_DEVICE_PROP_CHANGED = 0x4006;
+ public static final int EVENT_OBJECT_INFO_CHANGED = 0x4007;
+ public static final int EVENT_DEVICE_INFO_CHANGED = 0x4008;
+ public static final int EVENT_REQUEST_OBJECT_TRANSFER = 0x4009;
+ public static final int EVENT_STORE_FULL = 0x400A;
+ public static final int EVENT_DEVICE_RESET = 0x400B;
+ public static final int EVENT_STORAGE_INFO_CHANGED = 0x400C;
+ public static final int EVENT_CAPTURE_COMPLETE = 0x400D;
+ public static final int EVENT_UNREPORTED_STATUS = 0x400E;
+ public static final int EVENT_OBJECT_PROP_CHANGED = 0xC801;
+ public static final int EVENT_OBJECT_PROP_DESC_CHANGED = 0xC802;
+ public static final int EVENT_OBJECT_REFERENCES_CHANGED = 0xC803;
+
+ private int mEventCode = EVENT_UNDEFINED;
/**
* Returns event code of MTP event.
- *
+ * See the USB-IF MTP specification for the details of event constants.
* @return event code
*/
public int getEventCode() { return mEventCode; }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 9d2d171..83e3440 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -469,14 +469,18 @@
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (DEBUG) Log.d(mTag, "onKeyUp: keycode = " + keyCode);
- DirectoryFragment dir = DirectoryFragment.get(getFragmentManager());
- switch (keyCode) {
- case KeyEvent.KEYCODE_MOVE_HOME:
- dir.focusFirstFile();
- return true;
- case KeyEvent.KEYCODE_MOVE_END:
- dir.focusLastFile();
- return true;
+
+ // TODO: Support for RecentsCreateFragment.
+ DirectoryFragment fragment = DirectoryFragment.get(getFragmentManager());
+ if (fragment != null) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ fragment.focusFirstFile();
+ return true;
+ case KeyEvent.KEYCODE_MOVE_END:
+ fragment.focusLastFile();
+ return true;
+ }
}
return super.onKeyUp(keyCode, event);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 94fce59..a3a431f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -205,9 +205,12 @@
return builder.toString();
}
- public static DirectoryFragment get(FragmentManager fm) {
+ public static @Nullable DirectoryFragment get(FragmentManager fm) {
// TODO: deal with multiple directories shown at once
- return (DirectoryFragment) fm.findFragmentById(R.id.container_directory);
+ Fragment fragment = fm.findFragmentById(R.id.container_directory);
+ return fragment instanceof DirectoryFragment
+ ? (DirectoryFragment) fragment
+ : null;
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 6b428f5..aae5269 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -337,7 +337,7 @@
if (mState.action == ACTION_CREATE) {
final FragmentManager fm = getFragmentManager();
- SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
+ SaveFragment.get(fm).prepareForDirectory(cwd);
}
Menus.disableHiddenItems(menu);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Events.java b/packages/DocumentsUI/src/com/android/documentsui/Events.java
index d4c3ba3..c06ea0a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Events.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Events.java
@@ -38,7 +38,9 @@
* Returns true if event was triggered by a finger or stylus touch.
*/
static boolean isTouchEvent(MotionEvent e) {
- return isTouchType(e.getToolType(0));
+ return isTouchType(e.getToolType(0))
+ // Temporarily work around uiautomator's missing tool type support.
+ || isUnknownType(e.getToolType(0));
}
/**
@@ -49,7 +51,7 @@
}
/**
- * Returns true if event was triggered by a finger or stylus touch.
+ * Returns true if type is finger or stylus.
*/
static boolean isTouchType(int toolType) {
return toolType == MotionEvent.TOOL_TYPE_FINGER
@@ -57,6 +59,13 @@
}
/**
+ * Returns true if type is unknown.
+ */
+ static boolean isUnknownType(int toolType) {
+ return toolType == MotionEvent.TOOL_TYPE_UNKNOWN;
+ }
+
+ /**
* Returns true if event was triggered by a finger or stylus touch.
*/
static boolean isActionDown(MotionEvent e) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index de35cef..4fc3788 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -102,6 +102,7 @@
mRecentsRoot.authority = null;
mRecentsRoot.rootId = null;
mRecentsRoot.derivedIcon = R.drawable.ic_root_recent;
+ mRecentsRoot.derivedType = RootInfo.TYPE_RECENTS;
mRecentsRoot.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE
| Root.FLAG_SUPPORTS_IS_CHILD;
mRecentsRoot.title = mContext.getString(R.string.root_recent);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index c98da47..0dcd02d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -286,51 +286,34 @@
public RootsAdapter(Context context, Collection<RootInfo> roots, Intent includeApps) {
super(context, 0);
- RootItem recents = null;
- RootItem images = null;
- RootItem videos = null;
- RootItem audio = null;
- RootItem downloads = null;
-
- final List<RootInfo> clouds = new ArrayList<>();
- final List<RootInfo> locals = new ArrayList<>();
+ final List<RootItem> libraries = new ArrayList<>();
+ final List<RootItem> clouds = new ArrayList<>();
+ final List<RootItem> locals = new ArrayList<>();
for (RootInfo root : roots) {
- if (root.isRecents()) {
- recents = new RootItem(root);
- } else if (root.isExternalStorage()) {
- locals.add(root);
- } else if (root.isDownloads()) {
- downloads = new RootItem(root);
- } else if (root.isImages()) {
- images = new RootItem(root);
- } else if (root.isVideos()) {
- videos = new RootItem(root);
- } else if (root.isAudio()) {
- audio = new RootItem(root);
- } else {
- clouds.add(root);
+ RootItem item = new RootItem(root);
+ switch (root.derivedType) {
+ case RootInfo.TYPE_LOCAL:
+ locals.add(item);
+ break;
+ case RootInfo.TYPE_CLOUD:
+ clouds.add(item);
+ break;
+ default:
+ libraries.add(item);
+ break;
}
}
final RootComparator comp = new RootComparator();
- Collections.sort(clouds, comp);
+ Collections.sort(libraries, comp);
Collections.sort(locals, comp);
+ Collections.sort(clouds, comp);
- if (recents != null) add(recents);
-
- for (RootInfo cloud : clouds) {
- add(new RootItem(cloud));
- }
-
- if (images != null) add(images);
- if (videos != null) add(videos);
- if (audio != null) add(audio);
- if (downloads != null) add(downloads);
-
- for (RootInfo local : locals) {
- add(new RootItem(local));
- }
+ addAll(libraries);
+ add(new SpacerItem());
+ addAll(locals);
+ addAll(clouds);
if (includeApps != null) {
final PackageManager pm = context.getPackageManager();
@@ -348,9 +331,7 @@
if (apps.size() > 0) {
add(new SpacerItem());
- for (Item item : apps) {
- add(item);
- }
+ addAll(apps);
}
}
}
@@ -387,15 +368,20 @@
}
}
- public static class RootComparator implements Comparator<RootInfo> {
+ public static class RootComparator implements Comparator<RootItem> {
@Override
- public int compare(RootInfo lhs, RootInfo rhs) {
- final int score = DocumentInfo.compareToIgnoreCaseNullable(lhs.title, rhs.title);
+ public int compare(RootItem lhs, RootItem rhs) {
+ // Sort by root type, then title, then summary.
+ int score = lhs.root.derivedType - rhs.root.derivedType;
if (score != 0) {
return score;
- } else {
- return DocumentInfo.compareToIgnoreCaseNullable(lhs.summary, rhs.summary);
}
+ score = DocumentInfo.compareToIgnoreCaseNullable(lhs.root.title, rhs.root.title);
+ if (score != 0) {
+ return score;
+ }
+
+ return DocumentInfo.compareToIgnoreCaseNullable(lhs.root.summary, rhs.root.summary);
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index ce98db2..f3b750a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -23,6 +23,7 @@
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -79,6 +80,17 @@
mDisplayName = (EditText) view.findViewById(android.R.id.title);
mDisplayName.addTextChangedListener(mDisplayNameWatcher);
mDisplayName.setText(getArguments().getString(EXTRA_DISPLAY_NAME));
+ mDisplayName.setOnKeyListener(
+ new View.OnKeyListener() {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_ENTER && mSave.isEnabled()) {
+ performSave();
+ return true;
+ }
+ return false;
+ }
+ });
mSave = (Button) view.findViewById(android.R.id.button1);
mSave.setOnClickListener(mSaveListener);
@@ -113,17 +125,22 @@
private View.OnClickListener mSaveListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
- final DocumentsActivity activity = DocumentsActivity.get(SaveFragment.this);
- if (mReplaceTarget != null) {
- activity.onSaveRequested(mReplaceTarget);
- } else {
- final String mimeType = getArguments().getString(EXTRA_MIME_TYPE);
- final String displayName = mDisplayName.getText().toString();
- activity.onSaveRequested(mimeType, displayName);
- }
+ performSave();
}
+
};
+ private void performSave() {
+ final DocumentsActivity activity = DocumentsActivity.get(SaveFragment.this);
+ if (mReplaceTarget != null) {
+ activity.onSaveRequested(mReplaceTarget);
+ } else {
+ final String mimeType = getArguments().getString(EXTRA_MIME_TYPE);
+ final String displayName = mDisplayName.getText().toString();
+ activity.onSaveRequested(mimeType, displayName);
+ }
+ }
+
/**
* Set given document as target for in-place writing if user hits save
* without changing the filename. Can be set to {@code null} if user
@@ -139,7 +156,11 @@
}
}
- public void setSaveEnabled(boolean enabled) {
+ public void prepareForDirectory(DocumentInfo cwd) {
+ setSaveEnabled(cwd != null && cwd.isCreateSupported());
+ }
+
+ private void setSaveEnabled(boolean enabled) {
mSave.setEnabled(enabled);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index ecf4d6c..17e6a80 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -44,6 +44,15 @@
private static final int VERSION_INIT = 1;
private static final int VERSION_DROP_TYPE = 2;
+ // The values of these constants determine the sort order of various roots in the RootsFragment.
+ public static final int TYPE_IMAGES = 1;
+ public static final int TYPE_VIDEO = 2;
+ public static final int TYPE_AUDIO = 3;
+ public static final int TYPE_RECENTS = 4;
+ public static final int TYPE_DOWNLOADS = 5;
+ public static final int TYPE_LOCAL = 6;
+ public static final int TYPE_CLOUD = 7;
+
public String authority;
public String rootId;
public int flags;
@@ -57,6 +66,7 @@
/** Derived fields that aren't persisted */
public String[] derivedMimeTypes;
public int derivedIcon;
+ public int derivedType;
public RootInfo() {
reset();
@@ -76,6 +86,7 @@
derivedMimeTypes = null;
derivedIcon = 0;
+ derivedType = 0;
}
@Override
@@ -158,14 +169,23 @@
// TODO: remove these special case icons
if (isExternalStorage()) {
derivedIcon = R.drawable.ic_root_sdcard;
+ derivedType = TYPE_LOCAL;
} else if (isDownloads()) {
derivedIcon = R.drawable.ic_root_download;
+ derivedType = TYPE_DOWNLOADS;
} else if (isImages()) {
derivedIcon = R.drawable.ic_doc_image;
+ derivedType = TYPE_IMAGES;
} else if (isVideos()) {
derivedIcon = R.drawable.ic_doc_video;
+ derivedType = TYPE_VIDEO;
} else if (isAudio()) {
derivedIcon = R.drawable.ic_doc_audio;
+ derivedType = TYPE_AUDIO;
+ } else if (isRecents()) {
+ derivedType = TYPE_RECENTS;
+ } else {
+ derivedType = TYPE_CLOUD;
}
}
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index d778c98..0b8da83 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -23,6 +23,8 @@
android:layout_width="@dimen/notification_panel_width"
android:layout_height="@dimen/status_bar_header_height"
android:layout_gravity="@integer/notification_panel_layout_gravity"
+ android:paddingStart="@dimen/notification_side_padding"
+ android:paddingEnd="@dimen/notification_side_padding"
android:baselineAligned="false"
android:elevation="4dp"
android:background="@drawable/notification_header_bg"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index a64dbbd..bfa13e2 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -102,8 +102,7 @@
android:id="@+id/status_bar_header"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="@dimen/status_bar_header_height"
- android:layout_marginStart="@dimen/notification_side_padding"
- android:layout_marginEnd="@dimen/notification_side_padding" />
+ android:layout_gravity="@integer/notification_panel_layout_gravity" />
<com.android.systemui.statusbar.AlphaOptimizedView
android:id="@+id/qs_navbar_scrim"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index dd75dbf..5eca471 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -23,6 +23,8 @@
android:layout_width="@dimen/notification_panel_width"
android:layout_height="@dimen/status_bar_header_height"
android:layout_gravity="@integer/notification_panel_layout_gravity"
+ android:paddingStart="@dimen/notification_side_padding"
+ android:paddingEnd="@dimen/notification_side_padding"
android:baselineAligned="false"
android:elevation="4dp"
android:background="@drawable/notification_header_bg"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index c7c7f1a..4d07cdb 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Herrangskik Kitsinstellings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Wys helderheid in Kitsinstellings"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Gebruik verdeling in Kitsinstellings"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimenteel"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f49f5bc..c1180b6 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ፈጣን ቅንብሮችን ዳግም ያደራጁ"</string>
<string name="show_brightness" msgid="6613930842805942519">"በፈጣን ቅንብሮች ውስጥ ብሩህነትን አሳይ"</string>
- <string name="qs_paging" msgid="7020133150248666132">"በፈጣን ቅንብሮች ውስጥ ምልክት መጥሪያን ይጠቀሙ"</string>
<string name="experimental" msgid="6198182315536726162">"የሙከራ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index aaf20cc..fc2941f 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -443,6 +443,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"إعادة ترتيب الإعدادات السريعة"</string>
<string name="show_brightness" msgid="6613930842805942519">"عرض السطوع في الإعدادات السريعة"</string>
- <string name="qs_paging" msgid="7020133150248666132">"استخدام ترقيم الصفحات في الإعدادات السريعة"</string>
<string name="experimental" msgid="6198182315536726162">"إعدادات تجريبية"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 0efc82b..04d680b 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Sürətli Ayarları yenidən tənzimləyin"</string>
<string name="show_brightness" msgid="6613930842805942519">"Sürətli ayarlarda parlaqlılığı göstərin"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Sürətli Ayarlarda səhifə nömrələməsindən istifadə edin"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6805779..ca45d24 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Пренареждане на бързите настройки"</string>
<string name="show_brightness" msgid="6613930842805942519">"Показване на яркостта от бързите настройки"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Използване на разделянето на страници от бързите настройки"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментални"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index c0ffe2c..7df68ac 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"দ্রুত সেটিংসে পুনরায় সাজান"</string>
<string name="show_brightness" msgid="6613930842805942519">"দ্রুত সেটিংসে উজ্জ্বলতা দেখান"</string>
- <string name="qs_paging" msgid="7020133150248666132">"দ্রুত সেটিংসে পেজিং ব্যবহার করুন"</string>
<string name="experimental" msgid="6198182315536726162">"পরীক্ষামূলক"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 2a7c326..c85fac6 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Torna a ordenar la Configuració ràpida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a la Configuració ràpida"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Utilitza la paginació a la Configuració ràpida"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 18fd994..d58b11b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -443,6 +443,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Změnit uspořádání Rychlého nastavení"</string>
<string name="show_brightness" msgid="6613930842805942519">"Zobrazit jas v Rychlém nastavení"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Použít v Rychlém nastavení stránkování"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentální"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 5a2dd33..f300b3e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string>
<string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Brug sidelayout i Hurtige indstillinger"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a8143a4..ac513e40 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Schnelleinstellungen neu anordnen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Helligkeit in den Schnelleinstellungen anzeigen"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Seitenlayout in den Schnelleinstellungen verwenden"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentell"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6031d3b..c8ff7c6 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Αναδιάταξη Γρήγορων ρυθμίσεων"</string>
<string name="show_brightness" msgid="6613930842805942519">"Εμφάνιση φωτεινότητας στις Γρήγορες ρυθμίσεις"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Χρήση τηλεειδοποίησης στις Γρήγορες ρυθμίσεις"</string>
<string name="experimental" msgid="6198182315536726162">"Σε πειραματικό στάδιο"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index bef7661..6e66842 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index bef7661..6e66842 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index bef7661..6e66842 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
<string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en/donottranslate.xml b/packages/SystemUI/res/values-en/donottranslate.xml
deleted file mode 100644
index 9f04e1f..0000000
--- a/packages/SystemUI/res/values-en/donottranslate.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
- -->
-
-<resources>
- <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
- <item type="string" name="keyguard_indication_charging_time_fast_if_translated">@string/keyguard_indication_charging_time_fast</item>
- <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
- <item type="string" name="keyguard_indication_charging_time_slowly_if_translated">@string/keyguard_indication_charging_time_slowly</item>
-</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1590265..72258fa 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar la Configuración rápida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar el brillo en la Configuración rápida"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Usar la paginación en la Configuración rápida"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 082e762..298a0c6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Ajustes rápidos"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Ajustes rápidos"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Utilizar paginación en Ajustes rápidos"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 4add147..26b3081 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Korralda kiirseaded ümber"</string>
<string name="show_brightness" msgid="6613930842805942519">"Kuva kiirseadetes heledus"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Kasuta kiirseadetes lehe paigutust"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentaalne"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 4f5c9f2..83aac20 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Berrantolatu ezarpen bizkorrak"</string>
<string name="show_brightness" msgid="6613930842805942519">"Erakutsi distira Ezarpen bizkorretan"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Erabili orriak pasatzeko diseinu berria Ezarpen bizkorretan"</string>
<string name="experimental" msgid="6198182315536726162">"Esperimentala"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6fa7e1c..c8871c4 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -67,12 +67,12 @@
<string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"کاربری که درحالحاضر در این دستگاه وارد سیستم شده نمیتواند اشکالزدای USB را روشن کند. برای استفاده از این ویژگی، لطفاً به کاربر «سرپرست» تغییر حالت دهید."</string>
<string name="compat_mode_on" msgid="6623839244840638213">"بزرگنمایی برای پر کردن صفحه"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
- <string name="screenshot_saving_ticker" msgid="7403652894056693515">"در حال ذخیره تصویر صفحه..."</string>
- <string name="screenshot_saving_title" msgid="8242282144535555697">"در حال ذخیره تصویر صفحه..."</string>
- <string name="screenshot_saving_text" msgid="2419718443411738818">"تصویر صفحه ذخیره شد."</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"تصویر صفحه گرفته شد."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"در حال ذخیره عکس صفحهنمایش..."</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"در حال ذخیره عکس صفحهنمایش..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"عکس صفحهنمایش ذخیره شد."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"عکس صفحهنمایش گرفته شد."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده عکس صفحهنمایشتان، لمس کنید."</string>
- <string name="screenshot_failed_title" msgid="705781116746922771">"تصویر صفحه گرفته نشد."</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"عکس صفحهنمایش گرفته نشد."</string>
<string name="screenshot_failed_text" msgid="1260203058661337274">"به دلیل فضای ذخیرهسازی کم یا عدم اجازه برنامه یا سازمانتان، نمیتوان از صفحه عکس گرفت."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"گزینههای انتقال فایل USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"نصب بهعنوان دستگاه پخش رسانه (MTP)"</string>
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیههای ساعت را در نوار وضعیت نشان میدهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ترتیب مجدد در تنظیمات سریع"</string>
<string name="show_brightness" msgid="6613930842805942519">"نمایش روشنایی در تنظیمات سریع"</string>
- <string name="qs_paging" msgid="7020133150248666132">"استفاده از صفحهبندی در تنظیمات سریع"</string>
<string name="experimental" msgid="6198182315536726162">"آزمایشی"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 655cf31..3154d5c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Järjestä pika-asetukset uudelleen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Näytä kirkkaus pika-asetuksissa"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Käytä sivutusta pika-asetuksissa"</string>
<string name="experimental" msgid="6198182315536726162">"Kokeellinen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 2f2c331..669ca9b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser les paramètres rapides"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans les paramètres rapides"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Utiliser la pagination dans les paramètres rapides"</string>
<string name="experimental" msgid="6198182315536726162">"Fonctions expérimentales"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 9f34431..d42190f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser la fenêtre de configuration rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans fenêtre de configuration rapide"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Utiliser mise en page dans fenêtre de configuration rapide"</string>
<string name="experimental" msgid="6198182315536726162">"Paramètres expérimentaux"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index df90ef4..3c53983 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Configuración rápida"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Configuración rápida"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Utilizar paxinación en Configuración rápida"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 42ee460..0887e75 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string>
<string name="show_brightness" msgid="6613930842805942519">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ઝડપી સેટિંગ્સમાં પૃષ્ઠાંકનનો ઉપયોગ કરો"</string>
<string name="experimental" msgid="6198182315536726162">"પ્રાયોગિક"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 86f536d..11a0d3a 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"त्वरित सेटिंग को पुन: व्यवस्थित करें"</string>
<string name="show_brightness" msgid="6613930842805942519">"त्वरित सेटिंग में स्क्रीन की रोशनी दिखाएं"</string>
- <string name="qs_paging" msgid="7020133150248666132">"त्वरित सेटिंग में पेजिंग का उपयोग करें"</string>
<string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 043e7ad..eec3a6f 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -440,6 +440,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Promijeni raspored Brzih postavki"</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaži svjetlinu u Brzim postavkama"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Upotrijebi redni broj stranice u Brzim postavkama"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index e2b0812..2dc9ba0 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Gyorsbeállítások átrendezése"</string>
<string name="show_brightness" msgid="6613930842805942519">"Fényerő megjelenítése a gyorsbeállításokban"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Oldalelrendezés használata a gyorsbeállításokban"</string>
<string name="experimental" msgid="6198182315536726162">"Kísérleti"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index b69fc0f..a7fdb43 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Վերադասավորել Արագ կարգավորումները"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ցույց տալ պայծառությունն Արագ կարգավորումներում"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Օգտագործել էջերի դասավորությունը Արագ կարգավորումներում"</string>
<string name="experimental" msgid="6198182315536726162">"Փորձնական"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 7dbcda9..a6a68d4 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Atur Ulang Setelan Cepat"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tampilkan kecerahan di Setelan Cepat"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Gunakan pembagian laman di Setelan Cepat"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index b28b6fd..83468e5 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Endurraða flýtistillingum"</string>
<string name="show_brightness" msgid="6613930842805942519">"Sýna birtustig í flýtistillingum"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Nota síðuskoðun í flýtistillingum"</string>
<string name="experimental" msgid="6198182315536726162">"Tilraunastillingar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 54e6f56..4449a0a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Riorganizza Impostazioni rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostra luminosità in Impostazioni rapide"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Utilizza nuovo layout in Impostazioni rapide"</string>
<string name="experimental" msgid="6198182315536726162">"Sperimentali"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index c959feb..31c5126 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"סידור מחדש של הגדרות מהירות"</string>
<string name="show_brightness" msgid="6613930842805942519">"הצג בהירות בהגדרות מהירות"</string>
- <string name="qs_paging" msgid="7020133150248666132">"השתמש באפשרות הדפדוף בהגדרות המהירות"</string>
<string name="experimental" msgid="6198182315536726162">"ניסיוניות"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 29476d8..d1603ff 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"クイック設定を並べ替え"</string>
<string name="show_brightness" msgid="6613930842805942519">"クイック設定に明るさ調整バーを表示する"</string>
- <string name="qs_paging" msgid="7020133150248666132">"クイック設定でページ設定を使用する"</string>
<string name="experimental" msgid="6198182315536726162">"試験運用版"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index d83c9e9..e5e9003 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"სწრაფი პარამეტრების გადაწყობა"</string>
<string name="show_brightness" msgid="6613930842805942519">"სიკაშკაშის ჩვენება სწრაფ პარამეტრებში"</string>
- <string name="qs_paging" msgid="7020133150248666132">"გამოიყენეთ გვერდების დანომვრა სწრაფ პარამეტრებში"</string>
<string name="experimental" msgid="6198182315536726162">"ექსპერიმენტული"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 5c066b3..946d86b 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Жылдам параметрлерді қайта реттеу"</string>
<string name="show_brightness" msgid="6613930842805942519">"Жылдам параметрлерде жарықтықты көрсету"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Жылдам параметрлерде беттерді нөмірлеуді пайдалану"</string>
<string name="experimental" msgid="6198182315536726162">"Эксперименттік"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 4c469b0..264438b 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"រៀបចំការកំណត់រហ័សឡើងវិញ"</string>
<string name="show_brightness" msgid="6613930842805942519">"បង្ហាញកម្រិតពន្លឺនៅក្នុងការកំណត់រហ័ស"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ប្រើការចុះទំព័រនៅក្នុងការកំណត់រហ័ស"</string>
<string name="experimental" msgid="6198182315536726162">"ពិសោធន៍"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 4215a91..1696076 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
<string name="show_brightness" msgid="6613930842805942519">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಪ್ರಖರತೆಯನ್ನು ತೋರಿಸಿ"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಪುಟಗಳನ್ನು ಬಳಸಿ"</string>
<string name="experimental" msgid="6198182315536726162">"ಪ್ರಾಯೋಗಿಕ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 8ee5946..d053b53 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"빠른 설정 재정렬"</string>
<string name="show_brightness" msgid="6613930842805942519">"빠른 설정에서 밝기 표시"</string>
- <string name="qs_paging" msgid="7020133150248666132">"빠른 설정에서 페이지 레이아웃 사용"</string>
<string name="experimental" msgid="6198182315536726162">"베타"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index ce0afd4..ec4bec7 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ыкчам жөндөөлөрдү кайра коюу"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ыкчам жөндөөлөрдөн жарык деңгээлин көрсөтүү"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Ыкчам жөндөөлөрдөн баракты номерлөөнү колдонуу"</string>
<string name="experimental" msgid="6198182315536726162">"Сынамык"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index b45395e..e5d784f 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ສະແດງວິນາທີໂມງຢູ່ໃນແຖບສະຖານະ. ອາດຈະມີຜົນກະທົບຕໍ່ອາຍຸແບັດເຕີຣີ."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ຈັດວາງການຕັ້ງຄ່າດ່ວນຄືນໃໝ່"</string>
<string name="show_brightness" msgid="6613930842805942519">"ສະແດງຄວາມແຈ້ງຢູ່ໃນການຕັ້ງຄ່າດ່ວນ"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ໃຊ້ການໃສ່ໜ້າຢູ່ໃນການຕັ້ງຄ່າດ່ວນ"</string>
<string name="experimental" msgid="6198182315536726162">"ຍັງຢູ່ໃນການທົດລອງ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 194668b..ca50956 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Pertvarkyti sparčiuosius nustatymus"</string>
<string name="show_brightness" msgid="6613930842805942519">"Rodyti skaistį sparčiuosiuose nustatymuose"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Naudoti puslapių kaitą sparčiuosiuose nustatymuose"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentinė versija"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 2b3be58..a87d918 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -440,6 +440,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Pārkārtot ātros iestatījumus"</string>
<string name="show_brightness" msgid="6613930842805942519">"Rādīt spilgtumu ātrajos iestatījumos"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Izmantot lapošanu ātrajos iestatījumos"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentāli"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 912c30f..1015018 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Преуредете ги Брзи поставки"</string>
<string name="show_brightness" msgid="6613930842805942519">"Прикажете ја осветленоста во Брзи поставки"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Користете прелистување страници во Брзи поставки"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index c85ecc7..45ec29a 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ദ്രുത ക്രമീകരണം പുനഃസജ്ജീകരിക്കുക"</string>
<string name="show_brightness" msgid="6613930842805942519">"ദ്രുത ക്രമീകരണത്തിൽ തെളിച്ചം കാണിക്കുക"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ദ്രുത്ര ക്രമീകരണത്തിൽ പേജിംഗ് ഉപയോഗിക്കുക"</string>
<string name="experimental" msgid="6198182315536726162">"പരീക്ഷണാത്മകം!"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 6b29aff..1051e49 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -437,6 +437,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Түргэн тохиргоог дахин засварлах"</string>
<string name="show_brightness" msgid="6613930842805942519">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Хуудаслалтыг түргэн тохиргоонд ашиглаарай"</string>
<string name="experimental" msgid="6198182315536726162">"Туршилтын"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 9d518a0..66843fc 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्ये घड्याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्य प्रभावित होऊ शकते."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिंग्जची पुनर्रचना करा"</string>
<string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिंग्जमध्ये चमक दर्शवा"</string>
- <string name="qs_paging" msgid="7020133150248666132">"द्रुत सेटिंग्जमध्ये लिखाण वापरा"</string>
<string name="experimental" msgid="6198182315536726162">"प्रायोगिक"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 10dca3e..c50e214 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Susun Semula Tetapan Pantas"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tunjukkan kecerahan dalam Tetapan Pantas"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Gunakan penghalaman dalam Tetapan Pantas"</string>
<string name="experimental" msgid="6198182315536726162">"Percubaan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index adfd9f8..f4fd3d1 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"အမြန် ဆက်တင်များကို ပြန်စီစဉ်ရန်"</string>
<string name="show_brightness" msgid="6613930842805942519">"အမြန် ဆက်တင်များထဲက တောက်ပမှုကို ပြရန်"</string>
- <string name="qs_paging" msgid="7020133150248666132">"အမြန် ဆက်တင်များထဲတွင် စာမျက်နှာ ပုံစံချမှုကို အသုံးပြုပါ"</string>
<string name="experimental" msgid="6198182315536726162">"စမ်းသပ်ရေး"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index ecfb7f2..cae404d 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Omorganiser hurtiginnstillingene"</string>
<string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i hurtiginnstillingene"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Bruk sidetall i hurtiginnstillingene"</string>
<string name="experimental" msgid="6198182315536726162">"På forsøksstadiet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index d997aff..563bc87 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिङहरू पुनः व्यवस्थित गर्नुहोस्"</string>
<string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिङहरूमा उज्यालो देखाउनुहोस्"</string>
- <string name="qs_paging" msgid="7020133150248666132">"द्रुत सेटिङहरूमा पेजिंग प्रयोग गर्नुहोस्"</string>
<string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c6bab06..bf9f0f2 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Snelle instellingen opnieuw indelen"</string>
<string name="show_brightness" msgid="6613930842805942519">"Helderheid weergeven in Snelle instellingen"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Paginering gebruiken in Snelle instellingen"</string>
<string name="experimental" msgid="6198182315536726162">"Experimenteel"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 74e5fcb..45d56cc 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
<string name="show_brightness" msgid="6613930842805942519">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਮਕ ਦਿਖਾਓ"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਪੇਜਿੰਗ ਵਰਤੋ"</string>
<string name="experimental" msgid="6198182315536726162">"ਪ੍ਰਯੋਗਾਤਮਿਕ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index e04fd71..2807c5a 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Uporządkuj Szybkie ustawienia"</string>
<string name="show_brightness" msgid="6613930842805942519">"Pokaż jasność w Szybkich ustawieniach"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Użyj stronicowania w Szybkich ustawieniach"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperymentalne"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 2a8e3ab..c8400c9 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
- <string name="qs_paging" msgid="7020133150248666132">"Usar paginação nas \"Configurações rápidas\""</string>
<string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8453e5b..43088fe9 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar as Definições rápidas"</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar luminosidade nas Definições rápidas"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Utilizar paginação nas Definições rápidas"</string>
<string name="experimental" msgid="6198182315536726162">"Experimental"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 2a8e3ab..c8400c9 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
<string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
- <string name="qs_paging" msgid="7020133150248666132">"Usar paginação nas \"Configurações rápidas\""</string>
<string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index de693f5..d64ca7c 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -440,6 +440,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Rearanjați Setările rapide"</string>
<string name="show_brightness" msgid="6613930842805942519">"Afișați luminozitatea în Setările rapide"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Folosiți paginarea în Setările rapide"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentale"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 39d8617..480de30 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -443,6 +443,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Изменить порядок Быстрых настроек"</string>
<string name="show_brightness" msgid="6613930842805942519">"Добавить яркость в Быстрые настройки"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Разбить Быстрые настройки на страницы"</string>
<string name="experimental" msgid="6198182315536726162">"Экспериментальная функция"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 51bb047..e784601 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"ඉක්මන් සැකසීම් යළි පිළිවෙළට සකසන්න"</string>
<string name="show_brightness" msgid="6613930842805942519">"ඉක්මන් සැකසීම්වල දීප්තිය පෙන්වන්න"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ඉක්මන් සැකසීම්වල පිටු පිරිසැලසුම් භාවිත කරන්න"</string>
<string name="experimental" msgid="6198182315536726162">"පරීක්ෂණාත්මක"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 2886e36..15612ee 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -443,6 +443,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Zmeniť usporiadanie Rýchlych nastavení"</string>
<string name="show_brightness" msgid="6613930842805942519">"Zobraziť jas v Rýchlych nastaveniach"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Použite stránkovanie v Rýchlych nastaveniach"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentálne"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index e325ef1..23e4233 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Preuredi hitre nastavitve"</string>
<string name="show_brightness" msgid="6613930842805942519">"Prikaz svetlosti v hitrih nastavitvah"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Uporaba postavitve strani v hitrih nastavitvah"</string>
<string name="experimental" msgid="6198182315536726162">"Poskusno"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 5bcf941..771ad53 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Risistemo Cilësimet e shpejta"</string>
<string name="show_brightness" msgid="6613930842805942519">"Shfaq ndriçimin te Cilësimet e shpejta"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Përdor faqosjen te Cilësimet e shpejta"</string>
<string name="experimental" msgid="6198182315536726162">"Eksperimentale"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 522b2af..f3abc81 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -440,6 +440,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Преуреди Брза подешавања"</string>
<string name="show_brightness" msgid="6613930842805942519">"Прикажи осветљеност у Брзим подешавањима"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Користи листање страница у Брзим подешавањима"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7323126..3593b34 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ordna snabbinställningarna"</string>
<string name="show_brightness" msgid="6613930842805942519">"Visa ljusstyrka i snabbinställningarna"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Använd sidindelning i snabbinställningarna"</string>
<string name="experimental" msgid="6198182315536726162">"Experimentella"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 1cf4293..de39e9b 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Panga Upya Mipangilio ya Haraka"</string>
<string name="show_brightness" msgid="6613930842805942519">"Onyesha unga\'avu katika Mipangilio ya Haraka"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Tumia nambari za ukurasa katika Mipangilio ya Haraka"</string>
<string name="experimental" msgid="6198182315536726162">"Ya majaribio"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 670bccc..a895df7 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"விரைவு அமைப்புகளை மறுவரிசைப்படுத்து"</string>
<string name="show_brightness" msgid="6613930842805942519">"விரைவு அமைப்புகளில் ஒளிர்வுப் பட்டியைக் காட்டு"</string>
- <string name="qs_paging" msgid="7020133150248666132">"விரைவு அமைப்புகளில் புதிய பக்கத் தளவமைப்பைப் பயன்படுத்து"</string>
<string name="experimental" msgid="6198182315536726162">"சோதனை முயற்சி"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index bbd9979..c34a33d 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"శీఘ్ర సెట్టింగ్ల ఏర్పాటు క్రమం మార్చు"</string>
<string name="show_brightness" msgid="6613930842805942519">"శీఘ్ర సెట్టింగ్ల్లో ప్రకాశం చూపు"</string>
- <string name="qs_paging" msgid="7020133150248666132">"శీఘ్ర సెట్టింగ్ల్లో పేజింగ్ను ఉపయోగించు"</string>
<string name="experimental" msgid="6198182315536726162">"ప్రయోగాత్మకం"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2486519..d777a0a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"จัดเรียงการตั้งค่าด่วนใหม่"</string>
<string name="show_brightness" msgid="6613930842805942519">"แสดงความสว่างในการตั้งค่าด่วน"</string>
- <string name="qs_paging" msgid="7020133150248666132">"ใช้การแบ่งหน้าในการตั้งค่าด่วน"</string>
<string name="experimental" msgid="6198182315536726162">"ทดสอบ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 3d1243e..292d3a2 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Ayusing Muli ang Mga Mabilisang Setting"</string>
<string name="show_brightness" msgid="6613930842805942519">"Ipakita ang liwanag sa Mga Mabilisang Setting"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Gamitin ang paging sa Mga Mabilisang Setting"</string>
<string name="experimental" msgid="6198182315536726162">"Pang-eksperimento"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 4dadfbc..9c42e93 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Hızlı Ayarlar\'ı Yeniden Düzenle"</string>
<string name="show_brightness" msgid="6613930842805942519">"Hızlı Ayarlar\'da parlaklığı göster"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Hızlı Ayarlar\'da sayfa ayırmayı kullan"</string>
<string name="experimental" msgid="6198182315536726162">"Deneysel"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d158dbe..9638e80 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Упорядкувати швидкі налаштування"</string>
<string name="show_brightness" msgid="6613930842805942519">"Показувати панель яскравості у швидких налаштуваннях"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Показувати швидкі налаштування у вигляді сторінок"</string>
<string name="experimental" msgid="6198182315536726162">"Експериментальні налаштування"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index f8d8c71..8c2fb64 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"فوری ترتیبات کو دوبارہ ترتیب دیں"</string>
<string name="show_brightness" msgid="6613930842805942519">"فوری ترتیبات میں چمکیلا پن دکھائیں"</string>
- <string name="qs_paging" msgid="7020133150248666132">"فوری ترتیبات میں پیجنگ استعمال کریں"</string>
<string name="experimental" msgid="6198182315536726162">"تجرباتی"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 0186809..0ad5a69 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Tezkor sozlamalarni qayta tartiblash"</string>
<string name="show_brightness" msgid="6613930842805942519">"Tezkor sozlamalarda yorqinlikni ko‘rsatish"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Tezkor sozlamalarni sahifalarga ajratish"</string>
<string name="experimental" msgid="6198182315536726162">"Tajribaviy"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 49b5d1d..c1aeeb4 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Sắp xếp lại Cài đặt nhanh"</string>
<string name="show_brightness" msgid="6613930842805942519">"Hiển thị độ sáng trong Cài đặt nhanh"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Sử dụng đánh số trang trong Cài đặt nhanh"</string>
<string name="experimental" msgid="6198182315536726162">"Thử nghiệm"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 93ed5ca..fe1c311 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速设置"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速设置中显示亮度栏"</string>
- <string name="qs_paging" msgid="7020133150248666132">"在快速设置中使用分页功能"</string>
<string name="experimental" msgid="6198182315536726162">"实验性"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 2196111..d39adc0 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速設定顯示亮度"</string>
- <string name="qs_paging" msgid="7020133150248666132">"在快速設定使用分頁"</string>
<string name="experimental" msgid="6198182315536726162">"實驗版"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index fe4fe06..6606167 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -441,6 +441,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
<string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
<string name="show_brightness" msgid="6613930842805942519">"在快速設定中顯示亮度"</string>
- <string name="qs_paging" msgid="7020133150248666132">"在快速設定中使用分頁功能"</string>
<string name="experimental" msgid="6198182315536726162">"實驗性"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 2f068af..229c16b 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -439,6 +439,5 @@
<string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
<string name="qs_rearrange" msgid="8060918697551068765">"Hlela kabusha izilungiselelo ezisheshayo"</string>
<string name="show_brightness" msgid="6613930842805942519">"Bonisa ukukhanya kuzilungiselelo ezisheshayo"</string>
- <string name="qs_paging" msgid="7020133150248666132">"Sebenzisa i-paging kuzilungiselelo ezisheshayo"</string>
<string name="experimental" msgid="6198182315536726162">"Okokulinga"</string>
</resources>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 30ff704..351a1fd 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -20,10 +20,4 @@
<!-- Date format for display: should match the lockscreen in /policy. -->
<string name="system_ui_date_pattern">@*android:string/system_ui_date_pattern</string>
- <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
- <item type="string" name="keyguard_indication_charging_time_fast_if_translated">@string/keyguard_indication_charging_time</item>
-
- <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
- <item type="string" name="keyguard_indication_charging_time_slowly_if_translated">@string/keyguard_indication_charging_time</item>
-
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index e562682..8e98f10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -16,6 +16,7 @@
package com.android.systemui.qs;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Animatable;
@@ -325,6 +326,7 @@
public interface Host {
void startActivityDismissingKeyguard(Intent intent);
+ void startActivityDismissingKeyguard(PendingIntent intent);
void warn(String message, Throwable t);
void collapsePanels();
Looper getLooper();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 3d0dc7b..c7f2284 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -99,7 +99,7 @@
try {
if (pi != null) {
if (pi.isActivity()) {
- getHost().startActivityDismissingKeyguard(pi.getIntent());
+ getHost().startActivityDismissingKeyguard(pi);
} else {
pi.send();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
index 8827065..d3c65d2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
@@ -16,6 +16,9 @@
package com.android.systemui.recents;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -245,7 +248,7 @@
// the focus ends on the selected one.
for (int i = additionalTasks; i >= 0; --i) {
if (mTasks[i] != null) {
- mRecentsView.launchTask(mTasks[i], mBounds[i]);
+ mRecentsView.launchTask(mTasks[i], mBounds[i], FREEFORM_WORKSPACE_STACK_ID);
}
}
}
@@ -273,11 +276,11 @@
// Dismiss the dialog before trying to launch the task
dismissAllowingStateLoss();
- if (mTasks[0].key.stackId != ActivityManager.DOCKED_STACK_ID) {
+ if (mTasks[0].key.stackId != DOCKED_STACK_ID) {
int taskId = mTasks[0].key.id;
mSsp.setTaskResizeable(taskId);
mSsp.dockTask(taskId, createMode);
- mRecentsView.launchTask(mTasks[0], null);
+ mRecentsView.launchTask(mTasks[0], null, DOCKED_STACK_ID);
} else {
Toast.makeText(getContext(), "Already docked", Toast.LENGTH_SHORT);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 1266120..a5fd3eb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,6 +16,8 @@
package com.android.systemui.recents.views;
+import static android.app.ActivityManager.INVALID_STACK_ID;
+
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.Context;
@@ -185,7 +187,8 @@
TaskView tv = taskViews.get(j);
Task task = tv.getTask();
if (tv.isFocusedTask()) {
- onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null);
+ onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null,
+ INVALID_STACK_ID);
return true;
}
}
@@ -194,7 +197,7 @@
}
/** Launches a given task. */
- public boolean launchTask(Task task, Rect taskBounds) {
+ public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
if (mTaskStackView != null) {
TaskStack stack = mTaskStackView.getStack();
// Iterate the stack views and try and find the given task.
@@ -204,7 +207,7 @@
TaskView tv = taskViews.get(j);
if (tv.getTask() == task) {
onTaskViewClicked(mTaskStackView, tv, stack, task, false, taskBounds != null,
- taskBounds);
+ taskBounds, destinationStack);
return true;
}
}
@@ -226,7 +229,8 @@
if (tasks.get(j).isLaunchTarget) {
Task task = tasks.get(j);
TaskView tv = mTaskStackView.getChildViewForTask(task);
- onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null);
+ onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null,
+ INVALID_STACK_ID);
return true;
}
}
@@ -451,12 +455,13 @@
private void postDrawHeaderThumbnailTransitionRunnable(final TaskStackView view,
final TaskView clickedView, final int offsetX, final int offsetY,
final float stackScroll,
- final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+ final ActivityOptions.OnAnimationStartedListener animStartedListener,
+ final int destinationStack) {
Runnable r = new Runnable() {
@Override
public void run() {
overrideDrawHeaderThumbnailTransition(view, clickedView, offsetX, offsetY,
- stackScroll, animStartedListener);
+ stackScroll, animStartedListener, destinationStack);
}
};
@@ -466,9 +471,10 @@
private void overrideDrawHeaderThumbnailTransition(TaskStackView stackView,
TaskView clickedTask, int offsetX, int offsetY, float stackScroll,
- final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+ final ActivityOptions.OnAnimationStartedListener animStartedListener,
+ int destinationStack) {
List<AppTransitionAnimationSpec> specs = getAppTransitionAnimationSpecs(stackView,
- clickedTask, offsetX, offsetY, stackScroll);
+ clickedTask, offsetX, offsetY, stackScroll, destinationStack);
if (specs == null) {
return;
}
@@ -499,8 +505,10 @@
}
private List<AppTransitionAnimationSpec> getAppTransitionAnimationSpecs(TaskStackView stackView,
- TaskView clickedTask, int offsetX, int offsetY, float stackScroll) {
- final int targetStackId = clickedTask.getTask().key.stackId;
+ TaskView clickedTask, int offsetX, int offsetY, float stackScroll,
+ int destinationStack) {
+ final int targetStackId = destinationStack != INVALID_STACK_ID ?
+ destinationStack : clickedTask.getTask().key.stackId;
if (targetStackId != ActivityManager.FREEFORM_WORKSPACE_STACK_ID
&& targetStackId != ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
return null;
@@ -604,9 +612,8 @@
@Override
public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
- final TaskStack stack, final Task task, final boolean lockToTask,
- final boolean boundsValid, final Rect bounds) {
-
+ final TaskStack stack, final Task task, final boolean lockToTask,
+ final boolean boundsValid, final Rect bounds, int destinationStack) {
// Notify any callbacks of the launching of a new task
if (mCb != null) {
mCb.onTaskViewClicked();
@@ -654,7 +661,7 @@
};
}
postDrawHeaderThumbnailTransitionRunnable(stackView, tv, offsetX, offsetY, stackScroll,
- animStartedListener);
+ animStartedListener, destinationStack);
opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8).createAshmemBitmap(),
offsetX, offsetY, transform.rect.width(), transform.rect.height(),
@@ -810,7 +817,7 @@
SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
ssp.setTaskResizeable(event.task.key.id);
ssp.dockTask(event.task.key.id, event.dockState.createMode);
- launchTask(event.task, null);
+ launchTask(event.task, null, INVALID_STACK_ID);
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 08e4e20..f637407 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,7 +16,10 @@
package com.android.systemui.recents.views;
+import static android.app.ActivityManager.INVALID_STACK_ID;
+
import android.animation.ValueAnimator;
+import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Canvas;
@@ -59,7 +62,7 @@
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
- boolean lockToTask, boolean boundsValid, Rect bounds);
+ boolean lockToTask, boolean boundsValid, Rect bounds, int destinationStack);
public void onAllTaskViewsDismissed(ArrayList<Task> removedTasks);
public void onTaskStackFilterTriggered();
public void onTaskStackUnfilterTriggered();
@@ -1227,7 +1230,8 @@
mUIDozeTrigger.stopDozing();
if (mCb != null) {
- mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask, false, null);
+ mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask, false, null,
+ INVALID_STACK_ID);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 18e07a3..4322f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -157,6 +157,14 @@
mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
break;
}
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ final int index = ev.getActionIndex();
+ mActivePointerId = ev.getPointerId(index);
+ mLastMotionX = (int) ev.getX(index);
+ mLastMotionY = (int) ev.getY(index);
+ mLastP = layoutAlgorithm.sCurve.xToP(mLastMotionY, layoutAlgorithm.mStackRect);
+ break;
+ }
case MotionEvent.ACTION_MOVE: {
if (mActivePointerId == INACTIVE_POINTER_ID) break;
@@ -182,6 +190,20 @@
mLastP = layoutAlgorithm.sCurve.xToP(mLastMotionY, layoutAlgorithm.mStackRect);
break;
}
+ case MotionEvent.ACTION_POINTER_UP: {
+ int pointerIndex = ev.getActionIndex();
+ int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // Select a new active pointer id and reset the motion state
+ final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ mLastMotionX = (int) ev.getX(newPointerIndex);
+ mLastMotionY = (int) ev.getY(newPointerIndex);
+ mLastP = layoutAlgorithm.sCurve.xToP(mLastMotionY, layoutAlgorithm.mStackRect);
+ mVelocityTracker.clear();
+ }
+ break;
+ }
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// Animate the scroll back if we've cancelled
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 d2003bf..d227d55 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -167,7 +167,6 @@
mContent = findViewById(R.id.task_view_content);
mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
- mThumbnailView.updateClipToTaskBar(mHeaderView);
mActionButtonView = findViewById(R.id.lock_to_app_fab);
mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -210,6 +209,7 @@
mThumbnailView.measure(
MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY));
+ mThumbnailView.updateClipToTaskBar(mHeaderView);
setMeasuredDimension(width, height);
invalidateOutline();
}
@@ -786,8 +786,8 @@
// Start listening for drag events
setClipViewInStack(false);
- int width = (int) (getScaleX() * getWidth());
- int height = (int) (getScaleY() * getHeight());
+ final int width = (int) (getScaleX() * getWidth());
+ final int height = (int) (getScaleY() * getHeight());
Bitmap dragBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(dragBitmap);
c.scale(getScaleX(), getScaleY());
@@ -797,7 +797,12 @@
// Initiate the drag
final DragView dragView = new DragView(getContext(), dragBitmap, mDownTouchPos);
- dragView.setOutlineProvider(mViewBounds);
+ dragView.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRect(0, 0, width, height);
+ }
+ });
dragView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index aaed735..8938669 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1617,6 +1617,59 @@
return null;
}
+ public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
+ if (!isDeviceProvisioned()) return;
+
+ final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+ final boolean afterKeyguardGone = intent.isActivity()
+ && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+ mCurrentUserId);
+ dismissKeyguardThenExecute(new OnDismissAction() {
+ public boolean onDismiss() {
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ if (keyguardShowing && !afterKeyguardGone) {
+ ActivityManagerNative.getDefault()
+ .keyguardWaitingForActivityDrawn();
+ }
+
+ // The intent we are sending is for the application, which
+ // won't have permission to immediately start an activity after
+ // the user switches to home. We know it is safe to do at this
+ // point, so make sure new activity switches are now allowed.
+ ActivityManagerNative.getDefault().resumeAppSwitches();
+ } catch (RemoteException e) {
+ }
+
+ try {
+ intent.send();
+ } catch (PendingIntent.CanceledException e) {
+ // the stack trace isn't very helpful here.
+ // Just log the exception message.
+ Log.w(TAG, "Sending intent failed: " + e);
+
+ // TODO: Dismiss Keyguard.
+ }
+ if (intent.isActivity()) {
+ mAssistManager.hideAssist();
+ overrideActivityPendingAppTransition(keyguardShowing
+ && !afterKeyguardGone);
+ }
+ }
+ }.start();
+
+ // close the shade if it was open
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+ true /* force */, true /* delayed */);
+ visibilityChanged(false);
+
+ return true;
+ }
+ }, afterKeyguardGone);
+ }
+
private final class NotificationClicker implements View.OnClickListener {
public void onClick(final View v) {
if (!(v instanceof ExpandableNotificationRow)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 5e6fdd0..6d13947 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -200,12 +200,12 @@
switch (mChargingSpeed) {
case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time_fast_if_translated
+ ? R.string.keyguard_indication_charging_time_fast
: R.string.keyguard_plugged_in_charging_fast;
break;
case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
chargingId = hasChargingTime
- ? R.string.keyguard_indication_charging_time_slowly_if_translated
+ ? R.string.keyguard_indication_charging_time_slowly
: R.string.keyguard_plugged_in_charging_slowly;
break;
default:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index 9ef320bc..8f689c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import android.app.PendingIntent;
import android.content.Intent;
/**
@@ -24,6 +25,7 @@
* Keyguard.
*/
public interface ActivityStarter {
+ void startPendingIntentDismissingKeyguard(PendingIntent intent);
void startActivity(Intent intent, boolean dismissShade);
void startActivity(Intent intent, boolean dismissShade, Callback callback);
void preventNextAnimation();
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 bd16257..76edafa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -25,6 +25,7 @@
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver;
@@ -228,8 +229,7 @@
}
// On expanding, single mouse click expands the panel instead of dragging.
- if (isFullyCollapsed() && event.getPointerCount() == 1
- && event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
+ if (isFullyCollapsed() && event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
if (event.getAction() == MotionEvent.ACTION_UP) {
expand(true);
}
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 1c1a1d7..cfde791 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3261,6 +3261,15 @@
return !isDeviceProvisioned() || (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0;
}
+ public void postStartActivityDismissingKeyguard(final PendingIntent intent) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ startPendingIntentDismissingKeyguard(intent);
+ }
+ });
+ }
+
public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
mHandler.postDelayed(new Runnable() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 6906a52..f8ddc73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -121,6 +122,11 @@
}
@Override
+ public void startActivityDismissingKeyguard(PendingIntent intent) {
+ mStatusBar.postStartActivityDismissingKeyguard(intent);
+ }
+
+ @Override
public void warn(String message, Throwable t) {
// already logged
}
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 65d84e2..6cda561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -554,8 +554,8 @@
startBatteryActivity();
} else if (v == mAlarmStatus && mNextAlarm != null) {
PendingIntent showIntent = mNextAlarm.getShowIntent();
- if (showIntent != null && showIntent.isActivity()) {
- mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
+ if (showIntent != null) {
+ mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index b2df40a..0e91b0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -27,7 +27,6 @@
void removeCallback(Callback callback);
void setZen(int zen, Uri conditionId, String reason);
int getZen();
- void requestConditions(boolean request);
ZenRule getManualRule();
ZenModeConfig getConfig();
long getNextAlarm();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index c07f1a8..96efea1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -121,15 +121,6 @@
}
@Override
- public void requestConditions(boolean request) {
- mRequesting = request;
- mNoMan.requestZenModeConditions(mListener, request ? Condition.FLAG_RELEVANT_NOW : 0);
- if (!mRequesting) {
- mConditions.clear();
- }
- }
-
- @Override
public ZenRule getManualRule() {
return mConfig == null ? null : mConfig.manualRule;
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 3c9a7fc..02ee5d4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -1,4 +1,4 @@
-/*
+/**
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -58,6 +58,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Objects;
@@ -76,6 +78,7 @@
private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
private static final int FOREVER_CONDITION_INDEX = 0;
private static final int COUNTDOWN_CONDITION_INDEX = 1;
+ private static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
public static final Intent ZEN_SETTINGS
= new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -104,9 +107,6 @@
private Callback mCallback;
private ZenModeController mController;
private boolean mCountdownConditionSupported;
- private int mMaxConditions;
- private int mMaxOptionalConditions;
- private int mFirstConditionIndex;
private boolean mRequestingConditions;
private Condition mExitCondition;
private int mBucketIndex = -1;
@@ -118,6 +118,7 @@
private Condition mSessionExitCondition;
private Condition[] mConditions;
private Condition mTimeCondition;
+ private Condition mTimeUntilAlarmCondition;
private boolean mVoiceCapable;
public ZenModePanel(Context context, AttributeSet attrs) {
@@ -135,7 +136,6 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("ZenModePanel state:");
pw.print(" mCountdownConditionSupported="); pw.println(mCountdownConditionSupported);
- pw.print(" mMaxConditions="); pw.println(mMaxConditions);
pw.print(" mRequestingConditions="); pw.println(mRequestingConditions);
pw.print(" mAttached="); pw.println(mAttached);
pw.print(" mHidden="); pw.println(mHidden);
@@ -286,14 +286,6 @@
if (mRequestingConditions == requesting) return;
if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);
mRequestingConditions = requesting;
- if (mController != null) {
- AsyncTask.execute(new Runnable() {
- @Override
- public void run() {
- mController.requestConditions(requesting);
- }
- });
- }
if (mRequestingConditions) {
mTimeCondition = parseExistingTimeCondition(mContext, mExitCondition);
if (mTimeCondition != null) {
@@ -304,6 +296,11 @@
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
}
if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
+
+ mTimeUntilAlarmCondition = parseExistingTimeCondition(mContext, mExitCondition);
+ if (mTimeUntilAlarmCondition == null) {
+ mTimeUntilAlarmCondition = getTimeUntilNextAlarmCondition();
+ }
mConditions = null; // reset conditions
handleUpdateConditions();
} else {
@@ -314,13 +311,9 @@
public void init(ZenModeController controller) {
mController = controller;
mCountdownConditionSupported = mController.isCountdownConditionSupported();
- final int countdownDelta = mCountdownConditionSupported ? 1 : 0;
- mFirstConditionIndex = COUNTDOWN_CONDITION_INDEX + countdownDelta;
+ final int countdownDelta = mCountdownConditionSupported ? 2 : 0;
final int minConditions = 1 /*forever*/ + countdownDelta;
- mMaxConditions = MathUtils.constrain(mContext.getResources()
- .getInteger(R.integer.zen_mode_max_conditions), minConditions, 100);
- mMaxOptionalConditions = mMaxConditions - minConditions;
- for (int i = 0; i < mMaxConditions; i++) {
+ for (int i = 0; i < minConditions; i++) {
mZenConditions.addView(mInflater.inflate(R.layout.zen_mode_condition, this, false));
}
mSessionZen = getSelectedZen(-1);
@@ -357,28 +350,10 @@
return condition == null ? null : condition.copy();
}
- public static String getExitConditionText(Context context, Condition exitCondition) {
- if (exitCondition == null) {
- return foreverSummary(context);
- } else if (isCountdown(exitCondition)) {
- final Condition condition = parseExistingTimeCondition(context, exitCondition);
- return condition != null ? condition.summary : foreverSummary(context);
- } else {
- return exitCondition.summary;
- }
- }
-
public void setCallback(Callback callback) {
mCallback = callback;
}
- public void showSilentHint() {
- if (DEBUG) Log.d(mTag, "showSilentHint");
- if (mZenButtons == null || mZenButtons.getChildCount() == 0) return;
- final View noneButton = mZenButtons.getChildAt(0);
- mIconPulser.start(noneButton);
- }
-
private void handleUpdateManualRule(ZenRule rule) {
final int zen = rule != null ? rule.zenMode : Global.ZEN_MODE_OFF;
handleUpdateZen(zen);
@@ -410,7 +385,7 @@
final ConditionTag tag = getConditionTagAt(i);
if (tag != null) {
if (sameConditionId(tag.condition, mExitCondition)) {
- bind(exitCondition, mZenConditions.getChildAt(i));
+ bind(exitCondition, mZenConditions.getChildAt(i), i);
}
}
}
@@ -495,64 +470,29 @@
final long span = time - now;
if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
return ZenModeConfig.toTimeCondition(context,
- time, Math.round(span / (float) MINUTES_MS), now, ActivityManager.getCurrentUser(),
+ time, Math.round(span / (float) MINUTES_MS), ActivityManager.getCurrentUser(),
false /*shortVersion*/);
}
- private void handleUpdateConditions(Condition[] conditions) {
- conditions = trimConditions(conditions);
- if (Arrays.equals(conditions, mConditions)) {
- final int count = mConditions == null ? 0 : mConditions.length;
- if (DEBUG) Log.d(mTag, "handleUpdateConditions unchanged conditionCount=" + count);
- return;
- }
- mConditions = conditions;
- handleUpdateConditions();
- }
-
- private Condition[] trimConditions(Condition[] conditions) {
- if (conditions == null || conditions.length <= mMaxOptionalConditions) {
- // no need to trim
- return conditions;
- }
- // look for current exit condition, ensure it is included if found
- int found = -1;
- for (int i = 0; i < conditions.length; i++) {
- final Condition c = conditions[i];
- if (mSessionExitCondition != null && sameConditionId(mSessionExitCondition, c)) {
- found = i;
- break;
- }
- }
- final Condition[] rt = Arrays.copyOf(conditions, mMaxOptionalConditions);
- if (found >= mMaxOptionalConditions) {
- // found after the first N, promote to the end of the first N
- rt[mMaxOptionalConditions - 1] = conditions[found];
- }
- return rt;
- }
-
private void handleUpdateConditions() {
if (mTransitionHelper.isTransitioning()) {
- mTransitionHelper.pendingUpdateConditions();
return;
}
final int conditionCount = mConditions == null ? 0 : mConditions.length;
if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);
// forever
- bind(forever(), mZenConditions.getChildAt(FOREVER_CONDITION_INDEX));
+ bind(forever(), mZenConditions.getChildAt(FOREVER_CONDITION_INDEX),
+ FOREVER_CONDITION_INDEX);
// countdown
if (mCountdownConditionSupported && mTimeCondition != null) {
- bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX));
+ bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX),
+ COUNTDOWN_CONDITION_INDEX);
}
- // provider conditions
- for (int i = 0; i < conditionCount; i++) {
- bind(mConditions[i], mZenConditions.getChildAt(mFirstConditionIndex + i));
- }
- // hide the rest
- for (int i = mZenConditions.getChildCount() - 1; i > mFirstConditionIndex + conditionCount;
- i--) {
- mZenConditions.getChildAt(i).setVisibility(GONE);
+ // countdown until alarm
+ if (mCountdownConditionSupported && mTimeUntilAlarmCondition != null) {
+ bind(mTimeUntilAlarmCondition,
+ mZenConditions.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX),
+ COUNTDOWN_ALARM_CONDITION_INDEX);
}
// ensure something is selected
if (mExpanded && isShown()) {
@@ -569,6 +509,33 @@
return context.getString(com.android.internal.R.string.zen_mode_forever);
}
+ // Returns a time condition if the next alarm is within the next week.
+ private Condition getTimeUntilNextAlarmCondition() {
+ GregorianCalendar weekRange = new GregorianCalendar();
+ final long now = weekRange.getTimeInMillis();
+ setToMidnight(weekRange);
+ weekRange.roll(Calendar.DATE, 6);
+ final long nextAlarmMs = mController.getNextAlarm();
+ if (nextAlarmMs > 0) {
+ GregorianCalendar nextAlarm = new GregorianCalendar();
+ nextAlarm.setTimeInMillis(nextAlarmMs);
+ setToMidnight(nextAlarm);
+
+ if (weekRange.compareTo(nextAlarm) >= 0) {
+ return ZenModeConfig.toNextAlarmCondition(mContext, now, nextAlarmMs,
+ ActivityManager.getCurrentUser());
+ }
+ }
+ return null;
+ }
+
+ private void setToMidnight(Calendar calendar) {
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ }
+
private ConditionTag getConditionTagAt(int index) {
return (ConditionTag) mZenConditions.getChildAt(index).getTag();
}
@@ -610,7 +577,8 @@
mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[favoriteIndex], ActivityManager.getCurrentUser());
mBucketIndex = favoriteIndex;
- bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX));
+ bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX),
+ COUNTDOWN_CONDITION_INDEX);
getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
}
}
@@ -623,7 +591,7 @@
return c != null && mForeverId.equals(c.id);
}
- private void bind(final Condition condition, final View row) {
+ private void bind(final Condition condition, final View row, final int rowId) {
if (condition == null) throw new IllegalArgumentException("condition must not be null");
final boolean enabled = condition.state == Condition.STATE_TRUE;
final ConditionTag tag =
@@ -640,8 +608,7 @@
tag.rb.setEnabled(enabled);
final boolean checked = (mSessionExitCondition != null
|| mAttachedZen != Global.ZEN_MODE_OFF)
- && (sameConditionId(mSessionExitCondition, tag.condition)
- || isCountdown(mSessionExitCondition) && isCountdown(tag.condition));
+ && (sameConditionId(mSessionExitCondition, tag.condition));
if (checked != tag.rb.isChecked()) {
if (DEBUG) Log.d(mTag, "bind checked=" + checked + " condition=" + conditionId);
tag.rb.setChecked(checked);
@@ -692,7 +659,7 @@
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- onClickTimeButton(row, tag, false /*down*/);
+ onClickTimeButton(row, tag, false /*down*/, rowId);
}
});
@@ -700,7 +667,7 @@
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- onClickTimeButton(row, tag, true /*up*/);
+ onClickTimeButton(row, tag, true /*up*/, rowId);
}
});
tag.lines.setOnClickListener(new OnClickListener() {
@@ -711,7 +678,7 @@
});
final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
- if (time > 0) {
+ if (rowId != COUNTDOWN_ALARM_CONDITION_INDEX && time > 0) {
button1.setVisibility(VISIBLE);
button2.setVisibility(VISIBLE);
if (mBucketIndex > -1) {
@@ -761,7 +728,7 @@
tag.line1.getText()));
}
- private void onClickTimeButton(View row, ConditionTag tag, boolean up) {
+ private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
MetricsLogger.action(mContext, MetricsLogger.QS_DND_TIME, up);
Condition newCondition = null;
final int N = MINUTE_BUCKETS.length;
@@ -777,7 +744,7 @@
if (up && bucketTime > time || !up && bucketTime < time) {
mBucketIndex = j;
newCondition = ZenModeConfig.toTimeCondition(mContext,
- bucketTime, bucketMinutes, now, ActivityManager.getCurrentUser(),
+ bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
false /*shortVersion*/);
break;
}
@@ -794,7 +761,7 @@
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
}
mTimeCondition = newCondition;
- bind(mTimeCondition, row);
+ bind(mTimeCondition, row, rowId);
tag.rb.setChecked(true);
select(mTimeCondition);
announceConditionSelection(tag);
@@ -838,18 +805,12 @@
private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
@Override
- public void onConditionsChanged(Condition[] conditions) {
- mHandler.obtainMessage(H.UPDATE_CONDITIONS, conditions).sendToTarget();
- }
-
- @Override
public void onManualRuleChanged(ZenRule rule) {
mHandler.obtainMessage(H.MANUAL_RULE_CHANGED, rule).sendToTarget();
}
};
private final class H extends Handler {
- private static final int UPDATE_CONDITIONS = 1;
private static final int MANUAL_RULE_CHANGED = 2;
private static final int UPDATE_WIDGETS = 3;
@@ -860,7 +821,6 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case UPDATE_CONDITIONS: handleUpdateConditions((Condition[]) msg.obj); break;
case MANUAL_RULE_CHANGED: handleUpdateManualRule((ZenRule) msg.obj); break;
case UPDATE_WIDGETS: updateWidgets(); break;
}
@@ -1005,26 +965,20 @@
private final ArraySet<View> mTransitioningViews = new ArraySet<View>();
private boolean mTransitioning;
- private boolean mPendingUpdateConditions;
private boolean mPendingUpdateWidgets;
public void clear() {
mTransitioningViews.clear();
- mPendingUpdateConditions = mPendingUpdateWidgets = false;
+ mPendingUpdateWidgets = false;
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(" TransitionHelper state:");
- pw.print(" mPendingUpdateConditions="); pw.println(mPendingUpdateConditions);
pw.print(" mPendingUpdateWidgets="); pw.println(mPendingUpdateWidgets);
pw.print(" mTransitioning="); pw.println(mTransitioning);
pw.print(" mTransitioningViews="); pw.println(mTransitioningViews);
}
- public void pendingUpdateConditions() {
- mPendingUpdateConditions = true;
- }
-
public void pendingUpdateWidgets() {
mPendingUpdateWidgets = true;
}
@@ -1050,15 +1004,11 @@
@Override
public void run() {
if (DEBUG) Log.d(mTag, "TransitionHelper run"
- + " mPendingUpdateWidgets=" + mPendingUpdateWidgets
- + " mPendingUpdateConditions=" + mPendingUpdateConditions);
+ + " mPendingUpdateWidgets=" + mPendingUpdateWidgets);
if (mPendingUpdateWidgets) {
updateWidgets();
}
- if (mPendingUpdateConditions) {
- handleUpdateConditions();
- }
- mPendingUpdateWidgets = mPendingUpdateConditions = false;
+ mPendingUpdateWidgets = false;
}
private void updateTransitioning() {
@@ -1067,10 +1017,10 @@
mTransitioning = transitioning;
if (DEBUG) Log.d(mTag, "TransitionHelper mTransitioning=" + mTransitioning);
if (!mTransitioning) {
- if (mPendingUpdateConditions || mPendingUpdateWidgets) {
+ if (mPendingUpdateWidgets) {
mHandler.post(this);
} else {
- mPendingUpdateConditions = mPendingUpdateWidgets = false;
+ mPendingUpdateWidgets = false;
}
}
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 882899e..08f0952e 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -971,8 +971,8 @@
// This is a special alarm that will put the system into idle until it goes off.
// The caller has given the time they want this to happen at, however we need
// to pull that earlier if there are existing alarms that have requested to
- // bring us out of idle.
- if (mNextWakeFromIdle != null) {
+ // bring us out of idle at an earlier time.
+ if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) {
a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
}
// Add fuzz to make the alarm go off some time before the actual desired time.
@@ -1256,7 +1256,7 @@
pw.print(" Idling until: ");
if (mPendingIdleUntil != null) {
pw.println(mPendingIdleUntil);
- mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf);
+ mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf);
} else {
pw.println("null");
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 75dda9c..d031165 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -948,13 +948,13 @@
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
}
- if ((uidRules & RULE_REJECT_ALL) != 0
- || (networkCostly && (uidRules & RULE_REJECT_METERED) != 0)) {
+ if (uidRules == RULE_REJECT_ALL) {
return true;
+ } else if ((uidRules == RULE_REJECT_METERED) && networkCostly) {
+ return true;
+ } else {
+ return false;
}
-
- // no restrictive rules; network is visible
- return false;
}
/**
@@ -3215,6 +3215,11 @@
final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN));
final VpnProfile profile = VpnProfile.decode(
profileName, mKeyStore.get(Credentials.VPN + profileName));
+ if (profile == null) {
+ Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
+ setLockdownTracker(null);
+ return true;
+ }
int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized(mVpns) {
setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user),
@@ -3751,7 +3756,7 @@
synchronized(mRulesLock) {
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
}
- if ((uidRules & (RULE_REJECT_METERED | RULE_REJECT_ALL)) != 0) {
+ if (uidRules != RULE_ALLOW_ALL) {
// we could silently fail or we can filter the available nets to only give
// them those they have access to. Chose the more useful
networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 223519d..87b490d 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -246,6 +246,14 @@
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
int plugged = intent.getIntExtra("plugged", 0);
updateChargingLocked(plugged != 0);
+ } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+ if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+ removePowerSaveWhitelistAppInternal(ssp);
+ }
+ }
} else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
synchronized (DeviceIdleController.this) {
stepIdleStateLocked();
@@ -972,6 +980,10 @@
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ACTION_STEP_IDLE_STATE);
getContext().registerReceiver(mReceiver, filter);
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ getContext().registerReceiver(mReceiver, filter);
mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
@@ -984,7 +996,10 @@
public boolean addPowerSaveWhitelistAppInternal(String name) {
synchronized (this) {
try {
- ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0);
+ ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
reportPowerSaveWhitelistChangedLocked();
updateWhitelistAppIdsLocked();
@@ -1610,7 +1625,6 @@
} catch (IOException e) {
}
}
-
}
private void readConfigFileLocked(XmlPullParser parser) {
@@ -1639,7 +1653,10 @@
String name = parser.getAttributeValue(null, "n");
if (name != null) {
try {
- ApplicationInfo ai = pm.getApplicationInfo(name, 0);
+ ApplicationInfo ai = pm.getApplicationInfo(name,
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
mPowerSaveWhitelistUserApps.put(ai.packageName,
UserHandle.getAppId(ai.uid));
} catch (PackageManager.NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 087ddd6..9405d8e0 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -341,8 +341,10 @@
gpsProvider.disable();
}
- FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
- if (FlpHardwareProvider.isSupported() && flpHardwareProvider != null) {
+ // it is needed to check if FLP HW provider is supported before accessing the instance, this
+ // avoids an exception to be thrown by the singleton factory method
+ if (FlpHardwareProvider.isSupported()) {
+ FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
flpHardwareProvider.cleanup();
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 759a4f3..e7601c2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9161,13 +9161,14 @@
}
@Override
- public void resizeStack(int stackId, Rect bounds) {
+ public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"resizeStack()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- mStackSupervisor.resizeStackLocked(stackId, bounds, !PRESERVE_WINDOWS);
+ mStackSupervisor.resizeStackLocked(
+ stackId, bounds, !PRESERVE_WINDOWS, allowResizeInDockedMode);
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index cdb00ef..00664b4 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4572,7 +4572,7 @@
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, false);
if (mTaskPositioner != null) {
- mTaskPositioner.updateDefaultBounds(task, mTaskHistory, info.initialLayout);
+ mTaskPositioner.updateDefaultBounds(task, mTaskHistory, info.layout);
} else if (mBounds != null && task.mResizeable) {
task.updateOverrideConfiguration(mBounds);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index e465009..2a36230 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -97,6 +97,7 @@
import android.service.voice.IVoiceInteractionSession;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
@@ -352,6 +353,10 @@
private final SparseArray<Configuration> mTmpConfigs = new SparseArray<>();
private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
+ // The default minimal size that will be used if the activity doesn't specify its minimal size.
+ // It will be calculated when the default display gets added.
+ private int mDefaultMinimalSizeOfResizeableTask = -1;
+
/**
* Description of a request to start a new activity, which has been held
* due to app switches being disabled.
@@ -432,6 +437,7 @@
throw new IllegalStateException("Default Display does not exist");
}
mActivityDisplays.put(displayId, activityDisplay);
+ calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
}
createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY, true);
@@ -2973,13 +2979,21 @@
}
}
- void resizeStackLocked(int stackId, Rect bounds, boolean preserveWindows) {
+ void resizeStackLocked(int stackId, Rect bounds, boolean preserveWindows,
+ boolean allowResizeInDockedMode) {
final ActivityStack stack = getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
}
+ if (!allowResizeInDockedMode
+ && stackId != DOCKED_STACK_ID && getStack(DOCKED_STACK_ID) != null) {
+ // If the docked stack exist we don't allow resizes of stacks not caused by the docked
+ // stack size changing so things don't get out of sync.
+ return;
+ }
+
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
ActivityRecord r = stack.topRunningActivityLocked();
@@ -3014,7 +3028,7 @@
// docked stack tasks to the fullscreen stack.
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
if (i != DOCKED_STACK_ID && getStack(i) != null) {
- resizeStackLocked(i, null, preserveWindows);
+ resizeStackLocked(i, null, preserveWindows, true);
}
}
@@ -3029,23 +3043,15 @@
} else {
// Docked stacks occupy a dedicated region on screen so the size of all other
// static stacks need to be adjusted so they don't overlap with the docked stack.
- final int leftChange = stack.mBounds.left - bounds.left;
- final int rightChange = stack.mBounds.right - bounds.right;
- final int topChange = stack.mBounds.top - bounds.top;
- final int bottomChange = stack.mBounds.bottom - bounds.bottom;
+ // We get the bounds to use from window manager which has been adjusted for any
+ // screen controls and is also the same for all stacks.
+ mWindowManager.getStackDockedModeBounds(HOME_STACK_ID, tempRect);
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
if (i != DOCKED_STACK_ID) {
ActivityStack otherStack = getStack(i);
if (otherStack != null) {
- tempRect.set(otherStack.mBounds);
- // We adjust the opposing sides of the other stacks to
- // the side in the dock stack that changed.
- tempRect.left -= rightChange;
- tempRect.right -= leftChange;
- tempRect.top -= bottomChange;
- tempRect.bottom -= topChange;
- resizeStackLocked(i, tempRect, PRESERVE_WINDOWS);
+ resizeStackLocked(i, tempRect, PRESERVE_WINDOWS, true);
}
}
}
@@ -3075,6 +3081,8 @@
return;
}
+ adjustForMinimalTaskDimensions(task, bounds);
+
// If this is a forced resize, let it go through even if the bounds is not changing,
// as we might need a relayout due to surface size change (to/from fullscreen).
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
@@ -3123,6 +3131,38 @@
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
+ private void adjustForMinimalTaskDimensions(TaskRecord task, Rect bounds) {
+ if (bounds == null) {
+ return;
+ }
+ int minimalSize = task.mMinimalSize == -1 ? mDefaultMinimalSizeOfResizeableTask
+ : task.mMinimalSize;
+ final boolean adjustWidth = minimalSize > bounds.width();
+ final boolean adjustHeight = minimalSize > bounds.height();
+ if (!(adjustWidth || adjustHeight)) {
+ return;
+ }
+ Rect taskBounds = task.mBounds;
+ if (adjustWidth) {
+ if (taskBounds != null && bounds.right == taskBounds.right) {
+ bounds.left = bounds.right - minimalSize;
+ } else {
+ // Either left bounds match, or neither match, or the previous bounds were
+ // fullscreen and we default to keeping left.
+ bounds.right = bounds.left + minimalSize;
+ }
+ }
+ if (adjustHeight) {
+ if (taskBounds != null && bounds.bottom == taskBounds.bottom) {
+ bounds.top = bounds.bottom - minimalSize;
+ } else {
+ // Either top bounds match, or neither match, or the previous bounds were
+ // fullscreen and we default to keeping top.
+ bounds.bottom = bounds.top + minimalSize;
+ }
+ }
+ }
+
ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
@@ -3228,9 +3268,16 @@
// Apps may depend on onResume()/onPause() being called in pairs.
if (wasResumed) {
stack.mResumedActivity = r;
+ // Move the stack in which we are placing the task to the front. We don't use
+ // ActivityManagerService.setFocusedActivityLocked, because if the activity is
+ // already focused, the call will short-circuit and do nothing.
+ stack.moveToFront(reason);
+ } else {
+ // We need to not only move the stack to the front, but also have the activity
+ // focused. This will achieve both goals.
+ mService.setFocusedActivityLocked(r, reason);
}
- // move the stack in which we are placing the task to the front.
- stack.moveToFront(reason);
+
}
return stack;
@@ -4026,6 +4073,7 @@
return;
}
mActivityDisplays.put(displayId, activityDisplay);
+ calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
}
}
if (newDisplay) {
@@ -4033,6 +4081,16 @@
}
}
+ private void calculateDefaultMinimalSizeOfResizeableTasks(ActivityDisplay display) {
+ if (display.mDisplayId != Display.DEFAULT_DISPLAY) {
+ return;
+ }
+ final float fraction = mService.mContext.getResources().getFraction(com.android.internal.R.
+ fraction.config_displayFractionForDefaultMinimalSizeOfResizeableTask, 1, 1);
+ mDefaultMinimalSizeOfResizeableTask = (int) (fraction * Math.min(
+ display.mDisplayInfo.logicalWidth, display.mDisplayInfo.logicalHeight));
+ }
+
private void handleDisplayRemoved(int displayId) {
synchronized (mService) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
@@ -4193,7 +4251,7 @@
mLockTaskModeTasks.add(task);
if (task.mLockTaskUid == -1) {
- task.mLockTaskUid = task.mCallingUid;
+ task.mLockTaskUid = task.effectiveUid;
}
if (andResume) {
diff --git a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
index 3d45915..4ba1d0d 100644
--- a/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
+++ b/services/core/java/com/android/server/am/LaunchingTaskPositioner.java
@@ -109,22 +109,22 @@
*
* @param task Task for which we want to find bounds that won't collide with other.
* @param tasks Existing tasks with which we don't want to collide.
- * @param initialLayout Optional information from the client about how it would like to be sized
+ * @param layout Optional information from the client about how it would like to be sized
* and positioned.
*/
void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks,
- @Nullable ActivityInfo.InitialLayout initialLayout) {
+ @Nullable ActivityInfo.Layout layout) {
if (!mDefaultStartBoundsConfigurationSet) {
return;
}
- if (initialLayout == null) {
+ if (layout == null) {
positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight);
return;
}
- int width = getFinalWidth(initialLayout);
- int height = getFinalHeight(initialLayout);
- int verticalGravity = initialLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
- int horizontalGravity = initialLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ int width = getFinalWidth(layout);
+ int height = getFinalHeight(layout);
+ int verticalGravity = layout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+ int horizontalGravity = layout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if (verticalGravity == Gravity.TOP) {
if (horizontalGravity == Gravity.RIGHT) {
positionTopRight(task, tasks, width, height);
@@ -140,30 +140,30 @@
} else {
// Some fancy gravity setting that we don't support yet. We just put the activity in the
// center.
- Slog.w(TAG, "Received unsupported gravity: " + initialLayout.gravity
+ Slog.w(TAG, "Received unsupported gravity: " + layout.gravity
+ ", positioning in the center instead.");
positionCenter(task, tasks, width, height);
}
}
- private int getFinalWidth(ActivityInfo.InitialLayout initialLayout) {
+ private int getFinalWidth(ActivityInfo.Layout layout) {
int width = mDefaultFreeformWidth;
- if (initialLayout.width > 0) {
- width = initialLayout.width;
+ if (layout.width > 0) {
+ width = layout.width;
}
- if (initialLayout.widthFraction > 0) {
- width = (int) (mAvailableRect.width() * initialLayout.widthFraction);
+ if (layout.widthFraction > 0) {
+ width = (int) (mAvailableRect.width() * layout.widthFraction);
}
return width;
}
- private int getFinalHeight(ActivityInfo.InitialLayout initialLayout) {
+ private int getFinalHeight(ActivityInfo.Layout layout) {
int height = mDefaultFreeformHeight;
- if (initialLayout.height > 0) {
- height = initialLayout.height;
+ if (layout.height > 0) {
+ height = layout.height;
}
- if (initialLayout.heightFraction > 0) {
- height = (int) (mAvailableRect.height() * initialLayout.heightFraction);
+ if (layout.heightFraction > 0) {
+ height = (int) (mAvailableRect.height() * layout.heightFraction);
}
return height;
}
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index b216114..edd16ef 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -465,7 +465,7 @@
if (!sameActivity) {
continue;
}
- if (maxRecents > 0) {
+ if (maxRecents > 0 && !doTrim) {
--maxRecents;
continue;
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 77dbad4..5d5b5fe 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -217,6 +217,9 @@
// The information is persisted and used to determine the appropriate stack to launch the
// task into on restore.
Rect mLastNonFullscreenBounds = null;
+ // Minimal size for width/height of this task when it's resizeable. -1 means it should use the
+ // default minimal size.
+ final int mMinimalSize;
Configuration mOverrideConfig = Configuration.EMPTY;
@@ -235,6 +238,7 @@
mCallingUid = info.applicationInfo.uid;
mCallingPackage = info.packageName;
setIntent(_intent, info);
+ mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1;
}
TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
@@ -263,6 +267,7 @@
mTaskToReturnTo = HOME_ACTIVITY_TYPE;
userId = UserHandle.getUserId(info.applicationInfo.uid);
lastTaskDescription = _taskDescription;
+ mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1;
}
private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
@@ -310,6 +315,8 @@
mCallingPackage = callingPackage;
mResizeable = resizeable;
mPrivileged = privileged;
+ ActivityInfo info = mActivities.get(0).info;
+ mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1;
}
void touchActiveTime() {
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index bb4dbc3..835ba17 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -74,6 +74,7 @@
// Set to true when the animation context has been fully prepared.
private boolean mPrepared;
+ private boolean mCreatedResources;
private int mMode;
private final DisplayManagerInternal mDisplayManagerInternal;
@@ -169,6 +170,7 @@
}
// Done.
+ mCreatedResources = true;
mPrepared = true;
// Dejanking optimization.
@@ -313,6 +315,34 @@
}
/**
+ * Dismisses the color fade animation resources.
+ *
+ * This function destroys the resources that are created for the color fade
+ * animation but does not clean up the surface.
+ */
+ public void dismissResources() {
+ if (DEBUG) {
+ Slog.d(TAG, "dismissResources");
+ }
+
+ if (mCreatedResources) {
+ attachEglContext();
+ try {
+ destroyScreenshotTexture();
+ destroyGLShaders();
+ destroyGLBuffers();
+ destroyEglSurface();
+ } finally {
+ detachEglContext();
+ }
+ // This is being called with no active context so shouldn't be
+ // needed but is safer to not change for now.
+ GLES20.glFlush();
+ mCreatedResources = false;
+ }
+ }
+
+ /**
* Dismisses the color fade animation surface and cleans up.
*
* To prevent stray photons from leaking out after the color fade has been
@@ -325,17 +355,8 @@
}
if (mPrepared) {
- attachEglContext();
- try {
- destroyScreenshotTexture();
- destroyGLShaders();
- destroyGLBuffers();
- destroyEglSurface();
- } finally {
- detachEglContext();
- }
+ dismissResources();
destroySurface();
- GLES20.glFlush();
mPrepared = false;
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 452378f..7b49530 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -837,6 +837,7 @@
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
+ mPowerState.dismissColorFadeResources();
}
if (target == Display.STATE_ON) {
@@ -910,6 +911,7 @@
// A black surface is already hiding the contents of the screen.
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
+ mPowerState.dismissColorFadeResources();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 2eabd32..9862516 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -187,7 +187,7 @@
}
/**
- * Dismisses the electron beam surface.
+ * Dismisses the color fade surface.
*/
public void dismissColorFade() {
mColorFade.dismiss();
@@ -195,6 +195,13 @@
mColorFadeReady = true;
}
+ /**
+ * Dismisses the color fade resources.
+ */
+ public void dismissColorFadeResources() {
+ mColorFade.dismissResources();
+ }
+
/**
* Sets the level of the electron beam steering current.
*
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 5a13672..5b40375 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -206,6 +206,7 @@
private static native void nativeReloadDeviceAliases(long ptr);
private static native String nativeDump(long ptr);
private static native void nativeMonitor(long ptr);
+ private static native void nativeSetPointerIconShape(long ptr, int iconId);
// Input event injection constants defined in InputDispatcher.h.
private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1407,6 +1408,12 @@
}
}
+ // Binder call
+ @Override
+ public void setPointerIconShape(int iconId) {
+ nativeSetPointerIconShape(mPtr, iconId);
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 06bd583..3c50102 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -73,7 +73,7 @@
*/
public class JobSchedulerService extends com.android.server.SystemService
implements StateChangedListener, JobCompletedListener {
- static final boolean DEBUG = false;
+ public static final boolean DEBUG = false;
/** The number of concurrent jobs we run at one time. */
private static final int MAX_JOB_CONTEXTS_COUNT
= ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
@@ -99,7 +99,7 @@
* Minimum # of connectivity jobs that must be ready in order to force the JMS to schedule
* things early.
*/
- static final int MIN_CONNECTIVITY_COUNT = 2;
+ static final int MIN_CONNECTIVITY_COUNT = 1; // Run connectivity jobs as soon as ready.
/**
* Minimum # of jobs (with no particular constraints) for which the JMS will be happy running
* some work early.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 3991489..17ae6dc 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -39,17 +39,17 @@
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
+import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
+import static android.net.NetworkPolicyManager.RULE_UNKNOWN;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
-import static android.net.NetworkPolicyManager.dumpPolicy;
-import static android.net.NetworkPolicyManager.dumpRules;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
@@ -108,6 +108,7 @@
import android.net.NetworkIdentity;
import android.net.NetworkInfo;
import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
import android.net.NetworkTemplate;
@@ -138,6 +139,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.DebugUtils;
import android.util.Log;
import android.util.NtpTrustedTime;
import android.util.Pair;
@@ -147,8 +149,6 @@
import android.util.TrustedTime;
import android.util.Xml;
-import com.android.server.DeviceIdleController;
-import com.android.server.EventLogTags;
import libcore.io.IoUtils;
import com.android.internal.R;
@@ -156,6 +156,8 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.DeviceIdleController;
+import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.google.android.collect.Lists;
@@ -280,6 +282,12 @@
/** Currently derived rules for each UID. */
final SparseIntArray mUidRules = new SparseIntArray();
+ final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
+ final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+
+ /** Set of states for the child firewall chains. True if the chain is active. */
+ final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
+
/**
* UIDs that have been white-listed to always be able to have network access
* in power save mode, except device idle (doze) still applies.
@@ -444,14 +452,8 @@
// read policy from disk
readPolicyLocked();
- if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
- updateRulesForGlobalChangeLocked(false);
- updateNotificationsLocked();
- } else {
- // If we are not in any special mode, we just need to make sure the current
- // app idle state is updated.
- updateRulesForAppIdleLocked();
- }
+ updateRulesForGlobalChangeLocked(false);
+ updateNotificationsLocked();
}
updateScreenOn();
@@ -1796,7 +1798,9 @@
if (mDeviceIdleMode != enabled) {
mDeviceIdleMode = enabled;
if (mSystemReady) {
- updateRulesForDeviceIdleLocked();
+ // Device idle change means we need to rebuild rules for all
+ // known apps, so do a global refresh.
+ updateRulesForGlobalChangeLocked(false);
}
if (enabled) {
EventLogTags.writeDeviceIdleOnPhase("net");
@@ -1934,7 +1938,7 @@
fout.print("UID=");
fout.print(uid);
fout.print(" policy=");
- dumpPolicy(fout, policy);
+ fout.print(DebugUtils.flagsToString(NetworkPolicyManager.class, "POLICY_", policy));
fout.println();
}
fout.decreaseIndent();
@@ -1979,18 +1983,14 @@
fout.print("UID=");
fout.print(uid);
- int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
fout.print(" state=");
fout.print(state);
fout.print(state <= ActivityManager.PROCESS_STATE_TOP ? " (fg)" : " (bg)");
- fout.print(" rules=");
- final int rulesIndex = mUidRules.indexOfKey(uid);
- if (rulesIndex < 0) {
- fout.print("UNKNOWN");
- } else {
- dumpRules(fout, mUidRules.valueAt(rulesIndex));
- }
+ final int rule = mUidRules.get(uid, RULE_UNKNOWN);
+ fout.print(" rule=");
+ fout.print(DebugUtils.valueToString(NetworkPolicyManager.class, "RULE_", rule));
fout.println();
}
@@ -2025,7 +2025,7 @@
updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState)
!= isProcStateAllowedWhileIdle(uidState)) {
- updateRulesForDeviceIdleLocked();
+ updateRuleForDeviceIdleLocked(uid);
}
}
}
@@ -2039,7 +2039,7 @@
updateRulesForUidStateChangeLocked(uid, oldUidState,
ActivityManager.PROCESS_STATE_CACHED_EMPTY);
if (mDeviceIdleMode) {
- updateRulesForDeviceIdleLocked();
+ updateRuleForDeviceIdleLocked(uid);
}
}
}
@@ -2086,7 +2086,8 @@
if (mDeviceIdleMode) {
// sync the whitelists before enable dozable chain. We don't care about the rules if
// we are disabling the chain.
- SparseIntArray uidRules = new SparseIntArray();
+ final SparseIntArray uidRules = mUidFirewallDozableRules;
+ uidRules.clear();
final List<UserInfo> users = mUserManager.getUsers();
for (int ui = users.size() - 1; ui >= 0; ui--) {
UserInfo user = users.get(ui);
@@ -2110,6 +2111,7 @@
}
setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
}
+
enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
}
@@ -2123,11 +2125,15 @@
setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
}
}
+
+ updateRulesForUidLocked(uid);
}
void updateRulesForAppIdleLocked() {
+ final SparseIntArray uidRules = mUidFirewallStandbyRules;
+ uidRules.clear();
+
// Fully update the app idle firewall chain.
- SparseIntArray uidRules = new SparseIntArray();
final List<UserInfo> users = mUserManager.getUsers();
for (int ui = users.size() - 1; ui >= 0; ui--) {
UserInfo user = users.get(ui);
@@ -2138,6 +2144,7 @@
}
}
}
+
setUidFirewallRules(FIREWALL_CHAIN_STANDBY, uidRules);
}
@@ -2150,11 +2157,14 @@
} else {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
}
+
+ updateRulesForUidLocked(uid);
}
void updateRulesForAppIdleParoleLocked() {
boolean enableChain = !mUsageStats.isAppIdleParoleOn();
enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
+ updateRulesForUidsLocked(mUidFirewallStandbyRules);
}
/**
@@ -2224,6 +2234,12 @@
return true;
}
+ void updateRulesForUidsLocked(SparseIntArray uids) {
+ for (int i = 0; i < uids.size(); i++) {
+ updateRulesForUidLocked(uids.keyAt(i));
+ }
+ }
+
/**
* Applies network rules to bandwidth and firewall controllers based on uid policy.
* @param uid The uid for which to apply the latest policy
@@ -2245,8 +2261,7 @@
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final boolean uidForeground = isUidForegroundLocked(uid);
- // derive active rules based on policy and active state
-
+ // Derive active rules based on policy and active state
int appId = UserHandle.getAppId(uid);
int uidRules = RULE_ALLOW_ALL;
if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
@@ -2269,20 +2284,27 @@
}
}
- final int oldRules = mUidRules.get(uid);
+ // Check dozable state, which is whitelist
+ if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)
+ && mUidFirewallDozableRules.get(uid, FIREWALL_RULE_DEFAULT) != FIREWALL_RULE_ALLOW) {
+ uidRules = RULE_REJECT_ALL;
+ }
+ // Check standby state, which is blacklist
+ if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)
+ && mUidFirewallStandbyRules.get(uid, FIREWALL_RULE_DEFAULT) == FIREWALL_RULE_DENY) {
+ uidRules = RULE_REJECT_ALL;
+ }
+
+ final int oldRules = mUidRules.get(uid);
if (uidRules == RULE_ALLOW_ALL) {
mUidRules.delete(uid);
} else {
mUidRules.put(uid, uidRules);
}
- // Update bandwidth rules if necessary
- final boolean oldRejectMetered = (oldRules & RULE_REJECT_METERED) != 0;
- final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
- if (oldRejectMetered != rejectMetered) {
- setUidNetworkRules(uid, rejectMetered);
- }
+ final boolean rejectMetered = (uidRules == RULE_REJECT_METERED);
+ setUidNetworkRules(uid, rejectMetered);
// dispatch changed rule to existing listeners
if (oldRules != uidRules) {
@@ -2468,6 +2490,12 @@
* Add or remove a uid to the firewall blacklist for all network ifaces.
*/
private void setUidFirewallRule(int chain, int uid, int rule) {
+ if (chain == FIREWALL_CHAIN_DOZABLE) {
+ mUidFirewallDozableRules.put(uid, rule);
+ } else if (chain == FIREWALL_CHAIN_STANDBY) {
+ mUidFirewallStandbyRules.put(uid, rule);
+ }
+
try {
mNetworkManager.setFirewallUidRule(chain, uid, rule);
} catch (IllegalStateException e) {
@@ -2481,6 +2509,12 @@
* Add or remove a uid to the firewall blacklist for all network ifaces.
*/
private void enableFirewallChainLocked(int chain, boolean enable) {
+ if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
+ mFirewallChainStates.get(chain) == enable) {
+ // All is the same, nothing to do.
+ return;
+ }
+ mFirewallChainStates.put(chain, enable);
try {
mNetworkManager.setFirewallChainEnabled(chain, enable);
} catch (IllegalStateException e) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3e27c95..f7f38db 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8471,6 +8471,7 @@
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+ boolean runtimePermissionsRevoked = false;
int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY;
boolean changedInstallPermission = false;
@@ -8480,6 +8481,17 @@
if (!ps.isSharedUser()) {
origPermissions = new PermissionsState(permissionsState);
permissionsState.reset();
+ } else {
+ // We need to know only about runtime permission changes since the
+ // calling code always writes the install permissions state but
+ // the runtime ones are written only if changed. The only cases of
+ // changed runtime permissions here are promotion of an install to
+ // runtime and revocation of a runtime from a shared user.
+ changedRuntimePermissionUserIds = revokeUnusedSharedUserPermissionsLPw(
+ ps.sharedUser, UserManagerService.getInstance().getUserIds());
+ if (!ArrayUtils.isEmpty(changedRuntimePermissionUserIds)) {
+ runtimePermissionsRevoked = true;
+ }
}
}
@@ -8695,9 +8707,11 @@
ps.installPermissionsFixed = true;
}
- // Persist the runtime permissions state for users with changes.
+ // Persist the runtime permissions state for users with changes. If permissions
+ // were revoked because no app in the shared user declares them we have to
+ // write synchronously to avoid losing runtime permissions state.
for (int userId : changedRuntimePermissionUserIds) {
- mSettings.writeRuntimePermissionsForUserLPr(userId, false);
+ mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -12248,6 +12262,66 @@
}
}
+ private int[] revokeUnusedSharedUserPermissionsLPw(SharedUserSetting su, int[] allUserIds) {
+ // Collect all used permissions in the UID
+ ArraySet<String> usedPermissions = new ArraySet<>();
+ final int packageCount = su.packages.size();
+ for (int i = 0; i < packageCount; i++) {
+ PackageSetting ps = su.packages.valueAt(i);
+ if (ps.pkg == null) {
+ continue;
+ }
+ final int requestedPermCount = ps.pkg.requestedPermissions.size();
+ for (int j = 0; j < requestedPermCount; j++) {
+ String permission = ps.pkg.requestedPermissions.get(j);
+ BasePermission bp = mSettings.mPermissions.get(permission);
+ if (bp != null) {
+ usedPermissions.add(permission);
+ }
+ }
+ }
+
+ PermissionsState permissionsState = su.getPermissionsState();
+ // Prune install permissions
+ List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates();
+ final int installPermCount = installPermStates.size();
+ for (int i = installPermCount - 1; i >= 0; i--) {
+ PermissionState permissionState = installPermStates.get(i);
+ if (!usedPermissions.contains(permissionState.getName())) {
+ BasePermission bp = mSettings.mPermissions.get(permissionState.getName());
+ if (bp != null) {
+ permissionsState.revokeInstallPermission(bp);
+ permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+ }
+ }
+ }
+
+ int[] runtimePermissionChangedUserIds = EmptyArray.INT;
+
+ // Prune runtime permissions
+ for (int userId : allUserIds) {
+ List<PermissionState> runtimePermStates = permissionsState
+ .getRuntimePermissionStates(userId);
+ final int runtimePermCount = runtimePermStates.size();
+ for (int i = runtimePermCount - 1; i >= 0; i--) {
+ PermissionState permissionState = runtimePermStates.get(i);
+ if (!usedPermissions.contains(permissionState.getName())) {
+ BasePermission bp = mSettings.mPermissions.get(permissionState.getName());
+ if (bp != null) {
+ permissionsState.revokeRuntimePermission(bp, userId);
+ permissionsState.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+ runtimePermissionChangedUserIds = ArrayUtils.appendInt(
+ runtimePermissionChangedUserIds, userId);
+ }
+ }
+ }
+ }
+
+ return runtimePermissionChangedUserIds;
+ }
+
private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
String volumeUuid, int[] allUsers, boolean[] perUserInstalled, PackageInstalledInfo res,
UserHandle user) {
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 66170d4..5d8b1d2 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -100,6 +100,9 @@
private static final String SEAPP_HASH_FILE =
Environment.getDataDirectory().toString() + "/system/seapp_hash";
+ // Append privapp to existing seinfo label
+ private static final String PRIVILEGED_APP_STR = ":privapp";
+
/**
* Load the mac_permissions.xml file containing all seinfo assignments used to
* label apps. The loaded mac_permissions.xml file is determined by the
@@ -313,6 +316,9 @@
}
}
+ if (pkg.applicationInfo.isPrivilegedApp())
+ pkg.applicationInfo.seinfo += PRIVILEGED_APP_STR;
+
if (DEBUG_POLICY_INSTALL) {
Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
"seinfo=" + pkg.applicationInfo.seinfo);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 341410d..80697ed 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -356,6 +356,27 @@
}
@Override
+ public boolean isSameProfileGroup(int userId, int otherUserId) {
+ if (userId == otherUserId) return true;
+ checkManageUsersPermission("check if in the same profile group");
+ synchronized (mPackagesLock) {
+ return isSameProfileGroupLocked(userId, otherUserId);
+ }
+ }
+
+ private boolean isSameProfileGroupLocked(int userId, int otherUserId) {
+ UserInfo userInfo = getUserInfoLocked(userId);
+ if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ return false;
+ }
+ UserInfo otherUserInfo = getUserInfoLocked(otherUserId);
+ if (otherUserInfo == null || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ return false;
+ }
+ return userInfo.profileGroupId == otherUserInfo.profileGroupId;
+ }
+
+ @Override
public UserInfo getProfileParent(int userHandle) {
checkManageUsersPermission("get the profile parent");
synchronized (mPackagesLock) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 16add37..e354029 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4614,7 +4614,8 @@
final int fl = PolicyControl.getWindowFlags(null, lp);
if (localLOGV) {
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
- + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
+ + " shown position: "
+ + mTopFullscreenOpaqueWindowState.getShownPositionLw());
Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
+ " lp.flags=0x" + Integer.toHexString(fl));
}
diff --git a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
index 4ae3154..db2b941 100644
--- a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
@@ -22,6 +22,7 @@
import android.os.SystemClock;
import android.util.Slog;
import android.view.GestureDetector;
+import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy.PointerEventListener;
import android.widget.OverScroller;
@@ -130,8 +131,7 @@
}
break;
case MotionEvent.ACTION_HOVER_MOVE:
- if (event.getPointerCount() == 1
- && event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
+ if (event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
if (!mMouseHoveringAtEdge && event.getY() == 0) {
mCallbacks.onMouseHoverAtTop();
mMouseHoveringAtEdge = true;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 66ae9ef..d713751 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -206,8 +206,8 @@
sTempFloats[Matrix.MSKEW_Y] = windowState.mWinAnimator.mDtDx;
sTempFloats[Matrix.MSKEW_X] = windowState.mWinAnimator.mDsDy;
sTempFloats[Matrix.MSCALE_Y] = windowState.mWinAnimator.mDtDy;
- sTempFloats[Matrix.MTRANS_X] = windowState.mShownFrame.left;
- sTempFloats[Matrix.MTRANS_Y] = windowState.mShownFrame.top;
+ sTempFloats[Matrix.MTRANS_X] = windowState.mShownPosition.x;
+ sTempFloats[Matrix.MTRANS_Y] = windowState.mShownPosition.y;
sTempFloats[Matrix.MPERSP_0] = 0;
sTempFloats[Matrix.MPERSP_1] = 0;
sTempFloats[Matrix.MPERSP_2] = 1;
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index cc51d20..9f44fea 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -760,26 +760,24 @@
a = createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
containingFrame, surfaceInsets, taskId);
} else {
+ mTmpFromClipRect.set(containingFrame);
+ // exclude top screen decor (status bar) region from the source clip.
+ mTmpFromClipRect.top = contentInsets.top;
// App window scaling up to become full screen
+ mTmpToClipRect.set(containingFrame);
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// In portrait, we scale the width and clip to the top/left square
scale = thumbWidth / appWidth;
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbHeight = (int) (thumbHeight / scale);
- mTmpFromClipRect.set(containingFrame);
- mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
- mTmpToClipRect.set(containingFrame);
+ mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
} else {
// In landscape, we scale the height and clip to the top/left square
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
- mTmpFromClipRect.set(containingFrame);
- mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
- mTmpToClipRect.set(containingFrame);
+ mTmpFromClipRect.right = mTmpFromClipRect.left + unscaledThumbWidth;
}
- // exclude top screen decor (status bar) region from the source clip.
- mTmpFromClipRect.top = contentInsets.top;
mNextAppTransitionInsets.set(contentInsets);
@@ -821,25 +819,23 @@
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
// App window scaling down from full screen
+ mTmpFromClipRect.set(containingFrame);
+ mTmpToClipRect.set(containingFrame);
+ // exclude top screen decor (status bar) region from the destination clip.
+ mTmpToClipRect.top = contentInsets.top;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// In portrait, we scale the width and clip to the top/left square
scale = thumbWidth / appWidth;
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbHeight = (int) (thumbHeight / scale);
- mTmpFromClipRect.set(containingFrame);
- mTmpToClipRect.set(containingFrame);
- mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+ mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
} else {
// In landscape, we scale the height and clip to the top/left square
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
- mTmpFromClipRect.set(containingFrame);
- mTmpToClipRect.set(containingFrame);
- mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
+ mTmpToClipRect.right = mTmpToClipRect.left + unscaledThumbWidth;
}
- // exclude top screen decor (status bar) region from the destination clip.
- mTmpToClipRect.top = contentInsets.top;
mNextAppTransitionInsets.set(contentInsets);
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 3c28648..2d87123 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -206,7 +206,8 @@
}
if (distance <= mSideMargin) {
try {
- mDisplayContent.mService.mActivityManager.resizeStack(mTaskStack.mStackId, null);
+ mDisplayContent.mService.mActivityManager.resizeStack(
+ mTaskStack.mStackId, null, true);
} catch (RemoteException e) {
// This can't happen because we are in the same process.
}
@@ -364,7 +365,7 @@
}
mLastResizeRect.set(mTmpRect);
try {
- mDisplayContent.mService.mActivityManager.resizeStack(DOCKED_STACK_ID, mTmpRect);
+ mDisplayContent.mService.mActivityManager.resizeStack(DOCKED_STACK_ID, mTmpRect, true);
} catch (RemoteException e) {
// This can't happen because we are in the same process.
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index ca358b1..b409cea 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -238,8 +238,8 @@
// Post message to inform activity manager of the bounds change simulating
// a one-way call. We do this to prevent a deadlock between window manager
// lock and activity manager lock been held.
- mService.mH.sendMessage(
- mService.mH.obtainMessage(RESIZE_STACK, mStackId, UNUSED, mBounds));
+ mService.mH.sendMessage(mService.mH.obtainMessage(
+ RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mBounds));
}
}
}
@@ -399,8 +399,11 @@
if (dockedStack != null) {
dockedStack.getRawBounds(mTmpRect2);
}
- getInitialDockedStackBounds(mTmpRect, bounds, mStackId, mTmpRect2,
- mDisplayContent.mDividerControllerLocked.getWidthAdjustment());
+ final boolean dockedOnTopOrLeft = WindowManagerService.sDockedStackCreateMode
+ == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+ getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
+ mDisplayContent.mDividerControllerLocked.getWidthAdjustment(),
+ dockedOnTopOrLeft);
}
updateDisplayInfo(bounds);
@@ -413,28 +416,60 @@
}
}
+ void getStackDockedModeBoundsLocked(Rect outBounds) {
+ if (mStackId == DOCKED_STACK_ID
+ || mStackId > LAST_STATIC_STACK_ID
+ || mDisplayContent == null) {
+ outBounds.set(mBounds);
+ return;
+ }
+
+ final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
+ if (dockedStack == null) {
+ // Not sure why you are calling this method when there is no docked stack...
+ throw new IllegalStateException(
+ "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
+ }
+
+ @DockSide
+ final int dockedSide = dockedStack.getDockSide();
+ if (dockedSide == DOCKED_INVALID) {
+ // Not sure how you got here...Only thing we can do is return current bounds.
+ Slog.e(TAG, "Failed to get valid docked side for docked stack=" + dockedStack);
+ outBounds.set(mBounds);
+ return;
+ }
+
+ mDisplayContent.getLogicalDisplayRect(mTmpRect);
+ dockedStack.getRawBounds(mTmpRect2);
+ final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
+ getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
+ mDisplayContent.mDividerControllerLocked.getWidthAdjustment(), dockedOnTopOrLeft);
+
+ }
+
/**
- * Outputs the initial bounds a stack should be given the presence of a docked stack on the
- * display.
+ * Outputs the bounds a stack should be given the presence of a docked stack on the display.
* @param displayRect The bounds of the display the docked stack is on.
* @param outBounds Output bounds that should be used for the stack.
* @param stackId Id of stack we are calculating the bounds for.
* @param dockedBounds Bounds of the docked stack.
- * @param adjustment
+ * @param adjustment Additional adjustment to make to the output bounds close to the side of the
+ * dock.
+ * @param dockOntopOrLeft If the docked stack is on the top or left side of the screen.
*/
- private static void getInitialDockedStackBounds(
- Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int adjustment) {
+ private static void getStackDockedModeBounds(
+ Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int adjustment,
+ boolean dockOntopOrLeft) {
final boolean dockedStack = stackId == DOCKED_STACK_ID;
final boolean splitHorizontally = displayRect.width() > displayRect.height();
- final boolean topOrLeftCreateMode =
- WindowManagerService.sDockedStackCreateMode == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
outBounds.set(displayRect);
if (dockedStack) {
// The initial bounds of the docked stack when it is created half the screen space and
// its bounds can be adjusted after that. The bounds of all other stacks are adjusted
// to occupy whatever screen space the docked stack isn't occupying.
- if (topOrLeftCreateMode) {
+ if (dockOntopOrLeft) {
if (splitHorizontally) {
outBounds.right = displayRect.centerX() - adjustment;
} else {
@@ -451,7 +486,7 @@
}
// Other stacks occupy whatever space is left by the docked stack.
- if (!topOrLeftCreateMode) {
+ if (!dockOntopOrLeft) {
if (splitHorizontally) {
outBounds.right = dockedBounds.left - adjustment;
} else {
@@ -477,8 +512,10 @@
final Rect bounds = new Rect();
mDisplayContent.getLogicalDisplayRect(bounds);
if (!fullscreen) {
- getInitialDockedStackBounds(bounds, bounds, FULLSCREEN_WORKSPACE_STACK_ID, dockedBounds,
- mDisplayContent.mDividerControllerLocked.getWidth());
+ final boolean dockedOnTopOrLeft = WindowManagerService.sDockedStackCreateMode
+ == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+ getStackDockedModeBounds(bounds, bounds, FULLSCREEN_WORKSPACE_STACK_ID, dockedBounds,
+ mDisplayContent.mDividerControllerLocked.getWidth(), dockedOnTopOrLeft);
}
final int count = mService.mStackIdToStack.size();
@@ -489,7 +526,8 @@
&& otherStackId >= FIRST_STATIC_STACK_ID
&& otherStackId <= LAST_STATIC_STACK_ID) {
mService.mH.sendMessage(
- mService.mH.obtainMessage(RESIZE_STACK, otherStackId, UNUSED, bounds));
+ mService.mH.obtainMessage(RESIZE_STACK, otherStackId,
+ 1 /*allowResizeInDockedMode*/, bounds));
}
}
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 1a946b2..7f2f2cd 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -419,7 +419,7 @@
winAnimator.computeShownFrameLocked();
// No need to lay out the windows - we can just set the wallpaper position
// directly.
- winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
+ winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
// We only want to be synchronous with one wallpaper.
sync = false;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0932f15..f571d9c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4617,6 +4617,17 @@
}
}
+ public void getStackDockedModeBounds(int stackId, Rect bounds) {
+ synchronized (mWindowMap) {
+ final TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack != null) {
+ stack.getStackDockedModeBoundsLocked(bounds);
+ return;
+ }
+ bounds.setEmpty();
+ }
+ }
+
public void getStackBounds(int stackId, Rect bounds) {
synchronized (mWindowMap) {
final TaskStack stack = mStackIdToStack.get(stackId);
@@ -7779,7 +7790,7 @@
break;
case RESIZE_STACK: {
try {
- mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj);
+ mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj, msg.arg2 == 1);
} catch (RemoteException e) {
// This will not happen since we are in the same process.
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 383ad8c..e72d35c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -29,15 +29,14 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION;
-import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerService.DEBUG_POWER;
import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
-import android.app.ActivityManager;
import android.app.AppOpsManager;
+import android.graphics.Point;
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.SystemClock;
@@ -159,11 +158,10 @@
private boolean mConfigHasChanged;
/**
- * Actual frame shown on-screen (may be modified by animation). These
- * are in the screen's coordinate space (WITH the compatibility scale
- * applied).
+ * Actual position of the surface shown on-screen (may be modified by animation). These are
+ * in the screen's coordinate space (WITH the compatibility scale applied).
*/
- final RectF mShownFrame = new RectF();
+ final Point mShownPosition = new Point();
/**
* Insets that determine the actually visible area. These are in the application's
@@ -787,8 +785,8 @@
}
@Override
- public RectF getShownFrameLw() {
- return mShownFrame;
+ public Point getShownPositionLw() {
+ return mShownPosition;
}
@Override
@@ -1822,7 +1820,7 @@
}
}
pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
- pw.print(" mShownFrame="); mShownFrame.printShortString(pw);
+ pw.print(" mShownPosition="); mShownPosition.printShortString(pw);
pw.print(" isReadyForDisplay()="); pw.println(isReadyForDisplay());
if (dumpAll) {
pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 2733933..1913604 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1190,9 +1190,7 @@
mDtDy = tmpFloats[Matrix.MSCALE_Y];
float x = tmpFloats[Matrix.MTRANS_X];
float y = tmpFloats[Matrix.MTRANS_Y];
- int w = frame.width();
- int h = frame.height();
- mWin.mShownFrame.set(x, y, x+w, y+h);
+ mWin.mShownPosition.set((int) x, (int) y);
// Now set the alpha... but because our current hardware
// can't do alpha transformation on a non-opaque surface,
@@ -1287,13 +1285,13 @@
float y = tmpFloats[Matrix.MTRANS_Y];
int w = frame.width();
int h = frame.height();
- mWin.mShownFrame.set(x, y, x + w, y + h);
+ mWin.mShownPosition.set((int) x, (int) y);
mShownAlpha = mAlpha;
} else {
- mWin.mShownFrame.set(mWin.mFrame);
+ mWin.mShownPosition.set(mWin.mFrame.left, mWin.mFrame.top);
if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
- mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
+ mWin.mShownPosition.offset(mWin.mXOffset, mWin.mYOffset);
}
mShownAlpha = mAlpha;
mHaveMatrix = false;
@@ -1458,8 +1456,8 @@
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
- float left = w.mShownFrame.left;
- float top = w.mShownFrame.top;
+ float left = w.mShownPosition.x;
+ float top = w.mShownPosition.y;
int width;
int height;
@@ -1701,10 +1699,10 @@
}
}
- void setWallpaperOffset(RectF shownFrame) {
+ void setWallpaperOffset(Point shownPosition) {
final LayoutParams attrs = mWin.getAttrs();
- final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
- final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
+ final int left = shownPosition.x - attrs.surfaceInsets.left;
+ final int top = shownPosition.y - attrs.surfaceInsets.top;
if (mSurfaceX != left || mSurfaceY != top) {
if (mAnimating) {
// If this window (or its app token) is animating, then the position
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 112646a..247562f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -717,7 +717,8 @@
/*
* Updates the shown frame before we set up the surface. This is needed because
* the resizing could change the top-left position (in addition to size) of the
- * window. setSurfaceBoundariesLocked uses mShownFrame to position the surface.
+ * window. setSurfaceBoundariesLocked uses mShownPosition to position the
+ * surface.
*/
winAnimator.computeShownFrameLocked();
winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 1d4f047..8cb0a13 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -199,6 +199,7 @@
void setShowTouches(bool enabled);
void setInteractive(bool interactive);
void reloadCalibration();
+ void setPointerIconShape(int32_t iconId);
/* --- InputReaderPolicyInterface implementation --- */
@@ -237,6 +238,7 @@
/* --- PointerControllerPolicyInterface implementation --- */
virtual void loadPointerResources(PointerResources* outResources);
+ virtual void loadAdditionalMouseResources(std::map<int, SpriteIcon>* outResources);
private:
sp<InputManager> mInputManager;
@@ -779,6 +781,15 @@
InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION);
}
+void NativeInputManager::setPointerIconShape(int32_t iconId) {
+ AutoMutex _l(mLock);
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ if (controller != NULL) {
+ // Use 0 (the default icon) for ARROW.
+ controller->updatePointerShape((iconId == POINTER_ICON_STYLE_ARROW) ? 0 : iconId);
+ }
+}
+
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
JNIEnv *env, jfloatArray matrixArr) {
ScopedFloatArrayRO matrix(env, matrixArr);
@@ -1029,6 +1040,15 @@
&outResources->spotAnchor);
}
+void NativeInputManager::loadAdditionalMouseResources(std::map<int, SpriteIcon>* outResources) {
+ JNIEnv* env = jniEnv();
+
+ for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING;
+ ++iconId) {
+ loadSystemIconAsSprite(env, mContextObj, iconId, &((*outResources)[iconId]));
+ }
+}
+
// ----------------------------------------------------------------------------
@@ -1367,6 +1387,11 @@
im->getInputManager()->getDispatcher()->monitor();
}
+static void nativeSetPointerIconShape(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint iconId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ im->setPointerIconShape(iconId);
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputManagerMethods[] = {
@@ -1425,6 +1450,8 @@
(void*) nativeDump },
{ "nativeMonitor", "(J)V",
(void*) nativeMonitor },
+ { "nativeSetPointerIconShape", "(JI)V",
+ (void*) nativeSetPointerIconShape },
};
#define FIND_CLASS(var, className) \
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 8b37ec4..13e600e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -314,6 +314,8 @@
mAppIdleParoled = paroled;
if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleParoled);
if (paroled) {
+ postParoleEndTimeout();
+ } else {
mLastAppIdleParoledTime = checkAndGetTimeLocked();
postNextParoleTimeout();
}
@@ -404,8 +406,6 @@
if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
setAppIdleParoled(true);
- // Make sure it ends at some point
- postParoleEndTimeout();
} else {
if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
postNextParoleTimeout();
@@ -492,7 +492,6 @@
if (!deviceIdle
&& timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
- postNextParoleTimeout();
setAppIdleParoled(true);
} else if (deviceIdle) {
if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
index 3ca0c84..31d859f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
@@ -87,6 +87,7 @@
// This is an indirect indication of the microphone being open in some other application.
private boolean mServiceDisabled = false;
private boolean mStarted = false;
+ private boolean mRecognitionAborted = false;
private PowerSaveModeListener mPowerSaveModeListener;
SoundTriggerHelper(Context context) {
@@ -386,8 +387,9 @@
private void onRecognitionAbortLocked() {
Slog.w(TAG, "Recognition aborted");
- // No-op
- // This is handled via service state changes instead.
+ // If abort has been called, the hardware has already stopped recognition, so we shouldn't
+ // call it again when we process the state change.
+ mRecognitionAborted = true;
}
private void onRecognitionFailureLocked() {
@@ -490,8 +492,13 @@
}
return status;
} else {
- // Stop recognition.
- int status = mModule.stopRecognition(mCurrentSoundModelHandle);
+ // Stop recognition (only if we haven't been aborted).
+ int status = STATUS_OK;
+ if (!mRecognitionAborted) {
+ status = mModule.stopRecognition(mCurrentSoundModelHandle);
+ } else {
+ mRecognitionAborted = false;
+ }
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "stopRecognition call failed with " + status);
if (notify) {
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 5c64168..abb8803 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -584,9 +584,8 @@
out.writeInt(1);
mIcon.writeToParcel(out, flags);
}
-
- out.writeBundle(mExtras);
out.writeByte((byte) (mIsEnabled ? 1 : 0));
+ out.writeBundle(mExtras);
}
public static final Creator<PhoneAccount> CREATOR
@@ -628,8 +627,8 @@
} else {
mIcon = null;
}
- mExtras = in.readBundle();
mIsEnabled = in.readByte() == 1;
+ mExtras = in.readBundle();
}
@Override
@@ -645,7 +644,7 @@
sb.append(scheme)
.append(" ");
}
- sb.append(" Extras : ");
+ sb.append(" Extras: ");
sb.append(mExtras);
sb.append("]");
return sb.toString();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ba91254..7cf5f73 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -191,7 +191,7 @@
public static final String
KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
- /**
+ /**
* Override the platform's notion of a network operator being considered roaming.
* Value is string array of MCCMNCs to be considered roaming for 3GPP RATs.
*/
@@ -468,6 +468,12 @@
*/
public static final String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
+ /**
+ * Allow user to add APNs
+ * @hide
+ */
+ public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
+
// These variables are used by the MMS service and exposed through another API, {@link
// SmsManager}. The variable names and string values are copied from there.
public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -567,6 +573,7 @@
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING, "");
sDefaults.putBoolean(KEY_CSP_ENABLED_BOOL, false);
+ sDefaults.putBoolean(KEY_ALLOW_ADDING_APNS_BOOL, true);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index f535e5d..fced667 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -911,7 +911,7 @@
else if (tdScdmaDbm >= -49) level = SIGNAL_STRENGTH_GREAT;
else if (tdScdmaDbm >= -73) level = SIGNAL_STRENGTH_GOOD;
else if (tdScdmaDbm >= -97) level = SIGNAL_STRENGTH_MODERATE;
- else if (tdScdmaDbm >= -120) level = SIGNAL_STRENGTH_POOR;
+ else if (tdScdmaDbm >= -110) level = SIGNAL_STRENGTH_POOR;
else level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
if (DBG) log("getTdScdmaLevel = " + level);
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 37ffa06..e11c8d3 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -334,7 +334,8 @@
@Override
public String toString() {
- return "{id=" + mId + ", iccId=" + mIccId + " simSlotIndex=" + mSimSlotIndex
+ String iccIdToPrint = mIccId != null ? mIccId.substring(0, 9) + "XXXXXXXXXXX" : null;
+ return "{id=" + mId + ", iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
+ " displayName=" + mDisplayName + " carrierName=" + mCarrierName
+ " nameSource=" + mNameSource + " iconTint=" + mIconTint
+ " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index b2dc29a..93b3f4f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -73,6 +73,7 @@
import android.os.Parcel;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -1130,6 +1131,11 @@
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return false;
}
+
+ @Override
+ public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ResultReceiver resultReceiver) {
+ }
};
}
return mBinder;