Merge "Performe save when ENTER is pressed."
diff --git a/api/current.txt b/api/current.txt
index ef18bf9..9fe6857 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2876,6 +2876,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 +2892,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 {
@@ -18173,6 +18175,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..5e1aa41 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2975,6 +2975,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 +2991,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 {
@@ -19685,6 +19687,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/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 4b3df30..6f65889 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -536,9 +536,6 @@
return mDuration;
}
- /**
- * @hide
- */
@Override
public long getTotalDuration() {
if (mRepeatCount == INFINITE) {
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/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/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 7752ed8..4bc2112 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20995,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/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_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/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/config.xml b/core/res/res/values/config.xml
index 24d760f..6e956d7 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>
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..953b98f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2078,6 +2078,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 +2327,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 049da2d..7164747 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -865,6 +865,47 @@
}
@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);
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 ddfc533..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/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/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..ac513e4 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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f914b20..d031165 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -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),
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/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/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/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/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/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/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/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);