Merge "Filter products during compile phase"
diff --git a/api/current.txt b/api/current.txt
index eb6ad09..4a1a458 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4760,6 +4760,7 @@
method public android.graphics.drawable.Icon getLargeIcon();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
+ method public android.app.Notification.Topic[] getTopics();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4924,6 +4925,7 @@
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
+ method public android.app.Notification.Builder addTopic(android.app.Notification.Topic);
method public android.app.Notification build();
method public android.app.Notification.Builder extend(android.app.Notification.Extender);
method public android.os.Bundle getExtras();
@@ -5031,6 +5033,16 @@
field protected android.app.Notification.Builder mBuilder;
}
+ public static class Notification.Topic implements android.os.Parcelable {
+ ctor public Notification.Topic(java.lang.String, java.lang.CharSequence);
+ method public android.app.Notification.Topic clone();
+ method public int describeContents();
+ method public java.lang.String getId();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR;
+ }
+
public static final class Notification.WearableExtender implements android.app.Notification.Extender {
ctor public Notification.WearableExtender();
ctor public Notification.WearableExtender(android.app.Notification);
diff --git a/api/system-current.txt b/api/system-current.txt
index 64ea3b8..ecea9b0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4877,6 +4877,7 @@
method public android.graphics.drawable.Icon getLargeIcon();
method public android.graphics.drawable.Icon getSmallIcon();
method public java.lang.String getSortKey();
+ method public android.app.Notification.Topic[] getTopics();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -5041,6 +5042,7 @@
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
method public android.app.Notification.Builder addPerson(java.lang.String);
+ method public android.app.Notification.Builder addTopic(android.app.Notification.Topic);
method public android.app.Notification build();
method public android.app.Notification.Builder extend(android.app.Notification.Extender);
method public android.os.Bundle getExtras();
@@ -5148,6 +5150,16 @@
field protected android.app.Notification.Builder mBuilder;
}
+ public static class Notification.Topic implements android.os.Parcelable {
+ ctor public Notification.Topic(java.lang.String, java.lang.CharSequence);
+ method public android.app.Notification.Topic clone();
+ method public int describeContents();
+ method public java.lang.String getId();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR;
+ }
+
public static final class Notification.WearableExtender implements android.app.Notification.Extender {
ctor public Notification.WearableExtender();
ctor public Notification.WearableExtender(android.app.Notification);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 81da6af..1e2e33d 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -120,7 +120,7 @@
out.println(
"usage: am [subcommand] [options]\n" +
"usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
- " [--sampling INTERVAL] [-R COUNT] [-S] [--opengl-trace]\n" +
+ " [--sampling INTERVAL] [-R COUNT] [-S]\n" +
" [--track-allocation] [--user <USER_ID> | current] <INTENT>\n" +
" am startservice [--user <USER_ID> | current] <INTENT>\n" +
" am stopservice [--user <USER_ID> | current] <INTENT>\n" +
@@ -182,7 +182,6 @@
" -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" +
" the top activity will be finished.\n" +
" -S: force stop the target app before starting the activity\n" +
- " --opengl-trace: enable tracing of OpenGL functions\n" +
" --track-allocation: enable tracking of object allocations\n" +
" --user <USER_ID> | current: Specify which user to run as; if not\n" +
" specified then run as the current user.\n" +
@@ -739,8 +738,6 @@
mRepeat = Integer.parseInt(nextArgRequired());
} else if (opt.equals("-S")) {
mStopOption = true;
- } else if (opt.equals("--opengl-trace")) {
- mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
} else if (opt.equals("--track-allocation")) {
mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
} else if (opt.equals("--user")) {
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 26c886e..0b751b2 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -23,9 +23,9 @@
import android.graphics.PointF;
import android.util.Log;
import android.util.Property;
+import android.view.animation.AccelerateDecelerateInterpolator;
import java.lang.ref.WeakReference;
-import java.util.ArrayList;
/**
* This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
@@ -53,7 +53,8 @@
* from the target object when the animator starts, just like animators with only one
* value specified. In addition, an optional interpolator can be specified. The interpolator will
* be applied on the interval between the keyframe that the interpolator is set on and the previous
- * keyframe. When no interpolator is supplied, the default linear interpolator will be used. </p>
+ * keyframe. When no interpolator is supplied, the default {@link AccelerateDecelerateInterpolator}
+ * will be used. </p>
*
* {@sample development/samples/ApiDemos/res/anim/object_animator_pvh_kf_interpolated.xml KeyframeResources}
*
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d47c0aa..2f0849f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -705,6 +705,8 @@
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
private static final String SAVED_DIALOG_ARGS_KEY_PREFIX = "android:dialog_args_";
+ private static final String HAS_CURENT_PERMISSIONS_REQUEST_KEY =
+ "android:hasCurrentPermissionsRequest";
private static final String REQUEST_PERMISSIONS_WHO_PREFIX = "@android:requestPermissions:";
@@ -813,6 +815,8 @@
SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
+ private boolean mHasCurrentPermissionsRequest;
+
/** Return the intent that started this activity. */
public Intent getIntent() {
return mIntent;
@@ -1314,6 +1318,7 @@
onSaveInstanceState(outState);
saveManagedDialogs(outState);
mActivityTransitionState.saveState(outState);
+ storeHasCurrentPermissionRequest(outState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
}
@@ -1329,6 +1334,7 @@
final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
onSaveInstanceState(outState, outPersistentState);
saveManagedDialogs(outState);
+ storeHasCurrentPermissionRequest(outState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
", " + outPersistentState);
}
@@ -3862,8 +3868,15 @@
* @see #shouldShowRequestPermissionRationale(String)
*/
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
+ if (mHasCurrentPermissionsRequest) {
+ Log.w(TAG, "Can reqeust only one set of permissions at a time");
+ // Dispatch the callback with empty arrays which means a cancellation.
+ onRequestPermissionsResult(requestCode, new String[0], new int[0]);
+ return;
+ }
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
+ mHasCurrentPermissionsRequest = true;
}
/**
@@ -6301,12 +6314,14 @@
}
final void performCreate(Bundle icicle) {
+ restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
+ restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
performCreateCommon();
@@ -6489,6 +6504,19 @@
return mResumed;
}
+ private void storeHasCurrentPermissionRequest(Bundle bundle) {
+ if (bundle != null && mHasCurrentPermissionsRequest) {
+ bundle.putBoolean(HAS_CURENT_PERMISSIONS_REQUEST_KEY, true);
+ }
+ }
+
+ private void restoreHasCurrentPermissionRequest(Bundle bundle) {
+ if (bundle != null) {
+ mHasCurrentPermissionsRequest = bundle.getBoolean(
+ HAS_CURENT_PERMISSIONS_REQUEST_KEY, false);
+ }
+ }
+
void dispatchActivityResult(String who, int requestCode,
int resultCode, Intent data) {
if (false) Log.v(
@@ -6616,6 +6644,7 @@
}
private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
+ mHasCurrentPermissionsRequest = false;
// If the package installer crashed we may have not data - best effort.
String[] permissions = (data != null) ? data.getStringArrayExtra(
PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0];
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 61a9a84..3bfeff0 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -204,17 +204,10 @@
/**
* Flag for IActivityManaqer.startActivity: launch the app for
- * OpenGL tracing.
- * @hide
- */
- public static final int START_FLAG_OPENGL_TRACES = 1<<2;
-
- /**
- * Flag for IActivityManaqer.startActivity: launch the app for
* allocation tracking.
* @hide
*/
- public static final int START_FLAG_TRACK_ALLOCATION = 1<<3;
+ public static final int START_FLAG_TRACK_ALLOCATION = 1<<2;
/**
* Result for IActivityManaqer.broadcastIntent: success!
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index beaf3cf..b9292de 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -469,7 +469,6 @@
IUiAutomationConnection instrumentationUiAutomationConnection;
int debugMode;
boolean enableBinderTracking;
- boolean enableOpenGlTrace;
boolean trackAllocation;
boolean restrictedBackupMode;
boolean persistent;
@@ -805,10 +804,9 @@
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
- boolean enableBinderTracking, boolean enableOpenGlTrace,
- boolean trackAllocation, boolean isRestrictedBackupMode,
- boolean persistent, Configuration config, CompatibilityInfo compatInfo,
- Map<String, IBinder> services, Bundle coreSettings) {
+ boolean enableBinderTracking, boolean trackAllocation,
+ boolean isRestrictedBackupMode, boolean persistent, Configuration config,
+ CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
@@ -864,7 +862,6 @@
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
- data.enableOpenGlTrace = enableOpenGlTrace;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
@@ -4776,11 +4773,6 @@
}
}
- // Enable OpenGL tracing if required
- if (data.enableOpenGlTrace) {
- GLUtils.setTracingLevel(1);
- }
-
// Allow application-generated systrace messages if we're debuggable.
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(isAppDebuggable);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index bead625..bfd9ca5 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -294,7 +294,6 @@
IUiAutomationConnection.Stub.asInterface(binder);
int testMode = data.readInt();
boolean enableBinderTracking = data.readInt() != 0;
- boolean openGlTrace = data.readInt() != 0;
boolean trackAllocation = data.readInt() != 0;
boolean restrictedBackupMode = (data.readInt() != 0);
boolean persistent = (data.readInt() != 0);
@@ -304,8 +303,8 @@
Bundle coreSettings = data.readBundle();
bindApplication(packageName, info, providers, testName, profilerInfo, testArgs,
testWatcher, uiAutomationConnection, testMode, enableBinderTracking,
- openGlTrace, trackAllocation, restrictedBackupMode, persistent, config,
- compatInfo, services, coreSettings);
+ trackAllocation, restrictedBackupMode, persistent, config, compatInfo, services,
+ coreSettings);
return true;
}
@@ -1020,10 +1019,9 @@
List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo,
Bundle testArgs, IInstrumentationWatcher testWatcher,
IUiAutomationConnection uiAutomationConnection, int debugMode,
- boolean enableBinderTracking, boolean openGlTrace, boolean trackAllocation,
- boolean restrictedBackupMode, boolean persistent, Configuration config,
- CompatibilityInfo compatInfo, Map<String, IBinder> services,
- Bundle coreSettings) throws RemoteException {
+ boolean enableBinderTracking, boolean trackAllocation, boolean restrictedBackupMode,
+ boolean persistent, Configuration config, CompatibilityInfo compatInfo,
+ Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeString(packageName);
@@ -1046,7 +1044,6 @@
data.writeStrongInterface(uiAutomationConnection);
data.writeInt(debugMode);
data.writeInt(enableBinderTracking ? 1 : 0);
- data.writeInt(openGlTrace ? 1 : 0);
data.writeInt(trackAllocation ? 1 : 0);
data.writeInt(restrictedBackupMode ? 1 : 0);
data.writeInt(persistent ? 1 : 0);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 51d6132..046c87a 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2221,6 +2221,7 @@
// This fragment was retained from a previous instance; get it
// going now.
fragment.mInLayout = true;
+ fragment.mHost = mHost;
// If this fragment is newly instantiated (either right now, or
// from last saved state), then give it the attributes to
// initialize itself.
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 2d78e19..99e8853 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -96,10 +96,10 @@
void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,
IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
- int debugMode, boolean enableBinderTracking, boolean openGlTrace,
- boolean trackAllocation, boolean restrictedBackupMode, boolean persistent,
- Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
- Bundle coreSettings) throws RemoteException;
+ int debugMode, boolean enableBinderTracking, boolean trackAllocation,
+ boolean restrictedBackupMode, boolean persistent, Configuration config,
+ CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings)
+ throws RemoteException;
void scheduleExit() throws RemoteException;
void scheduleSuicide() throws RemoteException;
void scheduleConfigurationChanged(Configuration config) throws RemoteException;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 55aec59..db18722 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -62,6 +62,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* A class that represents how a persistent notification is to be presented to
@@ -1362,6 +1363,95 @@
public Notification publicVersion;
/**
+ * Structure to encapsulate a topic that is shown in Notification settings.
+ * It must include an id and label.
+ */
+ public static class Topic implements Parcelable {
+ private final String id;
+ private final CharSequence label;
+
+ public Topic(String id, CharSequence label) {
+ this.id = id;
+ this.label = safeCharSequence(label);
+ }
+
+ private Topic(Parcel in) {
+ if (in.readInt() != 0) {
+ id = in.readString();
+ } else {
+ id = null;
+ }
+ label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public CharSequence getLabel() {
+ return label;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(Topic.class.getSimpleName()).append('[')
+ .append("id=").append(id)
+ .append(",label=").append(label)
+ .append(']').toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Topic)) return false;
+ if (o == this) return true;
+ final Topic other = (Topic) o;
+ return Objects.equals(other.id, id)
+ && Objects.equals(other.label, label);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, label);
+ }
+
+ @Override
+ public Topic clone() {
+ return new Topic(id, label);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ if (id != null) {
+ out.writeInt(1);
+ out.writeString(id);
+ } else {
+ out.writeInt(0);
+ }
+ TextUtils.writeToParcel(label, out, flags);
+ }
+ public static final Parcelable.Creator<Topic> CREATOR =
+ new Parcelable.Creator<Topic>() {
+ public Topic createFromParcel(Parcel in) {
+ return new Topic(in);
+ }
+ public Topic[] newArray(int size) {
+ return new Topic[size];
+ }
+ };
+ }
+
+ private Topic[] topics;
+
+ public Topic[] getTopics() {
+ return topics;
+ }
+
+ /**
* Constructs a Notification object with default values.
* You might want to consider using {@link Builder} instead.
*/
@@ -1487,6 +1577,8 @@
}
color = parcel.readInt();
+
+ topics = parcel.createTypedArray(Topic.CREATOR); // may be null
}
@Override
@@ -1587,6 +1679,13 @@
that.color = this.color;
+ if (this.topics != null) {
+ that.topics = new Topic[this.topics.length];
+ for(int i=0; i<this.topics.length; i++) {
+ that.topics[i] = this.topics[i].clone();
+ }
+ }
+
if (!heavy) {
that.lightenPayload(); // will clean out extras
}
@@ -1759,6 +1858,8 @@
}
parcel.writeInt(color);
+
+ parcel.writeTypedArray(topics, 0); // null ok
}
/**
@@ -1895,6 +1996,18 @@
sb.append(" publicVersion=");
sb.append(publicVersion.toString());
}
+ if (topics != null) {
+ sb.append("topics=[");
+ int N = topics.length;
+ if (N > 0) {
+ for (int i = 0; i < N-1; i++) {
+ sb.append(topics[i]);
+ sb.append(',');
+ }
+ sb.append(topics[N-1]);
+ }
+ sb.append("]");
+ }
sb.append(")");
return sb.toString();
}
@@ -2105,6 +2218,7 @@
private final NotificationColorUtil mColorUtil;
private ArrayList<String> mPeople;
private int mColor = COLOR_DEFAULT;
+ private List<Topic> mTopics = new ArrayList<>();
/**
* The user that built the notification originally.
@@ -2874,6 +2988,19 @@
return this;
}
+ /**
+ * Add a topic to this notification. Topics are typically displayed in Notification
+ * settings.
+ * <p>
+ * Every topic must have an id and a textual label.
+ *
+ * @param topic The topic to add.
+ */
+ public Builder addTopic(Topic topic) {
+ mTopics.add(topic);
+ return this;
+ }
+
private Drawable getProfileBadgeDrawable() {
// Note: This assumes that the current user can read the profile badge of the
// originating user.
@@ -3364,6 +3491,10 @@
n.publicVersion = new Notification();
mPublicVersion.cloneInto(n.publicVersion, true);
}
+ if (mTopics.size() > 0) {
+ n.topics = new Topic[mTopics.size()];
+ mTopics.toArray(n.topics);
+ }
// Note: If you're adding new fields, also update restoreFromNotitification().
return n;
}
@@ -3605,6 +3736,10 @@
mPublicVersion = n.publicVersion;
+ if (n.topics != null) {
+ Collections.addAll(mTopics, n.topics);
+ }
+
// Extras.
Bundle extras = n.extras;
mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
diff --git a/core/java/android/content/PeriodicSync.java b/core/java/android/content/PeriodicSync.java
index 3efd89a..0441ccc 100644
--- a/core/java/android/content/PeriodicSync.java
+++ b/core/java/android/content/PeriodicSync.java
@@ -21,6 +21,8 @@
import android.os.Parcel;
import android.accounts.Account;
+import java.util.Objects;
+
/**
* Value type that contains information about a periodic sync.
*/
@@ -144,7 +146,9 @@
if (!b2.containsKey(key)) {
return false;
}
- if (!b1.get(key).equals(b2.get(key))) {
+ // Null check. According to ContentResolver#validateSyncExtrasBundle null-valued keys
+ // are allowed in the bundle.
+ if (!Objects.equals(b1.get(key), b2.get(key))) {
return false;
}
}
diff --git a/core/java/android/ddm/DdmHandleViewDebug.java b/core/java/android/ddm/DdmHandleViewDebug.java
index be48633..5539dc9 100644
--- a/core/java/android/ddm/DdmHandleViewDebug.java
+++ b/core/java/android/ddm/DdmHandleViewDebug.java
@@ -16,7 +16,6 @@
package android.ddm;
-import android.opengl.GLUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewDebug;
@@ -41,9 +40,6 @@
* Support for these features are advertised via {@link DdmHandleHello}.
*/
public class DdmHandleViewDebug extends ChunkHandler {
- /** Enable/Disable tracing of OpenGL calls. */
- public static final int CHUNK_VUGL = type("VUGL");
-
/** List {@link ViewRootImpl}'s of this process. */
private static final int CHUNK_VULW = type("VULW");
@@ -97,7 +93,6 @@
private DdmHandleViewDebug() {}
public static void register() {
- DdmServer.registerHandler(CHUNK_VUGL, sInstance);
DdmServer.registerHandler(CHUNK_VULW, sInstance);
DdmServer.registerHandler(CHUNK_VURT, sInstance);
DdmServer.registerHandler(CHUNK_VUOP, sInstance);
@@ -115,9 +110,7 @@
public Chunk handleChunk(Chunk request) {
int type = request.type;
- if (type == CHUNK_VUGL) {
- return handleOpenGlTrace(request);
- } else if (type == CHUNK_VULW) {
+ if (type == CHUNK_VULW) {
return listWindows();
}
@@ -165,12 +158,6 @@
}
}
- private Chunk handleOpenGlTrace(Chunk request) {
- ByteBuffer in = wrapChunk(request);
- GLUtils.setTracingLevel(in.getInt());
- return null; // empty response
- }
-
/** Returns the list of windows owned by this client. */
private Chunk listWindows() {
String[] windowNames = WindowManagerGlobal.getInstance().getViewRootNames();
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 30cdfd3..2fe8fb6 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -78,14 +78,14 @@
sSensorModuleInitialized = true;
nativeClassInit();
}
- }
- // initialize the sensor list
- for (int index = 0;;++index) {
- Sensor sensor = new Sensor();
- if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
- mFullSensorsList.add(sensor);
- mHandleToSensor.append(sensor.getHandle(), sensor);
+ // initialize the sensor list
+ for (int index = 0;;++index) {
+ Sensor sensor = new Sensor();
+ if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
+ mFullSensorsList.add(sensor);
+ mHandleToSensor.append(sensor.getHandle(), sensor);
+ }
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8e86a53..1aa5c66 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -169,7 +169,7 @@
/**
* Current version of checkin data format.
*/
- static final String CHECKIN_VERSION = "15";
+ static final String CHECKIN_VERSION = "16";
/**
* Old version, we hit 9 and ran out of room, need to remove.
@@ -468,8 +468,8 @@
* @param cluster the index of the CPU cluster.
* @param step the index of the CPU speed. This is not the actual speed of the CPU.
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
- * @see PowerProfile.getNumCpuClusters()
- * @see PowerProfile.getNumSpeedStepsInCpuCluster(int)
+ * @see com.android.internal.os.PowerProfile#getNumCpuClusters()
+ * @see com.android.internal.os.PowerProfile#getNumSpeedStepsInCpuCluster(int)
*/
public abstract long getTimeAtCpuSpeed(int cluster, int step, int which);
@@ -1135,14 +1135,15 @@
public static final int STATE2_WIFI_RUNNING_FLAG = 1<<29;
public static final int STATE2_WIFI_ON_FLAG = 1<<28;
public static final int STATE2_FLASHLIGHT_FLAG = 1<<27;
- public static final int STATE2_DEVICE_IDLE_FLAG = 1<<26;
- public static final int STATE2_CHARGING_FLAG = 1<<25;
- public static final int STATE2_PHONE_IN_CALL_FLAG = 1<<24;
- public static final int STATE2_BLUETOOTH_ON_FLAG = 1<<23;
- public static final int STATE2_CAMERA_FLAG = 1<<22;
+ public static final int STATE2_DEVICE_IDLE_SHIFT = 25;
+ public static final int STATE2_DEVICE_IDLE_MASK = 0x3 << STATE2_DEVICE_IDLE_SHIFT;
+ public static final int STATE2_CHARGING_FLAG = 1<<24;
+ public static final int STATE2_PHONE_IN_CALL_FLAG = 1<<23;
+ public static final int STATE2_BLUETOOTH_ON_FLAG = 1<<22;
+ public static final int STATE2_CAMERA_FLAG = 1<<21;
public static final int MOST_INTERESTING_STATES2 =
- STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_FLAG
+ STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_MASK
| STATE2_CHARGING_FLAG | STATE2_PHONE_IN_CALL_FLAG | STATE2_BLUETOOTH_ON_FLAG;
public static final int SETTLE_TO_ZERO_STATES2 = 0xffff0000 & ~MOST_INTERESTING_STATES2;
@@ -1620,36 +1621,57 @@
public abstract int getPowerSaveModeEnabledCount(int which);
/**
+ * Constant for device idle mode: not active.
+ */
+ public static final int DEVICE_IDLE_MODE_OFF = 0;
+
+ /**
+ * Constant for device idle mode: active in lightweight mode.
+ */
+ public static final int DEVICE_IDLE_MODE_LIGHT = 1;
+
+ /**
+ * Constant for device idle mode: active in full mode.
+ */
+ public static final int DEVICE_IDLE_MODE_FULL = 2;
+
+ /**
* Returns the time in microseconds that device has been in idle mode while
* running on battery.
*
* {@hide}
*/
- public abstract long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which);
+ public abstract long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which);
/**
* Returns the number of times that the devie has gone in to idle mode.
*
* {@hide}
*/
- public abstract int getDeviceIdleModeEnabledCount(int which);
+ public abstract int getDeviceIdleModeCount(int mode, int which);
+
+ /**
+ * Return the longest duration we spent in a particular device idle mode (fully in the
+ * mode, not in idle maintenance etc).
+ */
+ public abstract long getLongestDeviceIdleModeTime(int mode);
/**
* Returns the time in microseconds that device has been in idling while on
- * battery. This is broader than {@link #getDeviceIdleModeEnabledTime} -- it
+ * battery. This is broader than {@link #getDeviceIdleModeTime} -- it
* counts all of the time that we consider the device to be idle, whether or not
* it is currently in the actual device idle mode.
*
* {@hide}
*/
- public abstract long getDeviceIdlingTime(long elapsedRealtimeUs, int which);
+ public abstract long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which);
/**
* Returns the number of times that the devie has started idling.
*
* {@hide}
*/
- public abstract int getDeviceIdlingCount(int which);
+ public abstract int getDeviceIdlingCount(int mode, int which);
/**
* Returns the number of times that connectivity state changed.
@@ -1847,7 +1869,10 @@
new BitDescription(HistoryItem.STATE2_WIFI_RUNNING_FLAG, "wifi_running", "Ww"),
new BitDescription(HistoryItem.STATE2_WIFI_ON_FLAG, "wifi", "W"),
new BitDescription(HistoryItem.STATE2_FLASHLIGHT_FLAG, "flashlight", "fl"),
- new BitDescription(HistoryItem.STATE2_DEVICE_IDLE_FLAG, "device_idle", "di"),
+ new BitDescription(HistoryItem.STATE2_DEVICE_IDLE_MASK,
+ HistoryItem.STATE2_DEVICE_IDLE_SHIFT, "device_idle", "di",
+ new String[] { "off", "light", "full", "???" },
+ new String[] { "off", "light", "full", "???" }),
new BitDescription(HistoryItem.STATE2_CHARGING_FLAG, "charging", "ch"),
new BitDescription(HistoryItem.STATE2_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
new BitDescription(HistoryItem.STATE2_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
@@ -2529,8 +2554,14 @@
final long screenOnTime = getScreenOnTime(rawRealtime, which);
final long interactiveTime = getInteractiveTime(rawRealtime, which);
final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
- final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
- final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
+ final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT,
+ rawRealtime, which);
+ final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL,
+ rawRealtime, which);
+ final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT,
+ rawRealtime, which);
+ final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_FULL,
+ rawRealtime, which);
final int connChanges = getNumConnectivityChange(which);
final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
@@ -2613,11 +2644,15 @@
fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000,
getMobileRadioActiveTime(rawRealtime, which) / 1000,
getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
- powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000,
- getDeviceIdleModeEnabledCount(which), deviceIdlingTime / 1000,
- getDeviceIdlingCount(which),
+ powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeFullTime / 1000,
+ getDeviceIdleModeCount(DEVICE_IDLE_MODE_FULL, which), deviceIdlingTime / 1000,
+ getDeviceIdlingCount(DEVICE_IDLE_MODE_FULL, which),
getMobileRadioActiveCount(which),
- getMobileRadioActiveUnknownTime(which) / 1000);
+ getMobileRadioActiveUnknownTime(which) / 1000, deviceIdleModeLightTime / 1000,
+ getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which), deviceLightIdlingTime / 1000,
+ getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which),
+ getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT),
+ getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL));
// Dump screen brightness stats
Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -3082,8 +3117,14 @@
final long screenOnTime = getScreenOnTime(rawRealtime, which);
final long interactiveTime = getInteractiveTime(rawRealtime, which);
final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
- final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
- final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
+ final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT,
+ rawRealtime, which);
+ final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL,
+ rawRealtime, which);
+ final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT,
+ rawRealtime, which);
+ final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_FULL,
+ rawRealtime, which);
final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
final long wifiOnTime = getWifiOnTime(rawRealtime, which);
@@ -3127,26 +3168,54 @@
sb.append(")");
pw.println(sb.toString());
}
- if (deviceIdlingTime != 0) {
+ if (deviceLightIdlingTime != 0) {
sb.setLength(0);
sb.append(prefix);
- sb.append(" Device idling: ");
- formatTimeMs(sb, deviceIdlingTime / 1000);
+ sb.append(" Device light idling: ");
+ formatTimeMs(sb, deviceLightIdlingTime / 1000);
sb.append("(");
- sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
- sb.append(") "); sb.append(getDeviceIdlingCount(which));
+ sb.append(formatRatioLocked(deviceLightIdlingTime, whichBatteryRealtime));
+ sb.append(") "); sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
sb.append("x");
pw.println(sb.toString());
}
- if (deviceIdleModeEnabledTime != 0) {
+ if (deviceIdleModeLightTime != 0) {
sb.setLength(0);
sb.append(prefix);
- sb.append(" Idle mode time: ");
- formatTimeMs(sb, deviceIdleModeEnabledTime / 1000);
+ sb.append(" Idle mode light time: ");
+ formatTimeMs(sb, deviceIdleModeLightTime / 1000);
sb.append("(");
- sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime));
- sb.append(") "); sb.append(getDeviceIdleModeEnabledCount(which));
+ sb.append(formatRatioLocked(deviceIdleModeLightTime, whichBatteryRealtime));
+ sb.append(") ");
+ sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
sb.append("x");
+ sb.append(" -- longest ");
+ formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
+ pw.println(sb.toString());
+ }
+ if (deviceIdlingTime != 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Device full idling: ");
+ formatTimeMs(sb, deviceIdlingTime / 1000);
+ sb.append("(");
+ sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
+ sb.append(") "); sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_FULL, which));
+ sb.append("x");
+ pw.println(sb.toString());
+ }
+ if (deviceIdleModeFullTime != 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Idle mode full time: ");
+ formatTimeMs(sb, deviceIdleModeFullTime / 1000);
+ sb.append("(");
+ sb.append(formatRatioLocked(deviceIdleModeFullTime, whichBatteryRealtime));
+ sb.append(") ");
+ sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_FULL, which));
+ sb.append("x");
+ sb.append(" -- longest ");
+ formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL));
pw.println(sb.toString());
}
if (phoneOnTime != 0) {
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 9fdbec3..dd10df3 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -47,6 +47,7 @@
boolean isPowerSaveMode();
boolean setPowerSaveMode(boolean mode);
boolean isDeviceIdleMode();
+ boolean isLightDeviceIdleMode();
void reboot(boolean confirm, String reason, boolean wait);
void shutdown(boolean confirm, String reason, boolean wait);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 69974fa..1cffa83 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -910,6 +910,26 @@
}
/**
+ * Returns true if the device is currently in light idle mode. This happens when a device
+ * has had its screen off for a short time, switching it into a batching mode where we
+ * execute jobs, syncs, networking on a batching schedule. You can monitor for changes to
+ * this state with {@link #ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED}.
+ *
+ * @return Returns true if currently in active light device idle mode, else false. This is
+ * when light idle mode restrictions are being actively applied; it will return false if the
+ * device is in a long-term idle mode but currently running a maintenance window where
+ * restrictions have been lifted.
+ * @hide
+ */
+ public boolean isLightDeviceIdleMode() {
+ try {
+ return mService.isLightDeviceIdleMode();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
* Return whether the given application package name is on the device's power whitelist.
* Apps can be placed on the whitelist through the settings UI invoked by
* {@link android.provider.Settings#ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}.
@@ -961,6 +981,15 @@
= "android.os.action.DEVICE_IDLE_MODE_CHANGED";
/**
+ * Intent that is broadcast when the state of {@link #isLightDeviceIdleMode()} changes.
+ * This broadcast is only sent to registered receivers.
+ * @hide
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
+ = "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
+
+ /**
* @hide Intent that is broadcast when the set of power save whitelist apps has changed.
* This broadcast is only sent to registered receivers.
*/
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index b6d0fcb..9801e1b 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -148,7 +148,9 @@
public void onLowPowerModeChanged(boolean enabled);
}
- public abstract void setDeviceIdleMode(boolean enabled);
+ public abstract boolean setDeviceIdleMode(boolean enabled);
+
+ public abstract boolean setLightDeviceIdleMode(boolean enabled);
public abstract void setDeviceIdleWhitelist(int[] appids);
diff --git a/core/java/android/test/AndroidTestCase.java b/core/java/android/test/AndroidTestCase.java
index 0635559..2ecbfae 100644
--- a/core/java/android/test/AndroidTestCase.java
+++ b/core/java/android/test/AndroidTestCase.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.test.suitebuilder.annotation.Suppress;
import junit.framework.TestCase;
@@ -44,6 +45,7 @@
super.tearDown();
}
+ @Suppress
public void testAndroidTestCaseSetupProperly() {
assertNotNull("Context is null. setContext should be called before tests are run",
mContext);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6ece091..6a33579 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -627,7 +627,9 @@
chooseHt = getParagraphSpans(spanned, paraStart, paraEnd, LineHeightSpan.class);
- if (chooseHt.length != 0) {
+ if (chooseHt.length == 0) {
+ chooseHt = null; // So that out() would not assume it has any contents
+ } else {
if (chooseHtv == null ||
chooseHtv.length < chooseHt.length) {
chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length);
@@ -810,7 +812,7 @@
v = out(source, here, endPos,
fmAscent, fmDescent, fmTop, fmBottom,
- v, spacingmult, spacingadd, chooseHt,chooseHtv, fm, flags[breakIndex],
+ v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex],
needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad,
chs, widths, paraStart, ellipsize, ellipsizedWidth,
lineWidths[breakIndex], paint, moreChars);
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index c82587b..6d1d893 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -432,23 +432,24 @@
return anim;
}
} else {
- int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X);
- int startY = (Integer) startValues.values.get(PROPNAME_WINDOW_Y);
- int endX = (Integer) endValues.values.get(PROPNAME_WINDOW_X);
- int endY = (Integer) endValues.values.get(PROPNAME_WINDOW_Y);
+ sceneRoot.getLocationInWindow(tempLocation);
+ int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X) - tempLocation[0];
+ int startY = (Integer) startValues.values.get(PROPNAME_WINDOW_Y) - tempLocation[1];
+ int endX = (Integer) endValues.values.get(PROPNAME_WINDOW_X) - tempLocation[0];
+ int endY = (Integer) endValues.values.get(PROPNAME_WINDOW_Y) - tempLocation[1];
// TODO: also handle size changes: check bounds and animate size changes
if (startX != endX || startY != endY) {
- sceneRoot.getLocationInWindow(tempLocation);
- Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
- Bitmap.Config.ARGB_8888);
+ final int width = view.getWidth();
+ final int height = view.getHeight();
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
final BitmapDrawable drawable = new BitmapDrawable(bitmap);
+ drawable.setBounds(startX, startY, startX + width, startY + height);
final float transitionAlpha = view.getTransitionAlpha();
view.setTransitionAlpha(0);
sceneRoot.getOverlay().add(drawable);
- Path topLeftPath = getPathMotion().getPath(startX - tempLocation[0],
- startY - tempLocation[1], endX - tempLocation[0], endY - tempLocation[1]);
+ Path topLeftPath = getPathMotion().getPath(startX, startY, endX, endY);
PropertyValuesHolder origin = PropertyValuesHolder.ofObject(
DRAWABLE_ORIGIN_PROPERTY, null, topLeftPath);
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, origin);
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index e200bef..aa29636 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -547,9 +547,9 @@
// Don't retain static reference on context.
mConstructorArgs[0] = lastContext;
mConstructorArgs[1] = null;
- }
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
return result;
}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3cddbf6..3b9b8db 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -117,7 +117,7 @@
void noteWifiRadioPowerState(int powerState, long timestampNs);
void noteNetworkInterfaceType(String iface, int type);
void noteNetworkStatsEnabled();
- void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid);
+ void noteDeviceIdleMode(int mode, String activeReason, int activeUid);
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java
index b90cb36..6cc8ba9 100644
--- a/core/java/com/android/internal/logging/MetricsConstants.java
+++ b/core/java/com/android/internal/logging/MetricsConstants.java
@@ -262,6 +262,24 @@
public static final int TUNER_DEMO_MODE_ON = 236;
public static final int TUNER_BATTERY_PERCENTAGE = 237;
public static final int FUELGAUGE_INACTIVE_APPS = 238;
+ public static final int ACTION_ASSIST_LONG_PRESS = 239;
+ public static final int FINGERPRINT_ENROLLING = 240;
+ public static final int FINGERPRINT_FIND_SENSOR = 241;
+ public static final int FINGERPRINT_ENROLL_FINISH = 242;
+ public static final int FINGERPRINT_ENROLL_INTRO = 243;
+ public static final int FINGERPRINT_ENROLL_ONBOARD = 244;
+ public static final int FINGERPRINT_ENROLL_SIDECAR = 245;
+ public static final int FINGERPRINT_ENROLLING_SETUP = 246;
+ public static final int FINGERPRINT_FIND_SENSOR_SETUP = 247;
+ public static final int FINGERPRINT_ENROLL_FINISH_SETUP = 248;
+ public static final int FINGERPRINT_ENROLL_INTRO_SETUP = 249;
+ public static final int FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
+ public static final int ACTION_FINGERPRINT_ENROLL = 251;
+ public static final int ACTION_FINGERPRINT_AUTH = 252;
+ public static final int ACTION_FINGERPRINT_DELETE = 253;
+ public static final int ACTION_FINGERPRINT_RENAME = 254;
+ public static final int ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
+ public static final int ACTION_WIGGLE_CAMERA_GESTURE = 256;
// These constants must match those in the analytic pipeline, do not edit.
// Add temporary values to the top of MetricsLogger instead.
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index c25db65..2c5e50c 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -27,25 +27,6 @@
*/
public class MetricsLogger implements MetricsConstants {
// Temporary constants go here, to await migration to MetricsConstants.
- // next value is 239;
- public static final int ACTION_ASSIST_LONG_PRESS = 239;
- public static final int FINGERPRINT_ENROLLING = 240;
- public static final int FINGERPRINT_FIND_SENSOR = 241;
- public static final int FINGERPRINT_ENROLL_FINISH = 242;
- public static final int FINGERPRINT_ENROLL_INTRO = 243;
- public static final int FINGERPRINT_ENROLL_ONBOARD = 244;
- public static final int FINGERPRINT_ENROLL_SIDECAR = 245;
- public static final int FINGERPRINT_ENROLLING_SETUP = 246;
- public static final int FINGERPRINT_FIND_SENSOR_SETUP = 247;
- public static final int FINGERPRINT_ENROLL_FINISH_SETUP = 248;
- public static final int FINGERPRINT_ENROLL_INTRO_SETUP = 249;
- public static final int FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
- public static final int ACTION_FINGERPRINT_ENROLL = 251;
- public static final int ACTION_FINGERPRINT_AUTH = 252;
- public static final int ACTION_FINGERPRINT_DELETE = 253;
- public static final int ACTION_FINGERPRINT_RENAME = 254;
- public static final int ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
- public static final int ACTION_WIGGLE_CAMERA_GESTURE = 256;
public static final int QS_LOCK_TILE = 257;
public static final int QS_USER_TILE = 258;
public static final int QS_BATTERY_TILE = 259;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 64b7768..f73df00 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 132 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 135 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -338,8 +338,15 @@
boolean mDeviceIdling;
StopwatchTimer mDeviceIdlingTimer;
- boolean mDeviceIdleModeEnabled;
- StopwatchTimer mDeviceIdleModeEnabledTimer;
+ boolean mDeviceLightIdling;
+ StopwatchTimer mDeviceLightIdlingTimer;
+
+ int mDeviceIdleMode;
+ long mLastIdleTimeStart;
+ long mLongestLightIdleTime;
+ long mLongestFullIdleTime;
+ StopwatchTimer mDeviceIdleModeLightTimer;
+ StopwatchTimer mDeviceIdleModeFullTimer;
boolean mPhoneOn;
StopwatchTimer mPhoneOnTimer;
@@ -3219,42 +3226,69 @@
}
}
- public void noteDeviceIdleModeLocked(boolean enabled, String activeReason, int activeUid) {
+ public void noteDeviceIdleModeLocked(int mode, String activeReason, int activeUid) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
- boolean nowIdling = enabled;
- if (mDeviceIdling && !enabled && activeReason == null) {
+ boolean nowIdling = mode == DEVICE_IDLE_MODE_FULL;
+ if (mDeviceIdling && !nowIdling && activeReason == null) {
// We don't go out of general idling mode until explicitly taken out of
// device idle through going active or significant motion.
nowIdling = true;
}
+ boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
+ if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
+ // We don't go out of general light idling mode until explicitly taken out of
+ // device idle through going active or significant motion.
+ nowLightIdling = true;
+ }
+ if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
+ activeReason, activeUid);
+ }
if (mDeviceIdling != nowIdling) {
mDeviceIdling = nowIdling;
int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
- if (enabled) {
+ if (nowIdling) {
mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
} else {
mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
}
}
- if (mDeviceIdleModeEnabled != enabled) {
- mDeviceIdleModeEnabled = enabled;
- addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
- activeReason != null ? activeReason : "", activeUid);
- if (enabled) {
- mHistoryCur.states2 |= HistoryItem.STATE2_DEVICE_IDLE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode enabled to: "
- + Integer.toHexString(mHistoryCur.states2));
- mDeviceIdleModeEnabledTimer.startRunningLocked(elapsedRealtime);
+ if (mDeviceLightIdling != nowLightIdling) {
+ mDeviceLightIdling = nowLightIdling;
+ if (nowLightIdling) {
+ mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
} else {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_DEVICE_IDLE_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode disabled to: "
- + Integer.toHexString(mHistoryCur.states2));
- mDeviceIdleModeEnabledTimer.stopRunningLocked(elapsedRealtime);
+ mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
}
+ }
+ if (mDeviceIdleMode != mode) {
+ mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
+ | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
+ if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
+ + Integer.toHexString(mHistoryCur.states2));
addHistoryRecordLocked(elapsedRealtime, uptime);
+ long lastDuration = elapsedRealtime - mLastIdleTimeStart;
+ mLastIdleTimeStart = elapsedRealtime;
+ if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
+ if (lastDuration > mLongestLightIdleTime) {
+ mLongestLightIdleTime = lastDuration;
+ }
+ mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
+ } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_FULL) {
+ if (lastDuration > mLongestFullIdleTime) {
+ mLongestFullIdleTime = lastDuration;
+ }
+ mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
+ }
+ if (mode == DEVICE_IDLE_MODE_LIGHT) {
+ mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
+ } else if (mode == DEVICE_IDLE_MODE_FULL) {
+ mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
+ }
+ mDeviceIdleMode = mode;
}
}
@@ -4140,20 +4174,55 @@
return mPowerSaveModeEnabledTimer.getCountLocked(which);
}
- @Override public long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which) {
- return mDeviceIdleModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+ @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
+ int which) {
+ switch (mode) {
+ case DEVICE_IDLE_MODE_LIGHT:
+ return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+ case DEVICE_IDLE_MODE_FULL:
+ return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+ }
+ return 0;
}
- @Override public int getDeviceIdleModeEnabledCount(int which) {
- return mDeviceIdleModeEnabledTimer.getCountLocked(which);
+ @Override public int getDeviceIdleModeCount(int mode, int which) {
+ switch (mode) {
+ case DEVICE_IDLE_MODE_LIGHT:
+ return mDeviceIdleModeLightTimer.getCountLocked(which);
+ case DEVICE_IDLE_MODE_FULL:
+ return mDeviceIdleModeFullTimer.getCountLocked(which);
+ }
+ return 0;
}
- @Override public long getDeviceIdlingTime(long elapsedRealtimeUs, int which) {
- return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+ @Override public long getLongestDeviceIdleModeTime(int mode) {
+ switch (mode) {
+ case DEVICE_IDLE_MODE_LIGHT:
+ return mLongestLightIdleTime;
+ case DEVICE_IDLE_MODE_FULL:
+ return mLongestFullIdleTime;
+ }
+ return 0;
}
- @Override public int getDeviceIdlingCount(int which) {
- return mDeviceIdlingTimer.getCountLocked(which);
+ @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
+ switch (mode) {
+ case DEVICE_IDLE_MODE_LIGHT:
+ return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+ case DEVICE_IDLE_MODE_FULL:
+ return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+ }
+ return 0;
+ }
+
+ @Override public int getDeviceIdlingCount(int mode, int which) {
+ switch (mode) {
+ case DEVICE_IDLE_MODE_LIGHT:
+ return mDeviceLightIdlingTimer.getCountLocked(which);
+ case DEVICE_IDLE_MODE_FULL:
+ return mDeviceIdlingTimer.getCountLocked(which);
+ }
+ return 0;
}
@Override public int getNumConnectivityChange(int which) {
@@ -6855,7 +6924,9 @@
}
mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase);
mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
- mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
+ mDeviceIdleModeLightTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
+ mDeviceIdleModeFullTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase);
+ mDeviceLightIdlingTimer = new StopwatchTimer(null, -15, null, mOnBatteryTimeBase);
mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase);
mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -7484,7 +7555,11 @@
}
mInteractiveTimer.reset(false);
mPowerSaveModeEnabledTimer.reset(false);
- mDeviceIdleModeEnabledTimer.reset(false);
+ mLongestLightIdleTime = 0;
+ mLongestFullIdleTime = 0;
+ mDeviceIdleModeLightTimer.reset(false);
+ mDeviceIdleModeFullTimer.reset(false);
+ mDeviceLightIdlingTimer.reset(false);
mDeviceIdlingTimer.reset(false);
mPhoneOnTimer.reset(false);
mAudioOnTimer.reset(false);
@@ -9224,7 +9299,11 @@
mInteractiveTimer.readSummaryFromParcelLocked(in);
mPhoneOn = false;
mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
- mDeviceIdleModeEnabledTimer.readSummaryFromParcelLocked(in);
+ mLongestLightIdleTime = in.readLong();
+ mLongestFullIdleTime = in.readLong();
+ mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
+ mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
+ mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
mPhoneOnTimer.readSummaryFromParcelLocked(in);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -9558,7 +9637,11 @@
}
mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
- mDeviceIdleModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ out.writeLong(mLongestLightIdleTime);
+ out.writeLong(mLongestFullIdleTime);
+ mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -9892,7 +9975,11 @@
mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase, in);
mPhoneOn = false;
mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
- mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
+ mLongestLightIdleTime = in.readLong();
+ mLongestFullIdleTime = in.readLong();
+ mDeviceIdleModeLightTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase, in);
+ mDeviceIdleModeFullTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
+ mDeviceLightIdlingTimer = new StopwatchTimer(null, -15, null, mOnBatteryTimeBase, in);
mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase, in);
mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -10053,7 +10140,11 @@
}
mInteractiveTimer.writeToParcel(out, uSecRealtime);
mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
- mDeviceIdleModeEnabledTimer.writeToParcel(out, uSecRealtime);
+ out.writeLong(mLongestLightIdleTime);
+ out.writeLong(mLongestFullIdleTime);
+ mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
+ mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
+ mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
mPhoneOnTimer.writeToParcel(out, uSecRealtime);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -10188,8 +10279,12 @@
mInteractiveTimer.logState(pr, " ");
pr.println("*** Power save mode timer:");
mPowerSaveModeEnabledTimer.logState(pr, " ");
- pr.println("*** Device idle mode timer:");
- mDeviceIdleModeEnabledTimer.logState(pr, " ");
+ pr.println("*** Device idle mode light timer:");
+ mDeviceIdleModeLightTimer.logState(pr, " ");
+ pr.println("*** Device idle mode full timer:");
+ mDeviceIdleModeFullTimer.logState(pr, " ");
+ pr.println("*** Device light idling timer:");
+ mDeviceLightIdlingTimer.logState(pr, " ");
pr.println("*** Device idling timer:");
mDeviceIdlingTimer.logState(pr, " ");
pr.println("*** Phone timer:");
diff --git a/core/jni/android/graphics/MinikinSkia.cpp b/core/jni/android/graphics/MinikinSkia.cpp
index 4649b07..8ac5d46 100644
--- a/core/jni/android/graphics/MinikinSkia.cpp
+++ b/core/jni/android/graphics/MinikinSkia.cpp
@@ -32,16 +32,6 @@
SkSafeUnref(mTypeface);
}
-bool MinikinFontSkia::GetGlyph(uint32_t codepoint, uint32_t *glyph) const {
- SkPaint paint;
- paint.setTypeface(mTypeface);
- paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
- uint16_t glyph16;
- paint.textToGlyphs(&codepoint, sizeof(codepoint), &glyph16);
- *glyph = glyph16;
- return !!glyph16;
-}
-
static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) {
skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
skPaint->setTextSize(paint.size);
diff --git a/core/jni/android/graphics/MinikinSkia.h b/core/jni/android/graphics/MinikinSkia.h
index a06428d..8f469ba 100644
--- a/core/jni/android/graphics/MinikinSkia.h
+++ b/core/jni/android/graphics/MinikinSkia.h
@@ -28,8 +28,6 @@
~MinikinFontSkia();
- bool GetGlyph(uint32_t codepoint, uint32_t *glyph) const;
-
float GetHorizontalAdvance(uint32_t glyph_id,
const MinikinPaint &paint) const;
@@ -54,4 +52,4 @@
} // namespace android
-#endif // _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
\ No newline at end of file
+#endif // _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index e045f5f..d4735ec 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -643,12 +643,6 @@
// ---------------------------------------------------------------------------
-extern void setGLDebugLevel(int level);
-void setTracingLevel(JNIEnv *env, jclass clazz, jint level)
-{
- setGLDebugLevel(level);
-}
-
static int checkFormat(SkColorType colorType, int format, int type)
{
switch(colorType) {
@@ -1103,7 +1097,6 @@
{ "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType },
{ "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
{ "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D },
- { "setTracingLevel", "(I)V", (void*)setTracingLevel },
};
static const JNINativeMethod gEtc1Methods[] = {
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 738a62a..cb0abb6 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -1660,10 +1660,11 @@
uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
if (entry2.count > 0 && entry2.count == lsmWidth * lsmHeight * 4) {
+ // GainMap rectangle is relative to the active area origin.
err = builder.addGainMapsForMetadata(lsmWidth,
lsmHeight,
- ymin,
- xmin,
+ 0,
+ 0,
height,
width,
opcodeCfaLayout,
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 097bbac..1ee7ea8 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -294,7 +294,9 @@
// This is the regular Dalvik heap.
whichHeap = HEAP_DALVIK;
subHeap = HEAP_DALVIK_NORMAL;
- } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name) {
+ } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name ||
+ strstr(name, "/dev/ashmem/dalvik-free list large object space")
+ == name) {
whichHeap = HEAP_DALVIK;
subHeap = HEAP_DALVIK_LARGE;
} else if (strstr(name, "/dev/ashmem/dalvik-non moving space") == name) {
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 2f1627b..a58ec89 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 uur lank</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgende wekker)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Totdat jy dit afskakel"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Totdat jy Moenie steur nie afskakel"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5d94a69..80665a27 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">ለ%d ሰዓት</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"እስከ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ድረስ"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"እስከ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ቀጣይ ማንቂያ)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ይህን እስኪያጠፉት ድረስ"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"አትረብሽን እስኪያጠፉ ድረስ"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 209e1dc..22eaabe 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1538,6 +1538,7 @@
<item quantity="one">لمدة ساعة</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"حتى <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"حتى <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (التنبيه التالي)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"لحين تعطيل هذا الإعداد"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"حتى يتم تعطيل \"الرجاء عدم الإزعاج\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 16d123b..401e5b8 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 saat üçün</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Saat <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> qədər"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> radəsinə qədər (növbəti siqnal)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Bunu söndürənə kimi"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Narahat etməyin\" seçiminini deaktiv edənə kimi"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5427659..6c3fa54 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">За 1 ч</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"До следващия будилник (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Докато не изключите това"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Докато не изключите „Не безпокойте“"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 2d847ee..3f986a0 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">%d ঘন্টার জন্য</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত (পরবর্তী অ্যালার্ম)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"আপনার দ্বারা এটি বন্ধ করা পর্যন্ত"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"যতক্ষণ না পর্যন্ত আপনি বিরক্ত করবেন না বন্ধ করছেন"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e32c841..8d004df 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Durant 1 h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (propera alarma)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Fins que no ho desactivis"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Fins que desactivis el mode No molesteu"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7b05612..6ead72f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="one">1 h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (příští budík)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dokud tuto funkci nevypnete"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokud nevypnete režim Nerušit"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9c420c2..346cdb1 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">I %d t.</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Indtil <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Indtil <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (næste alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Indtil du slår denne indstilling fra"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Indtil du slår \"Forstyr ikke\" fra"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index fcbd762..4e8b455 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Für 1 h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nächste Weckzeit)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Bis zur Deaktivierung"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Bis zur Deaktivierung von \"Nicht stören\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index f2bb1d5..3f5e1af 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Για 1 ώρα</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Έως τις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Μέχρι τις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (επόμενο ξυπνητήρι)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Μέχρι να το απενεργοποιήσετε"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Μέχρι να απενεργοποιήσετε τη ρύθμιση \"Μην ενοχλείτε\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index ea33448..22179ed 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">For 1 hr</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do Not Disturb"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index ea33448..22179ed 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">For 1 hr</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do Not Disturb"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index ea33448..22179ed 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">For 1 hr</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do Not Disturb"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 5782eab..08f513b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Durante 1 hora</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hasta la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Hasta la hora <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hasta que lo desactives"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hasta que desactives No molestar"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index bb44ed3..4d1500d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Durante 1 hora</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hasta apagar el dispositivo"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hasta que desactives la opción No molestar"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 98818ad..09454d6 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kuni <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Kuni <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (järgmine äratus)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Kuni lülitate selle välja"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kuni lülitate välja valiku Mitte segada"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 8e7193a..0815aeb 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Ordubetez</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte (hurrengo alarma)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Zuk desaktibatu arte"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Ez molestatu\" desaktibatzen duzun arte"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 5032c25..683afb4 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -397,16 +397,16 @@
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"به برنامه اجازه میدهد تا بستههایی را دریافت کند که در شبکه Wi-Fi با استفاده از آدرسهای چندبخشی نه تنها به تلویزیون شما، بلکه به همه دستگاهها ارسال میشود. این حالت نسبت به حالت غیر چندبخشی از انرژی بیشتری استفاده میکند."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"به برنامه اجازه میدهد به دریافت بستههای ارسالی به همه دستگاههای موجود در شبکه Wi-Fi با استفاده از آدرسهای پخش چندگانه و نه فقط به تلفن شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده میکند."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"دسترسی به تنظیمات بلوتوث"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه میدهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاههای راه دور را شناسایی کرده و با آنها جفت شود."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"به برنامه اجازه میدهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاههای راه دور را شناسایی کرده و با آنها مرتبطسازی شود."</string>
<string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"به برنامه اجازه میدهد تا تلویزیون بلوتوث محلی را پیکربندی کند و دستگاههای از راه دور را شناسایی کند و با آنها مرتبط شود."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"به برنامه اجازه میدهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاههای راه دور را پیدا کند و با آنها جفت شود."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"به برنامه اجازه میدهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاههای راه دور را پیدا کند و با آنها مرتبطسازی شود."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"اتصال و قطع اتصال از WiMAX"</string>
<string name="permdesc_accessWimaxState" msgid="6360102877261978887">"به برنامه امکان میدهد فعال بودن وایمکس و اطلاعات مربوط به هر یک از شبکههای وایمکس متصل را مشخص کند."</string>
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"تغییر وضعیت WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان میدهد رایانهٔ لوحی را به شبکههای وایمکس متصل کرده یا اتصال آن را از این شبکهها قطع کند."</string>
<string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"به برنامه اجازه میدهد تا تلویزیون را به شبکههای WiMAX وصل یا ارتباط آن را با این شبکهها قطع کند."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"به برنامه امکان میدهد تا تلفن را به شبکههای وایمکس متصل کرده یا اتصال آنرا از این شبکهها قطع کند."</string>
- <string name="permlab_bluetooth" msgid="6127769336339276828">"جفت کردن با دستگاههای بلوتوث"</string>
+ <string name="permlab_bluetooth" msgid="6127769336339276828">"مرتبطسازی با دستگاههای بلوتوث"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاههای مرتبط را برقرار کرده و بپذیرد."</string>
<string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"به برنامه اجازه میدهد تا پیکربندی بلوتوث را در تلویزیون مشاهده کند و اتصالات را با دستگاههای مرتبطشده ایجاد کند و بپذیرد."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاههای مرتبط را برقرار کرده و بپذیرد."</string>
@@ -1143,7 +1143,7 @@
<string name="gpsNotifTitle" msgid="5446858717157416839">"درخواست موقعیت مکانی"</string>
<string name="gpsNotifMessage" msgid="1374718023224000702">"درخواست شده توسط <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"بله"</string>
- <string name="gpsVerifNo" msgid="1146564937346454865">"خیر"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"نه"</string>
<string name="sync_too_many_deletes" msgid="5296321850662746890">"از حد مجاز حذف فراتر رفت"</string>
<string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> مورد حذف شده برای <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>، حساب <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> وجود دارد. میخواهید چه کاری انجام دهید؟"</string>
<string name="sync_really_delete" msgid="2572600103122596243">"حذف موارد"</string>
@@ -1470,6 +1470,7 @@
<item quantity="other">برای %d ساعت</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"تا <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"تا <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (هشدار بعدی)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"تا وقتی آن را خاموش کنید"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"تا زمانی که «مزاحم نشوید» را خاموش کنید"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 7298cba..f8fb76f7 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 tunnin ajan</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kunnes kello on <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> asti (seuraava hälytys)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Kunnes poistat tämän käytöstä"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kunnes poistat Varattu-tilan käytöstä."</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index ba17051..286459a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">Pendant %d h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarme suivante)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Jusqu\'à ce que vous désactiviez le mode « Ne pas déranger »"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 15536cf..e4daeb1 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">Pendant %d h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarme suivante)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Jusqu\'à ce que vous désactiviez la fonctionnalité \"Ne pas déranger\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index c32add0..2abd2be 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Durante unha h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Ata as <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Ata as <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Ata que desactives isto"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Ata que desactives o modo Non molestar"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 6281abf..8f46194 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">%d કલાક માટે</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> સુધી"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (આગલા એલાર્મ) સુધી"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"તમે આ બંધ ન કરો ત્યાં સુધી"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"તમે ખલેલ પાડશો નહીં બંધ ન કરો ત્યાં સુધી"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 96eb95c..61b21bd 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">%d घंटे के लिए</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> तक"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (अगले अलार्म) तक"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"जब तक आप इसे बंद नहीं कर देते"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"जब तक कि आप परेशान ना करें को बंद नहीं कर देते"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 9b741bc..680dabd 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1487,6 +1487,7 @@
<item quantity="other">%d h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sljedeći alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dok ne isključite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dok ne isključite \"Ne uznemiravaj\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b063f0c..faed9b9 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 órán keresztül</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Eddig: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Eddig: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ez a következő riasztás)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Amíg ki nem kapcsolja ezt"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Amíg ki nem kapcsolja a „Ne zavarjanak” lehetőséget"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index a295306..9a0e603 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">%d ժամով</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Մինչև <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Մինչև ժ. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ը (հաջորդ զարթուցիչը)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Քանի դեռ չեք անջատել"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Մինչև չանջատեք «Չանհանգստացնել» գործառույթը"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 27f26a2..1bbd020 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Selama 1 jam</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Hingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarm berikutnya)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hingga Anda menonaktifkan ini"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hingga Anda menonaktifkan status Jangan Ganggu"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index c09914b..2a97573 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">Í %d klst.</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Þangað til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (næsta viðvörun)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Þar til þú slekkur á þessu"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Þar til þú slekkur á „Ónáðið ekki“"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index a034a25..c56b41b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Per 1 ora</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Fino alle ore <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Fino alle ore <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (prossima sveglia)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Fino alla disattivazione"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Fino alla disattivazione di Non disturbare"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a56332c..26fe698 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="one">למשך שעה אחת</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"עד <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"עד <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ההתראה הבאה)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"עד שתכבה"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"עד שתכבה את \'נא לא להפריע\'"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 135c7ea..6b1c833 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1時間</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>まで"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>(次のアラーム)まで"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ユーザーがOFFにするまで"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"[通知を非表示]をOFFにするまで"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index df302f5..e1221c4 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 სთ.</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-მდე"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-მდე (შემდეგი მაღვიძარა)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"სანამ ამას გამორთავდეთ"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"სანამ გამორთავთ „არ შემაწუხოთ“ ფუნქციას"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 7af4df0..b3172ff 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 сағат</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> дейін"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> дейін (келесі дабыл)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Сіз осыны өшіргенше"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Өшірмейінше мазаламау"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 3a02e76..822a303 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1472,6 +1472,7 @@
<item quantity="one">អស់រយៈពេល 1 ម៉ោង</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"រហូតដល់ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"រហូតដល់ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ម៉ោងរោទិ៍បន្ទាប់)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"រហូតដល់ពេលអ្នកបិទវា"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"រហូតទាល់តែអ្នកបិទ កុំរំខាន"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 0e98430..73d7ffc 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">%d ಗಂಟೆಗೆ</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ವರೆಗೆ"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ವರೆಗೆ (ಮುಂದಿನ ಅಲಾರಮ್)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ನೀವಿದನ್ನು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೂ ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f5a6fa4..0d76af2 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1시간 동안</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>까지"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>(다음 알람)까지"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"이 기능을 사용 중지할 때까지"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"알림 일시중지 기능을 사용 중지할 때까지"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index f20551d..22399b0 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 саатка</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> чейин"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> чейин (кийинки ойготкуч)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Бул өчүрүлгөнгө чейин"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Тынчымды алба\" режими өчүрүлгөнгө чейин"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 2e58b116..1d39230 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">ເປັນເວລາ 1 ຊມ</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"ຈົນຮອດ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"ຈົນກ່ວາ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ສັນຍານເຕືອນຕໍ່ໄປ)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າທ່ານຈະປິດ"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"ຈົນກ່ວາທ່ານປິດຫ້າມລົບກວນ"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index eb2903f..dbb8fbb 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="other">%d val.</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Iki <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Iki <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (kitas signalas)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Kol išjungsite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kol neišjungsite režimo „Netrukdyti“"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 7f10900..eaf7b46 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1487,6 +1487,7 @@
<item quantity="other">%d h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Līdz <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Līdz plkst. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nākamais signāls)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Līdz brīdim, kad izslēgsiet"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Līdz izslēgsiet statusu “Netraucēt”"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index a41be56..17e0d49 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1472,6 +1472,7 @@
<item quantity="other">За %d ч.</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (следниот аларм)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Додека не го исклучите"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Додека не го исклучите Не вознемирувај"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 2bdc9c8..3df3c86 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">ഒരു മണിക്കൂറത്തേക്ക്</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> വരെ"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> വരെ (അടുത്ത അലാറം)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"നിങ്ങൾ ഇത് ഓഫാക്കും വരെ"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\'ശല്ല്യപ്പെടുത്തരുത്\' ഓഫാക്കുന്നതുവരെ"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 3b5531d..ff8cc4d 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1468,6 +1468,7 @@
<item quantity="one">1 цагийн турш:</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> хүртэл"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> хүртэл (дараагийн сэрүүлэг)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Таныг унтраах хүртэл"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Бүү саад бол\"-ыг унтраах хүртэл"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 5956634..45bc3c5 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">%d तासासाठी</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर्यंत"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर्यंत (पुढील अलार्म)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"आपण हे बंद करेपर्यंत"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"आपण बंद करेपर्यंत व्यत्यय आणू नका"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index b69010e..1508d0e 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Selama 1 jam</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Sehingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Sehingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (penggera akan datang)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Sehingga anda matikan"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hingga anda mematikan Jangan Ganggu"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 41528d8..a09093f 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">၁ နာရီအတွက်</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>အထိ"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> အထိ (လာမည့် နှိုးစက်)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"သင်က ဒါကို ပိတ်မပစ်သည့် အထိ"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"မနှောင့်ယှက်ရန် ကိုသင်ပိတ်သည်အထိ"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b43314b..c2d2b80 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">I én time</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (neste alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Inntil du slår av funksjonen"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Inntil du slår av Ikke forstyrr"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index ac52911..e4b6c22 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1476,6 +1476,7 @@
<item quantity="one">१ घन्टाको लागि</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> सम्म"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (अर्को अलार्म) सम्म"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"तपाईँले यसलाई बन्द नगरेसम्म"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"तपाईँले बन्द नगरे सम्म बाधा नपुर्याउँनुहोस्"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index a850943..b208f48 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Gedurende 1 u</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgend alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Totdat u dit uitschakelt"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Totdat u \'Niet storen\' uitschakelt"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index e1276f1..8272d71 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">%d ਘੰਟਿਆਂ ਲਈ</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ਤੱਕ"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ਤੱਕ (ਅਗਲਾ ਅਲਾਰਮ)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸਨੂੰ ਬੰਦ ਨਹੀਂ ਕਰਦੇ ਹੋ"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕਰਦੇ ਹੋ"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 0ef89a6..34d26dc 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="one">1 godz.</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (następny alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dopóki nie wyłączysz"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Do wyłączenia Nie przeszkadzać"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 2f6c8bf..bd1b2f0 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">Por %d horas</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até que você desative \"Não perturbe\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e14303d..897dcd6 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Durante 1 h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Até que o utilizador desative"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até desativar Não incomodar"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 2f6c8bf..bd1b2f0 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">Por %d horas</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até que você desative \"Não perturbe\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 1faa14f..428e139 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1487,6 +1487,7 @@
<item quantity="one">Pentru 1 h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Până la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Până la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (următoarea alarmă)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Până la dezactivare"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Până când dezactivați „Nu deranja”"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 0621bbe..525e088 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="other">На %d часа</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Следующий сигнал в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Пока я не отключу"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Пока вы не отключите режим \"Не беспокоить\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 582f912..0135884 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1472,6 +1472,7 @@
<item quantity="other">පැය %d ක් සඳහා</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> තෙක්"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> තෙක් (ඊළඟ එලාමය)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"ඔබ මෙය අක්රිය කරන තුරු"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"බාධා නොකරන්න ඔබ අක්රිය කරන තුරු"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 8432348..5bd6867 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="one">Na 1 h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ďalší budík)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dokým túto funkciu nevypnete"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokým nevypnete stav Nerušiť"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c5ca3c2..02a748b3 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="other">%d h</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (naslednji alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Dokler tega ne izklopite"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokler ne izklopite načina »ne moti«"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 7df0f86..128dc23 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Për 1 orë</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarmi tjetër)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Deri sa ta çaktivizosh këtë"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Deri sa të çaktivizosh gjendjen \"Mos shqetëso\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 5bb2d78..aec317e 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1487,6 +1487,7 @@
<item quantity="other">За %d с</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (следећи аларм)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Док не искључите"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Док не искључите режим Не узнемиравај"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e803cbb..1032768 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1182,7 +1182,7 @@
<string name="shareactionprovider_share_with" msgid="806688056141131819">"Dela med"</string>
<string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dela med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="content_description_sliding_handle" msgid="415975056159262248">"Skärmlåsfunktion. Tryck och dra."</string>
- <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Lås upp genom att dra."</string>
+ <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Lås upp genom att svepa."</string>
<string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Anslut mikrofonlurar om du vill att lösenordet ska läsas upp."</string>
<string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
<string name="action_bar_home_description" msgid="5293600496601490216">"Visa startsidan"</string>
@@ -1470,6 +1470,7 @@
<item quantity="one">I en 1 tim</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Till kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Till <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nästa alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Tills du inaktiverar detta"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Tills du inaktiverar Stör ej"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index af04a46..6cc7b13 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1472,6 +1472,7 @@
<item quantity="one">Kwa saa 1 </item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hadi <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Mpaka <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (kengele inayofuata)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hadi utakapozima hili"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hadi utakapozima Usinisumbue"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 569fe82..1cdd590 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 மணிநேரத்திற்கு</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> வரை"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> மணி (அடுத்த அலாரம்) வரை"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"இதை முடக்கும்வரை"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"தொந்தரவு செய்ய வேண்டாம் என்பதை முடக்கும் வரை"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 77588b3..11c382e 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 గం పాటు</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> వరకు"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (తదుపరి అలారం) వరకు"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"మీరు దీన్ని ఆఫ్ చేసే వరకు"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"మీరు అంతరాయం కలిగించవద్దు ఎంపిక ఆఫ్ చేసే వరకు"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b2df636..d061873 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">เป็นเวลา 1 ชม.</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"จนถึงเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"จนถึงเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (การปลุกครั้งถัดไป)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"จนกว่าคุณจะปิดฟังก์ชันนี้"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"จนกว่าคุณจะปิดห้ามรบกวน"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 78c9358c..d87d7a9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">Sa loob ng %d na oras</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Hanggang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Hanggang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (susunod na alarm)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Hanggang sa i-off mo ito"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hanggang sa i-off mo ang Huwag Istorbohin"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index bf046e3..a5917e5 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 saat için</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Şu saate kadar: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sonraki alarma) saatine kadar"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Siz bunu kapatana kadar"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Rahatsız Etmeyin ayarını kapatana kadar"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 1aa1a51..6f77952 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1504,6 +1504,7 @@
<item quantity="other">Протягом %d год</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (наступний будильник)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Доки ви не вимкнете"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Доки ввімкнено режим \"Не турбувати\""</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index e6e20f1..55e6efd 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 گھنٹہ کیلئے</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> تک"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> تک (اگلا الارم)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"جب تک آپ اسے آف نہ کر دیں"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"جب تک آپ ڈسڑب نہ کریں کو آف نہیں کر دیتے"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index b7ae992..c76df70 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 soat</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> gacha (keyingi signal)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Men o‘chirmaguncha"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"“Bezovta qilinmasin” rejimi o‘chirilmaguncha"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 83b0d18..a74e10e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">Trong 1 giờ</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Cho đến <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Cho tới <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (cảnh báo tiếp theo)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Cho đến khi bạn tắt tính năng này"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Cho đến khi bạn tắt Đừng làm phiền"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 54100d5..57c91a8 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 小时</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"到<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"直到<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>(闹钟下次响铃时)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"直到您将其关闭"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"直到您关闭“勿扰”模式"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 4c713c9..5b6b456 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">需時 1 小時</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"完成時間:<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"直至<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (下一次響鬧)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"直至您關閉這項設定"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"直至您關閉「請勿騷擾」功能"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 46f0d2c..387f8bb 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="one">1 小時</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"結束時間:<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"到<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 為止 (下一個鬧鐘)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"手動關閉這項設定前一律啟用"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"直到您關閉「零打擾」模式"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 0ecd571..a9b6d14 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1470,6 +1470,7 @@
<item quantity="other">Ngamahora angu-%d</item>
</plurals>
<string name="zen_mode_until" msgid="7336308492289875088">"Kuze kube ngu-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_alarm" msgid="9128205721301330797">"Kuze kube ngu-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (i-alamu elandelayo)"</string>
<string name="zen_mode_forever" msgid="7420011936770086993">"Uze uvale lokhu"</string>
<string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Uze uvale ungaphazamisi"</string>
<string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 40cd097..c8d53d7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1697,7 +1697,7 @@
--> <skip />
<!-- On the keyguard screen, it shows the carrier the phone is connected to. This is displayed if the phone is not connected to a carrier.-->
- <string name="lockscreen_carrier_default">No service.</string>
+ <string name="lockscreen_carrier_default">No service</string>
<!-- Shown in the lock screen to tell the user that the screen is locked. -->
<string name="lockscreen_screen_locked">Screen locked.</string>
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 1105ca4..5988781 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -1569,16 +1569,16 @@
public boolean onStateChange(int[] stateSet) {
boolean changed = false;
- if (mStrokeColors != null && mStrokeColors.isStateful()) {
- final int strokeColor = mStrokeColor;
- mStrokeColor = mStrokeColors.getColorForState(stateSet, strokeColor);
- changed |= strokeColor != mStrokeColor;
+ if (mStrokeColors != null) {
+ final int oldStrokeColor = mStrokeColor;
+ mStrokeColor = mStrokeColors.getColorForState(stateSet, oldStrokeColor);
+ changed |= oldStrokeColor != mStrokeColor;
}
- if (mFillColors != null && mFillColors.isStateful()) {
- final int fillColor = mFillColor;
- mFillColor = mFillColors.getColorForState(stateSet, fillColor);
- changed |= fillColor != mFillColor;
+ if (mFillColors != null) {
+ final int oldFillColor = mFillColor;
+ mFillColor = mFillColors.getColorForState(stateSet, oldFillColor);
+ changed |= oldFillColor != mFillColor;
}
return changed;
@@ -1586,8 +1586,7 @@
@Override
public boolean isStateful() {
- return mStrokeColors != null && mStrokeColors.isStateful()
- || mFillColors != null && mFillColors.isStateful();
+ return mStrokeColors != null || mFillColors != null;
}
@Override
@@ -1716,31 +1715,31 @@
final ColorStateList fillColors = a.getColorStateList(
R.styleable.VectorDrawablePath_fillColor);
if (fillColors != null) {
- mFillColors = fillColors;
+ // If the color state list isn't stateful, discard the state
+ // list and keep the default (e.g. the only) color.
+ mFillColors = fillColors.isStateful() ? fillColors : null;
mFillColor = fillColors.getDefaultColor();
}
final ColorStateList strokeColors = a.getColorStateList(
R.styleable.VectorDrawablePath_strokeColor);
if (strokeColors != null) {
- mStrokeColors = strokeColors;
+ // If the color state list isn't stateful, discard the state
+ // list and keep the default (e.g. the only) color.
+ mStrokeColors = strokeColors.isStateful() ? strokeColors : null;
mStrokeColor = strokeColors.getDefaultColor();
}
- mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
- mFillAlpha);
+ mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha, mFillAlpha);
mStrokeLineCap = getStrokeLineCap(a.getInt(
R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
mStrokeLineJoin = getStrokeLineJoin(a.getInt(
R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
mStrokeMiterlimit = a.getFloat(
R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
- mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
- mStrokeAlpha);
- mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
- mStrokeWidth);
- mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
- mTrimPathEnd);
+ mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha, mStrokeAlpha);
+ mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
+ mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
mTrimPathOffset = a.getFloat(
R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
mTrimPathStart = a.getFloat(
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 9fc3924..1a43658 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -87,7 +87,6 @@
-Wall -Wno-unused-parameter -Wunreachable-code \
-ffast-math -O3 -Werror
-
ifeq (true, $(HWUI_NEW_OPS))
hwui_src_files += \
BakedOpRenderer.cpp \
@@ -154,6 +153,27 @@
include $(BUILD_STATIC_LIBRARY)
# ------------------------
+# static library null gpu
+# ------------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libhwui_static_null_gpu
+LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
+LOCAL_CFLAGS := \
+ $(hwui_cflags) \
+ -DHWUI_NULL_GPU
+LOCAL_SRC_FILES := \
+ $(hwui_src_files) \
+ tests/nullegl.cpp \
+ tests/nullgles.cpp
+LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(hwui_c_includes) $(call hwui_proto_include)
+
+include $(BUILD_STATIC_LIBRARY)
+
+# ------------------------
# shared library
# ------------------------
@@ -175,7 +195,7 @@
LOCAL_MODULE := hwui_unit_tests
LOCAL_MODULE_TAGS := tests
LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
-LOCAL_STATIC_LIBRARIES := libhwui_static
+LOCAL_STATIC_LIBRARIES := libhwui_static_null_gpu
LOCAL_CFLAGS := $(hwui_cflags)
LOCAL_SRC_FILES += \
@@ -210,22 +230,8 @@
LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
LOCAL_CFLAGS := $(hwui_cflags)
-HWUI_NULL_GPU := false
-
-ifeq (true, $(HWUI_NULL_GPU))
- # Only need to specify the includes if we are not linking against
- # libhwui_static as libhwui_static exports the appropriate includes
- LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
-
- LOCAL_SRC_FILES := \
- $(hwui_src_files) \
- tests/nullegl.cpp \
- tests/nullgles.cpp
-
- LOCAL_CFLAGS += -DHWUI_NULL_GPU
-else
- LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
-endif
+# set to libhwui_static_null_gpu to skip actual GL commands
+LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
LOCAL_SRC_FILES += \
tests/TestContext.cpp \
@@ -250,7 +256,7 @@
LOCAL_CFLAGS := $(hwui_cflags)
LOCAL_C_INCLUDES += bionic/benchmarks/
-LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
+LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static_null_gpu
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
LOCAL_SRC_FILES += \
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 4eb7066..59f0d7c 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -34,6 +34,17 @@
DisplayList::DisplayList()
: projectionReceiveIndex(-1)
+ , stdAllocator(allocator)
+ , chunks(stdAllocator)
+ , ops(stdAllocator)
+ , children(stdAllocator)
+ , bitmapResources(stdAllocator)
+ , pathResources(stdAllocator)
+ , patchResources(stdAllocator)
+ , paints(stdAllocator)
+ , regions(stdAllocator)
+ , referenceHolders(stdAllocator)
+ , functors(stdAllocator)
, hasDrawOps(false) {
}
@@ -68,9 +79,9 @@
}
size_t DisplayList::addChild(NodeOpType* op) {
- mReferenceHolders.push_back(op->renderNode);
- size_t index = mChildren.size();
- mChildren.push_back(op);
+ referenceHolders.push_back(op->renderNode);
+ size_t index = children.size();
+ children.push_back(op);
return index;
}
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index d32406f..86796c5 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -132,32 +132,22 @@
DisplayList();
~DisplayList();
- // pointers to all ops within display list, pointing into allocator data
- std::vector<DisplayListOp*> displayListOps;
-
// index of DisplayListOp restore, after which projected descendents should be drawn
int projectionReceiveIndex;
- std::vector<const SkBitmap*> bitmapResources;
- std::vector<const SkPath*> pathResources;
- std::vector<const Res_png_9patch*> patchResources;
+ const LsaVector<Chunk>& getChunks() const { return chunks; }
+ const LsaVector<BaseOpType*>& getOps() const { return ops; }
- std::vector<std::unique_ptr<const SkPaint>> paints;
- std::vector<std::unique_ptr<const SkRegion>> regions;
- Vector<Functor*> functors;
+ const LsaVector<NodeOpType*>& getChildren() const { return children; }
- const std::vector<Chunk>& getChunks() const {
- return chunks;
- }
- const std::vector<BaseOpType*>& getOps() const {
- return ops;
- }
+ const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
+ const LsaVector<Functor*>& getFunctors() const { return functors; }
size_t addChild(NodeOpType* childOp);
- const std::vector<NodeOpType*>& children() { return mChildren; }
+
void ref(VirtualLightRefBase* prop) {
- mReferenceHolders.push_back(prop);
+ referenceHolders.push_back(prop);
}
size_t getUsedSize() {
@@ -168,17 +158,27 @@
}
private:
- std::vector<BaseOpType*> ops;
-
- std::vector< sp<VirtualLightRefBase> > mReferenceHolders;
-
- // list of children display lists for quick, non-drawing traversal
- std::vector<NodeOpType*> mChildren;
-
- std::vector<Chunk> chunks;
-
- // allocator into which all ops were allocated
+ // allocator into which all ops and LsaVector arrays allocated
LinearAllocator allocator;
+ LinearStdAllocator<void*> stdAllocator;
+
+ LsaVector<Chunk> chunks;
+ LsaVector<BaseOpType*> ops;
+
+ // list of Ops referring to RenderNode children for quick, non-drawing traversal
+ LsaVector<NodeOpType*> children;
+
+ // Resources - Skia objects + 9 patches referred to by this DisplayList
+ LsaVector<const SkBitmap*> bitmapResources;
+ LsaVector<const SkPath*> pathResources;
+ LsaVector<const Res_png_9patch*> patchResources;
+ LsaVector<std::unique_ptr<const SkPaint>> paints;
+ LsaVector<std::unique_ptr<const SkRegion>> regions;
+ LsaVector< sp<VirtualLightRefBase> > referenceHolders;
+
+ // List of functors
+ LsaVector<Functor*> functors;
+
bool hasDrawOps;
void cleanupResources();
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index f49482b..bad3972 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -82,7 +82,7 @@
void DisplayListCanvas::callDrawGLFunction(Functor *functor) {
addDrawOp(new (alloc()) DrawFunctorOp(functor));
- mDisplayList->functors.add(functor);
+ mDisplayList->functors.push_back(functor);
}
SkCanvas* DisplayListCanvas::asSkCanvas() {
@@ -528,7 +528,7 @@
newChunk.endOpIndex = insertIndex + 1;
newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
- int nextChildIndex = mDisplayList->children().size();
+ int nextChildIndex = mDisplayList->children.size();
newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
mDeferredBarrierType = kBarrier_None;
} else {
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index 7c34992..7c0e257 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -225,18 +225,17 @@
if (node->applyViewProperties(mCanvasState)) {
// not rejected do ops...
const DisplayList& displayList = node->getDisplayList();
- deferImpl(displayList.getChunks(), displayList.getOps());
+ deferImpl(displayList);
}
mCanvasState.restore();
}
}
-void OpReorderer::defer(int viewportWidth, int viewportHeight,
- const std::vector<DisplayList::Chunk>& chunks, const std::vector<RecordedOp*>& ops) {
+void OpReorderer::defer(int viewportWidth, int viewportHeight, const DisplayList& displayList) {
ATRACE_NAME("prepare drawing commands");
mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
0, 0, viewportWidth, viewportHeight, Vector3());
- deferImpl(chunks, ops);
+ deferImpl(displayList);
}
/**
@@ -247,14 +246,13 @@
*/
#define OP_RECIEVER(Type) \
[](OpReorderer& reorderer, const RecordedOp& op) { reorderer.on##Type(static_cast<const Type&>(op)); },
-void OpReorderer::deferImpl(const std::vector<DisplayList::Chunk>& chunks,
- const std::vector<RecordedOp*>& ops) {
+void OpReorderer::deferImpl(const DisplayList& displayList) {
static std::function<void(OpReorderer& reorderer, const RecordedOp&)> receivers[] = {
MAP_OPS(OP_RECIEVER)
};
- for (const DisplayList::Chunk& chunk : chunks) {
+ for (const DisplayList::Chunk& chunk : displayList.getChunks()) {
for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
- const RecordedOp* op = ops[opIndex];
+ const RecordedOp* op = displayList.getOps()[opIndex];
receivers[op->opId](*this, *op);
}
}
@@ -288,8 +286,7 @@
// apply RenderProperties state
if (op.renderNode->applyViewProperties(mCanvasState)) {
// not rejected do ops...
- const DisplayList& displayList = op.renderNode->getDisplayList();
- deferImpl(displayList.getChunks(), displayList.getOps());
+ deferImpl(op.renderNode->getDisplayList());
}
mCanvasState.restore();
}
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
index 9c77248..6776a3c 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/OpReorderer.h
@@ -62,8 +62,7 @@
void defer(const SkRect& clip, int viewportWidth, int viewportHeight,
const std::vector< sp<RenderNode> >& nodes);
- void defer(int viewportWidth, int viewportHeight,
- const std::vector<DisplayList::Chunk>& chunks, const std::vector<RecordedOp*>& ops);
+ void defer(int viewportWidth, int viewportHeight, const DisplayList& displayList);
typedef std::function<void(void*, const RecordedOp&, const BakedOpState&)> BakedOpReceiver;
/**
@@ -92,8 +91,7 @@
private:
BakedOpState* bakeOpState(const RecordedOp& recordedOp);
- void deferImpl(const std::vector<DisplayList::Chunk>& chunks,
- const std::vector<RecordedOp*>& ops);
+ void deferImpl(const DisplayList& displayList);
void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers);
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 248a46e..3b413aa 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -369,7 +369,7 @@
newChunk.endOpIndex = insertIndex + 1;
newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
- int nextChildIndex = mDisplayList->children().size();
+ int nextChildIndex = mDisplayList->children.size();
newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
mDeferredBarrierType = kBarrier_None;
} else {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 3d32f02..894a2bd 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -49,7 +49,7 @@
mLayer->wasBuildLayered ? "true" : "false");
}
if (mDisplayList) {
- for (auto&& child : mDisplayList->children()) {
+ for (auto&& child : mDisplayList->getChildren()) {
child->renderNode->debugDumpLayers(prefix);
}
}
@@ -178,7 +178,7 @@
pnode->clear_children();
if (mDisplayList) {
- for (auto&& child : mDisplayList->children()) {
+ for (auto&& child : mDisplayList->getChildren()) {
child->renderNode->copyTo(pnode->add_children());
}
}
@@ -322,9 +322,9 @@
bool willHaveFunctor = false;
if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayList) {
- willHaveFunctor = !mStagingDisplayList->functors.isEmpty();
+ willHaveFunctor = !mStagingDisplayList->getFunctors().empty();
} else if (mDisplayList) {
- willHaveFunctor = !mDisplayList->functors.isEmpty();
+ willHaveFunctor = !mDisplayList->getFunctors().empty();
}
bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
willHaveFunctor, functorsNeedLayer);
@@ -379,7 +379,7 @@
// Make sure we inc first so that we don't fluctuate between 0 and 1,
// which would thrash the layer cache
if (mStagingDisplayList) {
- for (auto&& child : mStagingDisplayList->children()) {
+ for (auto&& child : mStagingDisplayList->getChildren()) {
child->renderNode->incParentRefCount();
}
}
@@ -387,8 +387,8 @@
mDisplayList = mStagingDisplayList;
mStagingDisplayList = nullptr;
if (mDisplayList) {
- for (size_t i = 0; i < mDisplayList->functors.size(); i++) {
- (*mDisplayList->functors[i])(DrawGlInfo::kModeSync, nullptr);
+ for (size_t i = 0; i < mDisplayList->getFunctors().size(); i++) {
+ (*mDisplayList->getFunctors()[i])(DrawGlInfo::kModeSync, nullptr);
}
}
}
@@ -406,7 +406,7 @@
void RenderNode::deleteDisplayList() {
if (mDisplayList) {
- for (auto&& child : mDisplayList->children()) {
+ for (auto&& child : mDisplayList->getChildren()) {
child->renderNode->decParentRefCount();
}
}
@@ -417,12 +417,11 @@
void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree) {
if (subtree) {
TextureCache& cache = Caches::getInstance().textureCache;
- info.out.hasFunctors |= subtree->functors.size();
- for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) {
- info.prepareTextures = cache.prefetchAndMarkInUse(
- info.canvasContext, subtree->bitmapResources[i]);
+ info.out.hasFunctors |= subtree->getFunctors().size();
+ for (auto&& bitmapResource : subtree->getBitmapResources()) {
+ info.prepareTextures = cache.prefetchAndMarkInUse(info.canvasContext, bitmapResource);
}
- for (auto&& op : subtree->children()) {
+ for (auto&& op : subtree->getChildren()) {
RenderNode* childNode = op->renderNode;
#if HWUI_NEW_OPS
info.damageAccumulator->pushTransform(&op->localMatrix);
@@ -445,7 +444,7 @@
mLayer = nullptr;
}
if (mDisplayList) {
- for (auto&& child : mDisplayList->children()) {
+ for (auto&& child : mDisplayList->getChildren()) {
child->renderNode->destroyHardwareResources();
}
if (mNeedsDisplayListSync) {
@@ -634,8 +633,8 @@
// TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that
// transform properties are applied correctly to top level children
if (mDisplayList == nullptr) return;
- for (unsigned int i = 0; i < mDisplayList->children().size(); i++) {
- DrawRenderNodeOp* childOp = mDisplayList->children()[i];
+ for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) {
+ DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i];
childOp->renderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity());
}
#endif
@@ -664,11 +663,11 @@
opState->mSkipInOrderDraw = false;
}
- if (mDisplayList->children().size() > 0) {
+ if (mDisplayList->getChildren().size() > 0) {
const bool isProjectionReceiver = mDisplayList->projectionReceiveIndex >= 0;
bool haveAppliedPropertiesToProjection = false;
- for (unsigned int i = 0; i < mDisplayList->children().size(); i++) {
- DrawRenderNodeOp* childOp = mDisplayList->children()[i];
+ for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) {
+ DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i];
RenderNode* child = childOp->renderNode;
std::vector<DrawRenderNodeOp*>* projectionChildren = nullptr;
@@ -756,7 +755,7 @@
if (chunk.beginChildIndex == chunk.endChildIndex) return;
for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
- DrawRenderNodeOp* childOp = mDisplayList->children()[i];
+ DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i];
RenderNode* child = childOp->renderNode;
float childZ = child->properties().getZ();
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/microbench/DisplayListCanvasBench.cpp
index 0be7634..7a62037 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/microbench/DisplayListCanvasBench.cpp
@@ -23,6 +23,7 @@
#include "DisplayListCanvas.h"
#endif
#include "microbench/MicroBench.h"
+#include "unit_tests/TestUtils.h"
using namespace android;
using namespace android::uirenderer;
@@ -102,6 +103,40 @@
StopBenchmarkTiming();
}
+/**
+ * Simulate a simple view drawing a background, overlapped by an image.
+ *
+ * Note that the recording commands are intentionally not perfectly efficient, as the
+ * View system frequently produces unneeded save/restores.
+ */
+BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_simpleBitmapView);
+void BM_DisplayListCanvas_record_simpleBitmapView::Run(int iters) {
+ TestCanvas canvas(100, 100);
+ delete canvas.finishRecording();
+
+ SkPaint rectPaint;
+ SkBitmap iconBitmap = TestUtils::createSkBitmap(80, 80);
+
+ StartBenchmarkTiming();
+ for (int i = 0; i < iters; ++i) {
+ canvas.reset(100, 100);
+ {
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ canvas.drawRect(0, 0, 100, 100, rectPaint);
+ canvas.restore();
+ }
+ {
+ canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ canvas.translate(10, 10);
+ canvas.drawBitmap(iconBitmap, 0, 0, nullptr);
+ canvas.restore();
+ }
+ MicroBench::DoNotOptimize(&canvas);
+ delete canvas.finishRecording();
+ }
+ StopBenchmarkTiming();
+}
+
class NullClient: public CanvasStateClient {
void onViewportInitialized() override {}
void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/unit_tests/OpReordererTests.cpp
index 24cff72..e1249fb 100644
--- a/libs/hwui/unit_tests/OpReordererTests.cpp
+++ b/libs/hwui/unit_tests/OpReordererTests.cpp
@@ -49,14 +49,14 @@
static void endFrame(Info& info) {}
};
TEST(OpReorderer, simple) {
- auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ auto dl = TestUtils::createDisplayList<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());
+ reorderer.defer(200, 200, *dl);
Info info;
reorderer.replayBakedOps<SimpleReceiver>(&info);
@@ -78,7 +78,7 @@
static void endFrame(Info& info) {}
};
TEST(OpReorderer, simpleBatching) {
- auto dld = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
SkBitmap bitmap = TestUtils::createSkBitmap(10, 10);
// Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
@@ -93,7 +93,7 @@
});
OpReorderer reorderer;
- reorderer.defer(200, 200, dld->getChunks(), dld->getOps());
+ reorderer.defer(200, 200, *dl);
Info info;
reorderer.replayBakedOps<SimpleBatchingReceiver>(&info);
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
index 7c19df5..ce25fc6 100644
--- a/libs/hwui/unit_tests/RecordingCanvasTests.cpp
+++ b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
@@ -23,30 +23,31 @@
namespace android {
namespace uirenderer {
-static void playbackOps(const std::vector<DisplayList::Chunk>& chunks,
- const std::vector<RecordedOp*>& ops, std::function<void(const RecordedOp&)> opReciever) {
- for (const DisplayList::Chunk& chunk : chunks) {
+static void playbackOps(const DisplayList& displayList,
+ std::function<void(const RecordedOp&)> opReciever) {
+ for (const DisplayList::Chunk& chunk : displayList.getChunks()) {
for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
- opReciever(*ops[opIndex]);
+ RecordedOp* op = displayList.getOps()[opIndex];
+ opReciever(*op);
}
}
}
TEST(RecordingCanvas, emptyPlayback) {
- auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
canvas.restore();
});
- playbackOps(dld->getChunks(), dld->getOps(), [](const RecordedOp& op) { FAIL(); });
+ playbackOps(*dl, [](const RecordedOp& op) { FAIL(); });
}
TEST(RecordingCanvas, testSimpleRectRecord) {
- auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
canvas.drawRect(10, 20, 90, 180, SkPaint());
});
int count = 0;
- playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+ playbackOps(*dl, [&count](const RecordedOp& op) {
count++;
ASSERT_EQ(RecordedOpId::RectOp, op.opId);
ASSERT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
@@ -56,7 +57,7 @@
}
TEST(RecordingCanvas, backgroundAndImage) {
- auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
SkBitmap bitmap;
bitmap.setInfo(SkImageInfo::MakeUnknown(25, 25));
SkPaint paint;
@@ -81,7 +82,7 @@
});
int count = 0;
- playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+ playbackOps(*dl, [&count](const RecordedOp& op) {
if (count == 0) {
ASSERT_EQ(RecordedOpId::RectOp, op.opId);
ASSERT_NE(nullptr, op.paint);
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index ade4ab3..e1c6f6c 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -29,6 +29,8 @@
#include <stddef.h>
#include <type_traits>
+#include <vector>
+
namespace android {
namespace uirenderer {
@@ -175,6 +177,13 @@
template <class T1, class T2>
bool operator!= (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return false; }
+template <class T>
+class LsaVector : public std::vector<T, LinearStdAllocator<T>> {
+public:
+ LsaVector(const LinearStdAllocator<T>& allocator)
+ : std::vector<T, LinearStdAllocator<T>>(allocator) {}
+};
+
}; // namespace uirenderer
}; // namespace android
diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java
index 4d890c9..d097335 100644
--- a/opengl/java/android/opengl/GLUtils.java
+++ b/opengl/java/android/opengl/GLUtils.java
@@ -261,12 +261,6 @@
}
}
- /**
- * Set OpenGL Tracing level for this application.
- * @hide
- */
- native public static void setTracingLevel(int level);
-
native private static int native_getInternalFormat(Bitmap bitmap);
native private static int native_getType(Bitmap bitmap);
native private static int native_texImage2D(int target, int level, int internalformat,
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ed7820b..73538278 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -16,4 +16,6 @@
<resources>
<bool name="productivity_device">true</bool>
+ <!-- intentionally unset. Vendors should set this in an overlay. -->
+ <string name="trusted_quick_viewer_package"></string>
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 83e3440..e3b1324 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -466,25 +466,6 @@
}
}
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (DEBUG) Log.d(mTag, "onKeyUp: keycode = " + keyCode);
-
- // TODO: Support for RecentsCreateFragment.
- DirectoryFragment fragment = DirectoryFragment.get(getFragmentManager());
- if (fragment != null) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_MOVE_HOME:
- fragment.focusFirstFile();
- return true;
- case KeyEvent.KEYCODE_MOVE_END:
- fragment.focusLastFile();
- return true;
- }
- }
- return super.onKeyUp(keyCode, event);
- }
-
public void onStackPicked(DocumentStack stack) {
try {
// Update the restored stack to ensure we have freshest data
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index a3a431f..7662689 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.State.ACTION_BROWSE;
import static com.android.documentsui.State.ACTION_CREATE;
import static com.android.documentsui.State.ACTION_MANAGE;
@@ -66,6 +65,7 @@
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
import android.support.v7.widget.RecyclerView.RecyclerListener;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.TextUtils;
@@ -109,6 +109,8 @@
*/
public class DirectoryFragment extends Fragment {
+ public static final String TAG = "DirectoryFragment";
+
public static final int TYPE_NORMAL = 1;
public static final int TYPE_SEARCH = 2;
public static final int TYPE_RECENT_OPEN = 3;
@@ -130,6 +132,7 @@
private static final String EXTRA_IGNORE_STATE = "ignoreState";
private Model mModel;
+ private MultiSelectManager mSelectionManager;
private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
private View mEmptyView;
@@ -268,7 +271,7 @@
}
// Clear any outstanding selection
- mModel.clearSelection();
+ mSelectionManager.clearSelection();
}
@Override
@@ -297,18 +300,35 @@
}
};
+ final GestureDetector detector = new GestureDetector(this.getContext(), listener);
+ detector.setOnDoubleTapListener(listener);
+
+ mRecView.addOnItemTouchListener(
+ new OnItemTouchListener() {
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ detector.onTouchEvent(e);
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+ });
+
// TODO: instead of inserting the view into the constructor, extract listener-creation code
// and set the listener on the view after the fact. Then the view doesn't need to be passed
- // into the selection manager which is passed into the model.
- MultiSelectManager selMgr= new MultiSelectManager(
+ // into the selection manager.
+ mSelectionManager = new MultiSelectManager(
mRecView,
- listener,
state.allowMultiple
? MultiSelectManager.MODE_MULTIPLE
: MultiSelectManager.MODE_SINGLE);
- selMgr.addCallback(new SelectionModeListener());
+ mSelectionManager.addCallback(new SelectionModeListener());
- mModel = new Model(context, selMgr, mAdapter);
+ mModel = new Model(context, mAdapter);
mModel.addUpdateListener(mModelUpdateListener);
mType = getArguments().getInt(EXTRA_TYPE);
@@ -430,7 +450,7 @@
}
private boolean onSingleTapUp(MotionEvent e) {
- if (Events.isTouchEvent(e) && mModel.getSelection().isEmpty()) {
+ if (Events.isTouchEvent(e) && mSelectionManager.getSelection().isEmpty()) {
int position = getEventAdapterPosition(e);
if (position != RecyclerView.NO_POSITION) {
return handleViewItem(position);
@@ -458,7 +478,7 @@
if (isDocumentEnabled(docMimeType, docFlags)) {
final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
((BaseActivity) getActivity()).onDocumentPicked(doc, mModel);
- mModel.clearSelection();
+ mSelectionManager.clearSelection();
return true;
}
return false;
@@ -564,7 +584,7 @@
mRecView.setLayoutManager(layout);
// TODO: Once b/23691541 is resolved, use a listener within MultiSelectManager instead of
// imperatively calling this function.
- mModel.mSelectionManager.handleLayoutChanged();
+ mSelectionManager.handleLayoutChanged();
// setting layout manager automatically invalidates existing ViewHolders.
mThumbSize = new Point(thumbSize, thumbSize);
}
@@ -620,7 +640,7 @@
@Override
public void onSelectionChanged() {
- mModel.getSelection(mSelected);
+ mSelectionManager.getSelection(mSelected);
TypedValue color = new TypedValue();
if (mSelected.size() > 0) {
if (DEBUG) Log.d(TAG, "Maybe starting action mode.");
@@ -628,8 +648,7 @@
if (DEBUG) Log.d(TAG, "Yeah. Starting action mode.");
mActionMode = getActivity().startActionMode(this);
}
- getActivity().getTheme().resolveAttribute(
- R.attr.colorActionMode, color, true);
+ getActivity().getTheme().resolveAttribute(R.attr.colorActionMode, color, true);
updateActionMenu();
} else {
if (DEBUG) Log.d(TAG, "Finishing action mode.");
@@ -652,16 +671,17 @@
if (DEBUG) Log.d(TAG, "Handling action mode destroyed.");
mActionMode = null;
// clear selection
- mModel.clearSelection();
+ mSelectionManager.clearSelection();
mSelected.clear();
mNoDeleteCount = 0;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ int size = mSelectionManager.getSelection().size();
mode.getMenuInflater().inflate(R.menu.mode_directory, menu);
- mode.setTitle(TextUtils.formatSelectedCount(mModel.getSelection().size()));
- return mModel.getSelection().size() > 0;
+ mode.setTitle(TextUtils.formatSelectedCount(size));
+ return (size > 0);
}
@Override
@@ -681,7 +701,7 @@
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- Selection selection = mModel.getSelection(new Selection());
+ Selection selection = mSelectionManager.getSelection(new Selection());
final int id = item.getItemId();
if (id == R.id.menu_open) {
@@ -920,15 +940,22 @@
public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final State state = getDisplayState(DirectoryFragment.this);
final LayoutInflater inflater = LayoutInflater.from(getContext());
+ View item = null;
switch (state.derivedMode) {
case MODE_GRID:
- return new DocumentHolder(inflater.inflate(R.layout.item_doc_grid, parent, false));
+ item = inflater.inflate(R.layout.item_doc_grid, parent, false);
+ break;
case MODE_LIST:
- return new DocumentHolder(inflater.inflate(R.layout.item_doc_list, parent, false));
+ item = inflater.inflate(R.layout.item_doc_list, parent, false);
+ break;
case MODE_UNKNOWN:
default:
throw new IllegalStateException("Unsupported layout mode.");
}
+ // Key event bubbling doesn't work properly, so instead of setting one key listener on
+ // the RecyclerView, we have to set it on each Item. See b/24865023.
+ item.setOnKeyListener(mSelectionManager);
+ return new DocumentHolder(item);
}
@Override
@@ -957,7 +984,7 @@
holder.docId = docId;
final View itemView = holder.view;
- itemView.setActivated(mModel.isSelected(position));
+ itemView.setActivated(isSelected(position));
final View line1 = itemView.findViewById(R.id.line1);
final View line2 = itemView.findViewById(R.id.line2);
@@ -1289,7 +1316,7 @@
}
void copySelectedToClipboard() {
- Selection sel = mModel.getSelection(new Selection());
+ Selection sel = mSelectionManager.getSelection(new Selection());
copySelectionToClipboard(sel);
}
@@ -1338,51 +1365,12 @@
}
void selectAllFiles() {
- boolean changed = mModel.selectAll();
+ boolean changed = mSelectionManager.setItemsSelected(0, mModel.getItemCount(), true);
if (changed) {
updateDisplayState();
}
}
- /**
- * Scrolls to the top of the file list and focuses the first file.
- */
- void focusFirstFile() {
- focusFile(0);
- }
-
- /**
- * Scrolls to the bottom of the file list and focuses the last file.
- */
- void focusLastFile() {
- focusFile(mAdapter.getItemCount() - 1);
- }
-
- /**
- * Scrolls to and then focuses on the file at the given position.
- */
- private void focusFile(final int pos) {
- // Don't smooth scroll; that taxes the system unnecessarily and makes the scroll handling
- // logic below more complicated.
- mRecView.scrollToPosition(pos);
-
- // If the item is already in view, focus it; otherwise, set a one-time listener to focus it
- // when the scroll is completed.
- RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(pos);
- if (vh != null) {
- vh.itemView.requestFocus();
- } else {
- mRecView.addOnScrollListener(
- new RecyclerView.OnScrollListener() {
- @Override
- public void onScrolled(RecyclerView view, int dx, int dy) {
- view.findViewHolderForAdapterPosition(pos).itemView.requestFocus();
- view.removeOnScrollListener(this);
- }
- });
- }
- }
-
private void setupDragAndDropOnDirectoryView(View view) {
// Listen for drops on non-directory items and empty space.
view.setOnDragListener(mOnDragListener);
@@ -1472,9 +1460,10 @@
return Collections.EMPTY_LIST;
}
- final List<DocumentInfo> selectedDocs = mModel.getSelectedDocuments();
+ final List<DocumentInfo> selectedDocs =
+ mModel.getDocuments(mSelectionManager.getSelection());
if (!selectedDocs.isEmpty()) {
- if (!mModel.isSelected(position)) {
+ if (!isSelected(position)) {
// There is a selection that does not include the current item, drag nothing.
return Collections.EMPTY_LIST;
}
@@ -1694,12 +1683,15 @@
public void afterActivityCreated(DirectoryFragment fragment) {}
}
+ boolean isSelected(int position) {
+ return mSelectionManager.getSelection().contains(position);
+ }
+
/**
* The data model for the current loaded directory.
*/
@VisibleForTesting
public static final class Model implements DocumentContext {
- private MultiSelectManager mSelectionManager;
private RecyclerView.Adapter<?> mViewAdapter;
private Context mContext;
private int mCursorCount;
@@ -1710,45 +1702,11 @@
@Nullable private String info;
@Nullable private String error;
- Model(Context context, MultiSelectManager selectionManager,
- RecyclerView.Adapter<?> viewAdapter) {
+ Model(Context context, RecyclerView.Adapter<?> viewAdapter) {
mContext = context;
- mSelectionManager = selectionManager;
mViewAdapter = viewAdapter;
}
- /**
- * Selects all files in the current directory.
- * @return true if the selection state changed for any files.
- */
- boolean selectAll() {
- return mSelectionManager.setItemsSelected(0, mCursorCount, true);
- }
-
- /**
- * Clones the current selection into the given Selection object.
- * @param selection
- * @return The selection that was passed in, for convenience.
- */
- Selection getSelection(Selection selection) {
- return mSelectionManager.getSelection(selection);
- }
-
- /**
- * @return The current selection (the live instance, not a copy).
- */
- Selection getSelection() {
- return mSelectionManager.getSelection();
- }
-
- boolean isSelected(int position) {
- return mSelectionManager.getSelection().contains(position);
- }
-
- void clearSelection() {
- mSelectionManager.clearSelection();
- }
-
void update(DirectoryResult result) {
if (DEBUG) Log.i(TAG, "Updating model with new result set.");
@@ -1821,11 +1779,6 @@
return mIsLoading;
}
- private List<DocumentInfo> getSelectedDocuments() {
- Selection sel = getSelection(new Selection());
- return getDocuments(sel);
- }
-
List<DocumentInfo> getDocuments(Selection items) {
final int size = (items != null) ? items.size() : 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 1330b3c..3b985ec 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -323,26 +323,36 @@
private void openDocument(DocumentInfo doc, @Nullable DocumentContext siblings) {
Intent intent = null;
if (siblings != null) {
- QuickViewIntentBuilder builder =
- new QuickViewIntentBuilder(getPackageManager(), doc, siblings);
+ QuickViewIntentBuilder builder = new QuickViewIntentBuilder(
+ getPackageManager(), getResources(), doc, siblings);
intent = builder.build();
}
- // fallback to traditional VIEW action...
- if (intent == null) {
- intent = new Intent(Intent.ACTION_VIEW);
- intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.setData(doc.derivedUri);
+ if (intent != null) {
+ // TODO: un-work around issue b/24963914. Should be fixed soon.
+ try {
+ startActivity(intent);
+ return;
+ } catch (SecurityException e) {
+ // carry on to regular view mode.
+ Log.e(TAG, "Caught security error: " + e.getLocalizedMessage());
+ }
}
+ // fallback to traditional VIEW action...
+ intent = new Intent(Intent.ACTION_VIEW);
+ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setData(doc.derivedUri);
+
if (DEBUG && intent.getClipData() != null) {
Log.d(TAG, "Starting intent w/ clip data: " + intent.getClipData());
}
try {
startActivity(intent);
- } catch (ActivityNotFoundException ex2) {
- Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
+ } catch (ActivityNotFoundException e) {
+ Snackbars.makeSnackbar(
+ this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 858fb42..87c037d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -37,16 +37,13 @@
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.GestureDetector;
-import android.view.GestureDetector.OnDoubleTapListener;
-import android.view.GestureDetector.OnGestureListener;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import com.android.documentsui.Events.InputEvent;
import com.android.documentsui.Events.MotionInputEvent;
-import com.google.android.collect.Lists;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -56,7 +53,7 @@
* Additionally it can be configured to restrict selection to a single element, @see
* #setSelectMode.
*/
-public final class MultiSelectManager {
+public final class MultiSelectManager implements View.OnKeyListener {
/** Selection mode for multiple select. **/
public static final int MODE_MULTIPLE = 0;
@@ -72,33 +69,26 @@
private Selection mIntermediateSelection;
private Range mRanger;
+ private SelectionEnvironment mEnvironment;
+
private final List<MultiSelectManager.Callback> mCallbacks = new ArrayList<>(1);
private Adapter<?> mAdapter;
- private ItemFinder mHelper;
private boolean mSingleSelect;
@Nullable private BandController mBandManager;
/**
* @param recyclerView
- * @param gestureDelegate Option delegate gesture listener.
* @param mode Selection mode
- * @template A gestureDelegate that implements both {@link OnGestureListener}
- * and {@link OnDoubleTapListener}
*/
- public <L extends OnGestureListener & OnDoubleTapListener> MultiSelectManager(
- final RecyclerView recyclerView, L gestureDelegate, int mode) {
+ public MultiSelectManager(final RecyclerView recyclerView, int mode) {
+ this(recyclerView.getAdapter(), mode);
- this(
- recyclerView.getAdapter(),
- new RuntimeItemFinder(recyclerView),
- mode);
+ mEnvironment = new RuntimeSelectionEnvironment(recyclerView);
if (mode == MODE_MULTIPLE) {
- mBandManager = new BandController(
- mHelper,
- new RuntimeBandEnvironment(recyclerView));
+ mBandManager = new BandController();
}
GestureDetector.SimpleOnGestureListener listener =
@@ -115,15 +105,8 @@
}
};
- CompositeOnGestureListener compositeListener =
- new CompositeOnGestureListener(
- Lists.<OnGestureListener>newArrayList(listener, gestureDelegate),
- Lists.<OnDoubleTapListener>newArrayList(listener, gestureDelegate));
-
- final GestureDetector detector =
- new GestureDetector(recyclerView.getContext(), compositeListener);
-
- detector.setOnDoubleTapListener(compositeListener);
+ final GestureDetector detector = new GestureDetector(recyclerView.getContext(), listener);
+ detector.setOnDoubleTapListener(listener);
recyclerView.addOnItemTouchListener(
new RecyclerView.OnItemTouchListener() {
@@ -131,37 +114,15 @@
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
detector.onTouchEvent(e);
- if (mBandManager == null) {
- return false;
+ if (mBandManager != null) {
+ return mBandManager.handleEvent(new MotionInputEvent(e, recyclerView));
}
-
- // b/23793622 notes the fact that we *never* receiver ACTION_DOWN
- // events in onTouchEvent. Where it not for this issue, we'd
- // push start handling down into handleInputEvent.
- if (mBandManager.shouldStart(e)) {
- // endBandSelect is handled in handleInputEvent.
- mBandManager.startBandSelect(
- new Point((int) e.getX(), (int) e.getY()));
- } else if (mBandManager.isActive()
- && Events.isMouseEvent(e)
- && Events.isActionUp(e)) {
- // Same issue here w b/23793622. The ACTION_UP event
- // is only evert dispatched to onTouchEvent when
- // there is some associated motion. If a user taps
- // mouse, but doesn't move, then band select gets
- // started BUT not ended. Causing phantom
- // bands to appear when the user later clicks to start
- // band select.
- mBandManager.handleInputEvent(
- new MotionInputEvent(e, recyclerView));
- }
-
- return mBandManager.isActive();
+ return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
- mBandManager.handleInputEvent(
+ mBandManager.processInputEvent(
new MotionInputEvent(e, recyclerView));
}
@Override
@@ -174,13 +135,11 @@
* @hide
*/
@VisibleForTesting
- MultiSelectManager(Adapter<?> adapter, ItemFinder helper, int mode) {
+ MultiSelectManager(Adapter<?> adapter, int mode) {
checkNotNull(adapter, "'adapter' cannot be null.");
- checkNotNull(helper, "'helper' cannot be null.");
mSingleSelect = mode == MODE_SINGLE;
- mHelper = helper;
mAdapter = adapter;
mAdapter.registerAdapterDataObserver(
@@ -871,36 +830,10 @@
}
/**
- * Provides functionality for MultiSelectManager. Exists primarily to tests that are
- * fully isolated from RecyclerView.
- */
- interface ItemFinder {
- int findItemPosition(MotionEvent e);
- }
-
- /** ItemFinder implementation backed by good ol' RecyclerView. */
- private static final class RuntimeItemFinder implements ItemFinder {
-
- private final RecyclerView mView;
-
- RuntimeItemFinder(RecyclerView view) {
- mView = view;
- }
-
- @Override
- public int findItemPosition(MotionEvent e) {
- View view = mView.findChildViewUnder(e.getX(), e.getY());
- return view != null
- ? mView.getChildAdapterPosition(view)
- : RecyclerView.NO_POSITION;
- }
- }
-
- /**
* Provides functionality for BandController. Exists primarily to tests that are
* fully isolated from RecyclerView.
*/
- interface BandEnvironment {
+ interface SelectionEnvironment {
void showBand(Rect rect);
void hideBand();
void addOnScrollListener(RecyclerView.OnScrollListener listener);
@@ -913,29 +846,39 @@
Point createAbsolutePoint(Point relativePoint);
Rect getAbsoluteRectForChildViewAt(int index);
int getAdapterPositionAt(int index);
+ int getAdapterPositionForChildView(View view);
int getColumnCount();
int getRowCount();
int getChildCount();
int getVisibleChildCount();
+ void focusItem(int position);
}
/** RvFacade implementation backed by good ol' RecyclerView. */
- private static final class RuntimeBandEnvironment implements BandEnvironment {
+ private static final class RuntimeSelectionEnvironment implements SelectionEnvironment {
private final RecyclerView mView;
private final Drawable mBand;
private boolean mIsOverlayShown = false;
- RuntimeBandEnvironment(RecyclerView rv) {
+ RuntimeSelectionEnvironment(RecyclerView rv) {
mView = rv;
mBand = mView.getContext().getTheme().getDrawable(R.drawable.band_select_overlay);
}
@Override
+ public int getAdapterPositionForChildView(View view) {
+ if (view.getParent() == mView) {
+ return mView.getChildAdapterPosition(view);
+ } else {
+ return RecyclerView.NO_POSITION;
+ }
+ }
+
+ @Override
public int getAdapterPositionAt(int index) {
- View child = mView.getChildAt(index);
- return mView.getChildViewHolder(child).getAdapterPosition();
+ return getAdapterPositionForChildView(mView.getChildAt(index));
}
@Override
@@ -1032,6 +975,28 @@
public void hideBand() {
mView.getOverlay().remove(mBand);
}
+
+ @Override
+ public void focusItem(final int pos) {
+ // If the item is already in view, focus it; otherwise, scroll to it and focus it.
+ RecyclerView.ViewHolder vh = mView.findViewHolderForAdapterPosition(pos);
+ if (vh != null) {
+ vh.itemView.requestFocus();
+ } else {
+ // Don't smooth scroll; that taxes the system unnecessarily and makes the scroll
+ // handling logic below more complicated. See b/24865658.
+ mView.scrollToPosition(pos);
+ // Set a one-time listener to request focus when the scroll has completed.
+ mView.addOnScrollListener(
+ new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView view, int dx, int dy) {
+ view.findViewHolderForAdapterPosition(pos).itemView.requestFocus();
+ view.removeOnScrollListener(this);
+ }
+ });
+ }
+ }
}
public interface Callback {
@@ -1061,110 +1026,6 @@
}
/**
- * A composite {@code OnGestureDetector} that allows us to delegate unhandled
- * events to an outside party (presumably DirectoryFragment).
- * @template A gestureDelegate that implements both {@link OnGestureListener}
- * and {@link OnDoubleTapListener}
- */
- private static final class CompositeOnGestureListener
- implements OnGestureListener, OnDoubleTapListener {
-
- private List<OnGestureListener> mGestureListeners;
- private List<OnDoubleTapListener> mTapListeners;
-
- public CompositeOnGestureListener(
- List<OnGestureListener> gestureListeners,
- List<OnDoubleTapListener> tapListeners) {
- mGestureListeners = gestureListeners;
- mTapListeners = tapListeners;
- }
-
- @Override
- public boolean onDown(MotionEvent e) {
- for (OnGestureListener l : mGestureListeners) {
- if (l.onDown(e)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void onShowPress(MotionEvent e) {
- for (OnGestureListener l : mGestureListeners) {
- l.onShowPress(e);
- }
- }
-
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- for (OnGestureListener l : mGestureListeners) {
- if (l.onSingleTapUp(e)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- for (OnGestureListener l : mGestureListeners) {
- if (l.onScroll(e1, e2, distanceX, distanceY)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void onLongPress(MotionEvent e) {
- for (OnGestureListener l : mGestureListeners) {
- l.onLongPress(e);
- }
- }
-
- @Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- for (OnGestureListener l : mGestureListeners) {
- if (l.onFling(e1, e2, velocityX, velocityY)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onSingleTapConfirmed(MotionEvent e) {
- for (OnDoubleTapListener listener : mTapListeners) {
- if (listener.onSingleTapConfirmed(e)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onDoubleTap(MotionEvent e) {
- for (OnDoubleTapListener listener : mTapListeners) {
- if (listener.onDoubleTap(e)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onDoubleTapEvent(MotionEvent e) {
- for (OnDoubleTapListener listener : mTapListeners) {
- if (listener.onDoubleTapEvent(e)) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
* Provides mouse driven band-select support when used in conjunction with {@link RecyclerView}
* and {@link MultiSelectManager}. This class is responsible for rendering the band select
* overlay and selecting overlaid items via MultiSelectManager.
@@ -1174,8 +1035,6 @@
private static final int NOT_SET = -1;
- private final ItemFinder mItemFinder;
- private final BandEnvironment mEnvironment;
private final Runnable mModelBuilder;
@Nullable private Rect mBounds;
@@ -1188,20 +1047,41 @@
private long mScrollStartTime = NOT_SET;
private final Runnable mViewScroller = new ViewScroller();
- public BandController(ItemFinder finder, final BandEnvironment environment) {
- mItemFinder = finder;
- mEnvironment = environment;
+ public BandController() {
mEnvironment.addOnScrollListener(this);
mModelBuilder = new Runnable() {
@Override
public void run() {
- mModel = new GridModel(environment);
+ mModel = new GridModel(mEnvironment);
mModel.addOnSelectionChangedListener(BandController.this);
}
};
}
+ public boolean handleEvent(MotionInputEvent e) {
+ // b/23793622 notes the fact that we *never* receive ACTION_DOWN
+ // events in onTouchEvent. Where it not for this issue, we'd
+ // push start handling down into handleInputEvent.
+ if (mBandManager.shouldStart(e)) {
+ // endBandSelect is handled in handleInputEvent.
+ mBandManager.startBandSelect(e.getOrigin());
+ } else if (mBandManager.isActive()
+ && e.isMouseEvent()
+ && e.isActionUp()) {
+ // Same issue here w b/23793622. The ACTION_UP event
+ // is only evert dispatched to onTouchEvent when
+ // there is some associated motion. If a user taps
+ // mouse, but doesn't move, then band select gets
+ // started BUT not ended. Causing phantom
+ // bands to appear when the user later clicks to start
+ // band select.
+ mBandManager.processInputEvent(e);
+ }
+
+ return isActive();
+ }
+
private boolean isActive() {
return mModel != null;
}
@@ -1220,12 +1100,12 @@
}
}
- boolean shouldStart(MotionEvent e) {
+ boolean shouldStart(MotionInputEvent e) {
return !isActive()
- && Events.isMouseEvent(e) // a mouse
- && Events.isActionDown(e) // the initial button press
+ && e.isMouseEvent() // a mouse
+ && e.isActionDown() // the initial button press
&& mAdapter.getItemCount() > 0
- && mItemFinder.findItemPosition(e) == RecyclerView.NO_ID; // in empty space
+ && e.getItemPosition() == RecyclerView.NO_ID; // in empty space
}
boolean shouldStop(InputEvent input) {
@@ -1238,7 +1118,7 @@
* Processes a MotionEvent by starting, ending, or resizing the band select overlay.
* @param input
*/
- private void handleInputEvent(InputEvent input) {
+ private void processInputEvent(InputEvent input) {
checkArgument(input.isMouseEvent());
if (shouldStop(input)) {
@@ -1459,7 +1339,7 @@
private static final int LOWER_LEFT = LOWER | LEFT;
private static final int LOWER_RIGHT = LOWER | RIGHT;
- private final BandEnvironment mHelper;
+ private final SelectionEnvironment mHelper;
private final List<OnSelectionChangedListener> mOnSelectionChangedListeners =
new ArrayList<>();
@@ -1497,7 +1377,7 @@
// should expand from when Shift+click is used.
private int mPositionNearestOrigin = NOT_SET;
- GridModel(BandEnvironment helper) {
+ GridModel(SelectionEnvironment helper) {
mHelper = helper;
mHelper.addOnScrollListener(this);
}
@@ -2041,4 +1921,72 @@
return true;
}
}
+
+ // TODO: Might have to move this to a more global level. e.g. What should happen if the
+ // user taps a file and then presses shift-down? Currently the RecyclerView never even sees
+ // the key event. Perhaps install a global key handler to catch those events while in
+ // selection mode?
+ @Override
+ public boolean onKey(View view, int keyCode, KeyEvent event) {
+ // Listen for key-down events. This allows the handler to respond appropriately when
+ // the user holds down the arrow keys for navigation.
+ if (event.getAction() != KeyEvent.ACTION_DOWN) {
+ return false;
+ }
+
+ int target = RecyclerView.NO_POSITION;
+ if (keyCode == KeyEvent.KEYCODE_MOVE_HOME) {
+ target = 0;
+ } else if (keyCode == KeyEvent.KEYCODE_MOVE_END) {
+ target = mAdapter.getItemCount() - 1;
+ } else {
+ // Find a navigation target based on the arrow key that the user pressed. Ignore
+ // navigation targets that aren't items in the recycler view.
+ int searchDir = -1;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ searchDir = View.FOCUS_UP;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ searchDir = View.FOCUS_DOWN;
+ break;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ searchDir = View.FOCUS_LEFT;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ searchDir = View.FOCUS_RIGHT;
+ break;
+ }
+ if (searchDir != -1) {
+ View targetView = view.focusSearch(searchDir);
+ target = mEnvironment.getAdapterPositionForChildView(targetView);
+ }
+ }
+
+ if (target == RecyclerView.NO_POSITION) {
+ // If there is no valid navigation target, don't handle the keypress.
+ return false;
+ }
+
+ // Focus the new file.
+ mEnvironment.focusItem(target);
+
+ if (event.isShiftPressed()) {
+ if (mSelection.isEmpty()) {
+ // If there is no selection, start a selection when the user presses shift-arrow.
+ toggleSelection(mEnvironment.getAdapterPositionForChildView(view));
+ } else {
+ // Deal with b/24802917 (selected items can't be focused) by adjusting the
+ // selection sorted the focused item isn't in the selection.
+ target -= Integer.signum(target - mRanger.mBegin);
+ mRanger.snapSelection(target);
+ }
+ } else if (!event.isShiftPressed() && !mSelection.isEmpty()) {
+ // If there is a selection, clear it if the user presses arrow with no shift.
+ clearSelection();
+ }
+
+ return true;
+ }
+
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index 607cb95..6a424a6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -25,11 +25,13 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
+import android.text.TextUtils;
import android.util.Log;
import com.android.documentsui.BaseActivity.DocumentContext;
@@ -43,13 +45,20 @@
private final DocumentInfo mDocument;
private final DocumentContext mContext;
- public ClipData mClipData;
- public int mDocumentLocation;
- private PackageManager mPkgManager;
+ private final PackageManager mPkgManager;
+ private final Resources mResources;
+
+ private ClipData mClipData;
+ private int mDocumentLocation;
public QuickViewIntentBuilder(
- PackageManager pkgManager, DocumentInfo doc, DocumentContext context) {
+ PackageManager pkgManager,
+ Resources resources,
+ DocumentInfo doc,
+ DocumentContext context) {
+
mPkgManager = pkgManager;
+ mResources = resources;
mDocument = doc;
mContext = context;
}
@@ -61,25 +70,37 @@
@Nullable Intent build() {
if (DEBUG) Log.d(TAG, "Preparing intent for doc:" + mDocument.documentId);
+ String trustedPkg = mResources.getString(R.string.trusted_quick_viewer_package);
+
Intent intent = new Intent(Intent.ACTION_QUICK_VIEW);
intent.setDataAndType(mDocument.derivedUri, mDocument.mimeType);
-
- // Try to resolve the intent. If a matching app isn't installed, it won't resolve.
- ComponentName handler = intent.resolveActivity(mPkgManager);
- if (handler == null) {
- return null;
- }
-
- Cursor cursor = mContext.getCursor();
- for (int i = 0; i < cursor.getCount(); i++) {
- onNextItem(i, cursor);
- }
-
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.putExtra(Intent.EXTRA_INDEX, mDocumentLocation);
- intent.setClipData(mClipData);
- return intent;
+ if (TextUtils.isEmpty(trustedPkg)) {
+ if (hasRegisteredHandler(intent)) {
+ return intent;
+ }
+ } else {
+ intent.setPackage(trustedPkg);
+ if (hasRegisteredHandler(intent)) {
+ // We have a trusted handler. Load all of the docs into the intent.
+ Cursor cursor = mContext.getCursor();
+ for (int i = 0; i < cursor.getCount(); i++) {
+ onNextItem(i, cursor);
+ }
+ intent.putExtra(Intent.EXTRA_INDEX, mDocumentLocation);
+ intent.setClipData(mClipData);
+
+ return intent;
+ }
+ }
+
+ return null;
+ }
+
+ private boolean hasRegisteredHandler(Intent intent) {
+ // Try to resolve the intent. If a matching app isn't installed, it won't resolve.
+ return intent.resolveActivity(mPkgManager) != null;
}
private void onNextItem(int index, Cursor cursor) {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
index 98ffb77..ace9e27 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
@@ -22,10 +22,8 @@
import android.database.Cursor;
import android.database.MatrixCursor;
import android.provider.DocumentsContract.Document;
-import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.RecyclerView;
import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
import android.test.mock.MockContentResolver;
import android.view.ViewGroup;
@@ -64,7 +62,7 @@
r.cursor = cursor;
// Instantiate the model with a dummy view adapter and listener that (for now) do nothing.
- model = new Model(mContext, null, new DummyAdapter());
+ model = new Model(mContext, new DummyAdapter());
model.addUpdateListener(new DummyListener());
model.update(r);
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
index 2447469..ceb8cdc 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
@@ -16,13 +16,9 @@
package com.android.documentsui;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import android.support.v7.widget.RecyclerView;
import android.test.AndroidTestCase;
import android.util.SparseBooleanArray;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -51,13 +47,11 @@
private MultiSelectManager mManager;
private TestAdapter mAdapter;
private TestCallback mCallback;
- private EventHelper mEventHelper;
public void setUp() throws Exception {
mAdapter = new TestAdapter(items);
mCallback = new TestCallback();
- mEventHelper = new EventHelper();
- mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_MULTIPLE);
+ mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_MULTIPLE);
mManager.addCallback(mCallback);
}
@@ -175,7 +169,7 @@
}
public void testSingleSelectMode() {
- mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_SINGLE);
+ mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE);
mManager.addCallback(mCallback);
longPress(20);
tap(13);
@@ -183,7 +177,7 @@
}
public void testSingleSelectMode_ShiftTap() {
- mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_SINGLE);
+ mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE);
mManager.addCallback(mCallback);
longPress(13);
shiftTap(20);
@@ -269,26 +263,13 @@
assertEquals(selection.toString(), expected, selection.size());
}
- private static final class EventHelper implements MultiSelectManager.ItemFinder {
-
- @Override
- public int findItemPosition(MotionEvent e) {
- throw new UnsupportedOperationException();
- }
- }
-
private static final class TestCallback implements MultiSelectManager.Callback {
Set<Integer> ignored = new HashSet<>();
- private int mLastChangedPosition;
- private boolean mLastChangedSelected;
private boolean mSelectionChanged = false;
@Override
- public void onItemStateChanged(int position, boolean selected) {
- this.mLastChangedPosition = position;
- this.mLastChangedSelected = selected;
- }
+ public void onItemStateChanged(int position, boolean selected) {}
@Override
public boolean onBeforeItemStateChange(int position, boolean selected) {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
index aa50b48..f6683fa 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
@@ -24,6 +24,7 @@
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.test.AndroidTestCase;
import android.util.SparseBooleanArray;
+import android.view.View;
import com.android.documentsui.MultiSelectManager.GridModel;
@@ -34,14 +35,14 @@
private static final int VIEWPORT_HEIGHT = 500;
private static GridModel model;
- private static TestHelper helper;
+ private static TestEnvironment env;
private static SparseBooleanArray lastSelection;
private static int viewWidth;
private static void setUp(int numChildren, int numColumns) {
- helper = new TestHelper(numChildren, numColumns);
+ env = new TestEnvironment(numChildren, numColumns);
viewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX);
- model = new GridModel(helper);
+ model = new GridModel(env);
model.addOnSelectionChangedListener(
new GridModel.OnSelectionChangedListener() {
@Override
@@ -54,7 +55,7 @@
@Override
public void tearDown() {
model = null;
- helper = null;
+ env = null;
lastSelection = null;
}
@@ -176,12 +177,12 @@
}
private static void scroll(int dy) {
- assertTrue(helper.verticalOffset + VIEWPORT_HEIGHT + dy <= helper.getTotalHeight());
- helper.verticalOffset += dy;
+ assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight());
+ env.verticalOffset += dy;
model.onScrolled(null, 0, dy);
}
- private static final class TestHelper implements MultiSelectManager.BandEnvironment {
+ private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment {
public int horizontalOffset = 0;
public int verticalOffset = 0;
@@ -189,7 +190,7 @@
private final int mNumRows;
private final int mNumChildren;
- public TestHelper(int numChildren, int numColumns) {
+ public TestEnvironment(int numChildren, int numColumns) {
mNumChildren = numChildren;
mNumColumns = numColumns;
mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
@@ -307,5 +308,15 @@
public void removeCallback(Runnable r) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public int getAdapterPositionForChildView(View view) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void focusItem(int i) {
+ throw new UnsupportedOperationException();
+ }
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 9a91ca4..29b319f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -133,10 +133,6 @@
mLockPatternView.setSaveEnabled(false);
mLockPatternView.setOnPatternListener(new UnlockPatternListener());
- // stealth mode will be the same for the life of this screen
- mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
- KeyguardUpdateMonitor.getCurrentUser()));
-
// vibrate mode will be the same for the life of this screen
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
@@ -176,6 +172,8 @@
@Override
public void reset() {
// reset lock pattern
+ mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
+ KeyguardUpdateMonitor.getCurrentUser()));
mLockPatternView.enableInput();
mLockPatternView.setEnabled(true);
mLockPatternView.clearPattern();
diff --git a/packages/MtpDocumentsProvider/res/values/strings.xml b/packages/MtpDocumentsProvider/res/values/strings.xml
index 37efdb5..7a4087b 100644
--- a/packages/MtpDocumentsProvider/res/values/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values/strings.xml
@@ -14,7 +14,11 @@
limitations under the License.
-->
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title of the external storage application [CHAR LIMIT=32] -->
<string name="app_label">MTP Storage</string>
+ <!-- Name of MTP root shown in UI. Please align the two strings (device
+ model and storage name) in proper order in the language.
+ [CHAR LIMIT=32] -->
+ <string name="root_name"><xliff:g id="device_model" example="Nexus 9">%1$s</xliff:g> <xliff:g id="storage_name" example="Internal Storage">%2$s</xliff:g></string>
</resources>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
index b5694b7..cc510a9 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
@@ -16,25 +16,24 @@
package com.android.mtp;
+import android.content.res.Resources;
import android.database.MatrixCursor;
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
-import java.util.Date;
-
final class CursorHelper {
static final int DUMMY_HANDLE_FOR_ROOT = 0;
private CursorHelper() {
}
- static void addToCursor(MtpRoot root, MatrixCursor.RowBuilder builder) {
+ static void addToCursor(Resources resources, MtpRoot root, MatrixCursor.RowBuilder builder) {
final Identifier identifier = new Identifier(
root.mDeviceId, root.mStorageId, DUMMY_HANDLE_FOR_ROOT);
builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
- builder.add(Document.COLUMN_DISPLAY_NAME, root.mDescription);
+ builder.add(Document.COLUMN_DISPLAY_NAME, root.getRootName(resources));
builder.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
builder.add(Document.COLUMN_LAST_MODIFIED, null);
builder.add(Document.COLUMN_FLAGS, 0);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index a1a43c1..9d5850b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -18,6 +18,7 @@
import android.content.ContentResolver;
import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.Point;
@@ -59,8 +60,8 @@
private MtpManager mMtpManager;
private ContentResolver mResolver;
private Map<Integer, DeviceToolkit> mDeviceToolkits;
- private DocumentLoader mDocumentLoaders;
private RootScanner mRootScanner;
+ private Resources mResources;
/**
* Provides singleton instance to MtpDocumentsService.
@@ -72,6 +73,7 @@
@Override
public boolean onCreate() {
sSingleton = this;
+ mResources = getContext().getResources();
mMtpManager = new MtpManager(getContext());
mResolver = getContext().getContentResolver();
mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
@@ -80,7 +82,8 @@
}
@VisibleForTesting
- void onCreateForTesting(MtpManager mtpManager, ContentResolver resolver) {
+ void onCreateForTesting(Resources resources, MtpManager mtpManager, ContentResolver resolver) {
+ mResources = resources;
mMtpManager = mtpManager;
mResolver = resolver;
mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
@@ -99,10 +102,8 @@
final MatrixCursor.RowBuilder builder = cursor.newRow();
builder.add(Root.COLUMN_ROOT_ID, rootIdentifier.toRootId());
builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
- builder.add(Root.COLUMN_TITLE, root.mDescription);
- builder.add(
- Root.COLUMN_DOCUMENT_ID,
- rootIdentifier.toDocumentId());
+ builder.add(Root.COLUMN_TITLE, root.getRootName(mResources));
+ builder.add(Root.COLUMN_DOCUMENT_ID, rootIdentifier.toDocumentId());
builder.add(Root.COLUMN_AVAILABLE_BYTES , root.mFreeSpace);
}
cursor.setNotificationUri(
@@ -143,7 +144,7 @@
if (identifier.mStorageId != root.mStorageId)
continue;
final MatrixCursor cursor = new MatrixCursor(projection);
- CursorHelper.addToCursor(root, cursor.newRow());
+ CursorHelper.addToCursor(mResources, root, cursor.newRow());
return cursor;
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index af7f691..714936d 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -107,7 +107,10 @@
}
final MtpRoot[] results = new MtpRoot[storageIds.length];
for (int i = 0; i < storageIds.length; i++) {
- results[i] = new MtpRoot(deviceId, device.getStorageInfo(storageIds[i]));
+ results[i] = new MtpRoot(
+ device.getDeviceId(),
+ device.getDeviceInfo().getModel(),
+ device.getStorageInfo(storageIds[i]));
}
return results;
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
index 9dd53c0..ec338c3 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
@@ -16,6 +16,7 @@
package com.android.mtp;
+import android.content.res.Resources;
import android.mtp.MtpStorageInfo;
import com.android.internal.annotations.VisibleForTesting;
@@ -23,6 +24,7 @@
class MtpRoot {
final int mDeviceId;
final int mStorageId;
+ final String mDeviceModelName;
final String mDescription;
final long mFreeSpace;
final long mMaxCapacity;
@@ -31,21 +33,24 @@
@VisibleForTesting
MtpRoot(int deviceId,
int storageId,
+ String deviceName,
String description,
long freeSpace,
long maxCapacity,
String volumeIdentifier) {
mDeviceId = deviceId;
mStorageId = storageId;
+ mDeviceModelName = deviceName;
mDescription = description;
mFreeSpace = freeSpace;
mMaxCapacity = maxCapacity;
mVolumeIdentifier = volumeIdentifier;
}
- MtpRoot(int deviceId, MtpStorageInfo storageInfo) {
+ MtpRoot(int deviceId, String deviceModelName, MtpStorageInfo storageInfo) {
mDeviceId = deviceId;
mStorageId = storageInfo.getStorageId();
+ mDeviceModelName = deviceModelName;
mDescription = storageInfo.getDescription();
mFreeSpace = storageInfo.getFreeSpace();
mMaxCapacity = storageInfo.getMaxCapacity();
@@ -59,6 +64,7 @@
final MtpRoot other = (MtpRoot) object;
return mDeviceId == other.mDeviceId &&
mStorageId == other.mStorageId &&
+ mDeviceModelName.equals(other.mDeviceModelName) &&
mDescription.equals(other.mDescription) &&
mFreeSpace == other.mFreeSpace &&
mMaxCapacity == other.mMaxCapacity &&
@@ -67,7 +73,19 @@
@Override
public int hashCode() {
- return mDeviceId ^ mStorageId ^ mDescription.hashCode() ^ ((int) mFreeSpace) ^
- ((int) mMaxCapacity) ^ mVolumeIdentifier.hashCode();
+ return mDeviceId ^ mStorageId ^ mDeviceModelName.hashCode() ^ mDescription.hashCode() ^
+ ((int) mFreeSpace) ^ ((int) mMaxCapacity) ^ mVolumeIdentifier.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "MtpRoot{Name: " + mDeviceModelName + " " + mDescription + "}";
+ }
+
+ String getRootName(Resources resources) {
+ return String.format(
+ resources.getString(R.string.root_name),
+ mDeviceModelName,
+ mDescription);
}
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 4b3a5cd..0c03814c 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -16,19 +16,21 @@
package com.android.mtp;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo.Builder;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsContract;
import android.test.AndroidTestCase;
+import android.test.mock.MockResources;
import android.test.suitebuilder.annotation.SmallTest;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.util.Date;
@SmallTest
public class MtpDocumentsProviderTest extends AndroidTestCase {
@@ -37,13 +39,23 @@
private TestContentResolver mResolver;
private MtpDocumentsProvider mProvider;
private TestMtpManager mMtpManager;
+ private final MockResources mResources = new MockResources() {
+ @Override
+ public String getString(int id) throws NotFoundException {
+ switch (id) {
+ case R.string.root_name:
+ return "%1$s %2$s";
+ }
+ throw new NotFoundException();
+ }
+ };
@Override
public void setUp() throws IOException {
mResolver = new TestContentResolver();
mMtpManager = new TestMtpManager(getContext());
mProvider = new MtpDocumentsProvider();
- mProvider.onCreateForTesting(mMtpManager, mResolver);
+ mProvider.onCreateForTesting(mResources, mMtpManager, mResolver);
}
public void testOpenAndCloseDevice() throws Exception {
@@ -52,6 +64,7 @@
new MtpRoot(
0 /* deviceId */,
1 /* storageId */,
+ "Device A" /* device model name */,
"Storage A" /* volume description */,
1024 /* free space */,
2048 /* total space */,
@@ -86,6 +99,7 @@
new MtpRoot(
0 /* deviceId */,
1 /* storageId */,
+ "Device A" /* device model name */,
"Storage A" /* volume description */,
1024 /* free space */,
2048 /* total space */,
@@ -101,6 +115,7 @@
new MtpRoot(
0 /* deviceId */,
1 /* storageId */,
+ "Device A" /* device model name */,
"Storage A" /* volume description */,
1024 /* free space */,
2048 /* total space */,
@@ -121,6 +136,7 @@
new MtpRoot(
0 /* deviceId */,
1 /* storageId */,
+ "Device A" /* device model name */,
"Storage A" /* volume description */,
1024 /* free space */,
2048 /* total space */,
@@ -130,6 +146,7 @@
new MtpRoot(
1 /* deviceId */,
1 /* storageId */,
+ "Device B" /* device model name */,
"Storage B" /* volume description */,
2048 /* free space */,
4096 /* total space */,
@@ -146,7 +163,7 @@
assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
- assertEquals("Storage A", cursor.getString(3));
+ assertEquals("Device A Storage A", cursor.getString(3));
assertEquals("0_1_0", cursor.getString(4));
assertEquals(1024, cursor.getInt(5));
}
@@ -162,7 +179,7 @@
assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
- assertEquals("Storage B", cursor.getString(3));
+ assertEquals("Device B Storage B", cursor.getString(3));
assertEquals("1_1_0", cursor.getString(4));
assertEquals(2048, cursor.getInt(5));
}
@@ -183,6 +200,7 @@
new MtpRoot(
1 /* deviceId */,
1 /* storageId */,
+ "Device B" /* device model name */,
"Storage B" /* volume description */,
2048 /* free space */,
4096 /* total space */,
@@ -200,7 +218,7 @@
assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
// TODO: Add storage icon for MTP devices.
assertTrue(cursor.isNull(2) /* icon */);
- assertEquals("Storage B", cursor.getString(3));
+ assertEquals("Device B Storage B", cursor.getString(3));
assertEquals("1_1_0", cursor.getString(4));
assertEquals(2048, cursor.getInt(5));
}
@@ -265,6 +283,7 @@
new MtpRoot(
0 /* deviceId */,
1 /* storageId */,
+ "Device A" /* device model name */,
"Storage A" /* volume description */,
1024 /* free space */,
4096 /* total space */,
@@ -276,7 +295,7 @@
cursor.moveToNext();
assertEquals("0_1_0", cursor.getString(0));
assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
- assertEquals("Storage A", cursor.getString(2));
+ assertEquals("Device A Storage A", cursor.getString(2));
assertTrue(cursor.isNull(3));
assertEquals(0, cursor.getInt(4));
assertEquals(3072, cursor.getInt(5));
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 5605388..3d92cc2 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -18,12 +18,10 @@
import android.content.Context;
import android.mtp.MtpObjectInfo;
-import android.mtp.MtpObjectInfo.Builder;
import android.os.ParcelFileDescriptor;
import java.io.IOException;
import java.util.Arrays;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index c8871c4..3efd33d 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -384,7 +384,7 @@
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"دستگاه قفل باقی میماند تا زمانی که قفل آن را به صورت دستی باز کنید"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"دریافت سریعتر اعلانها"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"قبل از باز کردن قفل آنها را مشاهده کنید"</string>
- <string name="hidden_notifications_cancel" msgid="3690709735122344913">"خیر، سپاسگزارم"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"نه سپاسگزارم"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"راهاندازی"</string>
<string name="notification_expand_button_text" msgid="1037425494153780718">"مشاهده همه"</string>
<string name="notification_collapse_button_text" msgid="6883253262134328057">"پنهان کردن همه"</string>
@@ -396,7 +396,7 @@
<string name="screen_pinning_description" msgid="1346522416878235405">"تا زمانی که پین را بردارید، در نما نگهداشته میشود. برای برداشتن پین، برگشت و نمای کلی را به صورت همزمان لمس کنید و نگهدارید."</string>
<string name="screen_pinning_description_accessible" msgid="8518446209564202557">"تا زمانی که پین را بردارید، در نما نگهداشته میشود. برای برداشتن پین، نمای کلی را لمس کنید و نگهدارید."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"متوجه شدم"</string>
- <string name="screen_pinning_negative" msgid="3741602308343880268">"خیر متشکرم"</string>
+ <string name="screen_pinning_negative" msgid="3741602308343880268">"نه سپاسگزارم"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> مخفی شود؟"</string>
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"دفعه بعد که آن را روشن کنید، در تنظیمات نشان داده میشود."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"پنهان کردن"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 3593b34..6427644 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -313,7 +313,7 @@
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre brådskande aviseringar nedan"</string>
<string name="notification_tap_again" msgid="8524949573675922138">"Tryck igen för att öppna"</string>
- <string name="keyguard_unlock" msgid="8043466894212841998">"Dra uppåt om du vill låsa upp"</string>
+ <string name="keyguard_unlock" msgid="8043466894212841998">"Svep uppåt om du vill låsa upp"</string>
<string name="phone_hint" msgid="4872890986869209950">"Dra från ikonen och öppna telefonen"</string>
<string name="voice_hint" msgid="8939888732119726665">"Dra från ikonen och öppna röstassistenten"</string>
<string name="camera_hint" msgid="7939688436797157483">"Dra från ikonen och öppna kameran"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index c070a0e..955efb5 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -20,6 +20,7 @@
<attr name="keyCode" format="integer" />
<!-- does this button generate longpress / repeat events? -->
<attr name="keyRepeat" format="boolean" />
+ <attr name="android:contentDescription" />
</declare-styleable>
<declare-styleable name="ToggleSlider">
<attr name="text" format="string" />
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
index a0ceb29..e6c42da 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
@@ -20,8 +20,8 @@
public static float evaluate(float value) {
float evaluation = 0.0f;
if (value < 1.00) evaluation++;
- if (value < 0.95) evaluation++;
if (value < 0.90) evaluation++;
+ if (value < 0.70) evaluation++;
return evaluation;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
index c125e00..652d969 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
@@ -27,10 +27,12 @@
@Override
public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ float ratio;
if (stroke.getTotalLength() == 0.0f) {
- return 1.0f;
+ ratio = 1.0f;
+ } else {
+ ratio = stroke.getEndPointLength() / stroke.getTotalLength();
}
- return EndPointRatioEvaluator.evaluate(
- stroke.getEndPointLength() / stroke.getTotalLength());
+ return EndPointRatioEvaluator.evaluate(ratio);
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index a7a5694..27d4c0e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -48,7 +48,7 @@
private final float mDpi;
private HistoryEvaluator mHistoryEvaluator;
- private boolean mEnableClassifier = true;
+ private boolean mEnableClassifier = false;
private int mCurrentType = Classifier.GENERIC;
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
index 2a45fa3..d50d406 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
@@ -20,8 +20,8 @@
public static float evaluate(float value) {
float evaluation = 0.0f;
if (value < 1.00) evaluation++;
- if (value < 0.95) evaluation++;
if (value < 0.90) evaluation++;
+ if (value < 0.70) evaluation++;
return evaluation;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
index c0e4a2d..afd8d01 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
@@ -19,9 +19,10 @@
public class SpeedEvaluator {
public static float evaluate(float value) {
float evaluation = 0.0f;
- if (value < 4.0 || value > 35.0) evaluation += 1.0;
- if (value < 2.2) evaluation += 1.0;
- if (value > 50.0) evaluation += 1.0;
+ if (value < 4.0) evaluation++;
+ if (value < 2.2) evaluation++;
+ if (value > 35.0) evaluation++;
+ if (value > 50.0) evaluation++;
return evaluation;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
index 349aa9e..4c6cea0 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
@@ -19,8 +19,10 @@
public class SpeedRatioEvaluator {
public static float evaluate(float value) {
float evaluation = 0.0f;
- if (value > 9.0) ++evaluation;
- if (value > 18.0) ++evaluation;
+ if (value <= 1.0) evaluation++;
+ if (value <= 0.5) evaluation++;
+ if (value > 9.0) evaluation++;
+ if (value > 18.0) evaluation++;
return evaluation;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
index 8f9a7e1..48b1b6e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
@@ -19,10 +19,10 @@
public class SpeedVarianceEvaluator {
public static float evaluate(float value) {
float evaluation = 0.0f;
- if (value > 0.06) evaluation += 1.0;
- if (value > 0.15) evaluation += 1.0;
- if (value > 0.3) evaluation += 1.0;
- if (value > 0.6) evaluation += 1.0;
+ if (value > 0.06) evaluation++;
+ if (value > 0.15) evaluation++;
+ if (value > 0.3) evaluation++;
+ if (value > 0.6) evaluation++;
return evaluation;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 687f6c1..7b0a44f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -149,10 +149,7 @@
}
private boolean isFalseTouch() {
- if (mFalsingManager.isClassiferEnabled()) {
- return mFalsingManager.isFalseTouch();
- }
- return !mDraggedFarEnough;
+ return mFalsingManager.isFalseTouch() || !mDraggedFarEnough;
}
private void captureStartingChild(float x, float y) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 210be9f..33f21ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -31,6 +31,7 @@
import android.view.ViewStub;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.LinearInterpolator;
+import android.widget.Chronometer;
import android.widget.ImageView;
import com.android.systemui.R;
@@ -88,6 +89,7 @@
private NotificationGuts mGuts;
private StatusBarNotification mStatusBarNotification;
private boolean mIsHeadsUp;
+ private boolean mLastChronometerRunning = true;
private View mExpandButton;
private View mExpandButtonDivider;
private ViewStub mExpandButtonStub;
@@ -295,6 +297,7 @@
*/
public void setPinned(boolean pinned) {
mIsPinned = pinned;
+ setChronometerRunning(mLastChronometerRunning);
}
public boolean isPinned() {
@@ -320,6 +323,41 @@
return mJustClicked;
}
+ public void setChronometerRunning(boolean running) {
+ mLastChronometerRunning = running;
+ setChronometerRunning(running, mPrivateLayout);
+ setChronometerRunning(running, mPublicLayout);
+ if (mChildrenContainer != null) {
+ List<ExpandableNotificationRow> notificationChildren =
+ mChildrenContainer.getNotificationChildren();
+ for (int i = 0; i < notificationChildren.size(); i++) {
+ ExpandableNotificationRow child = notificationChildren.get(i);
+ child.setChronometerRunning(running);
+ }
+ }
+ }
+
+ private void setChronometerRunning(boolean running, NotificationContentView layout) {
+ if (layout != null) {
+ running = running || isPinned();
+ View contractedChild = layout.getContractedChild();
+ View expandedChild = layout.getExpandedChild();
+ View headsUpChild = layout.getHeadsUpChild();
+ setChronometerRunningForChild(running, contractedChild);
+ setChronometerRunningForChild(running, expandedChild);
+ setChronometerRunningForChild(running, headsUpChild);
+ }
+ }
+
+ private void setChronometerRunningForChild(boolean running, View child) {
+ if (child != null) {
+ View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
+ if (chronometer instanceof Chronometer) {
+ ((Chronometer) chronometer).setStarted(running);
+ }
+ }
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
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 76edafa..ebe7785 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -229,7 +229,7 @@
}
// On expanding, single mouse click expands the panel instead of dragging.
- if (isFullyCollapsed() && event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
+ if (isFullyCollapsed() && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (event.getAction() == MotionEvent.ACTION_UP) {
expand(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 4f7756e..56f6036 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -170,7 +170,6 @@
*/
public void showNotification(NotificationData.Entry headsUp) {
if (DEBUG) Log.v(TAG, "showNotification");
- MetricsLogger.count(mContext, "note_peek", 1);
addHeadsUpEntry(headsUp);
updateNotification(headsUp, true);
headsUp.setInterruption();
@@ -247,6 +246,9 @@
return;
}
mHasPinnedNotification = hasPinnedNotification;
+ if (mHasPinnedNotification) {
+ MetricsLogger.count(mContext, "note_peek", 1);
+ }
updateTouchableRegionListener();
for (OnHeadsUpChangedListener listener : mListeners) {
listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 4c99792..4d268ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -18,12 +18,14 @@
import android.app.ActivityManager;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.hardware.input.InputManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
@@ -43,6 +45,7 @@
public class KeyButtonView extends ImageView {
+ private int mContentDescriptionRes;
private long mDownTime;
private int mCode;
private int mTouchSlop;
@@ -79,8 +82,14 @@
mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
+ TypedValue value = new TypedValue();
+ if (a.getValue(R.styleable.KeyButtonView_android_contentDescription, value)) {
+ mContentDescriptionRes = value.resourceId;
+ }
+
a.recycle();
+
setClickable(true);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -88,6 +97,15 @@
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ if (mContentDescriptionRes != 0) {
+ setContentDescription(mContext.getString(mContentDescriptionRes));
+ }
+ }
+
+ @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
if (mCode != 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 5e5f810..d50f8ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1789,6 +1789,7 @@
((ExpandableView) child).setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
+ updateChronometerForChild(child);
if (canChildBeDismissed(child)) {
// Make sure the dismissButton is visible and not in the animated state.
// We need to do this to avoid a race where a clearable notification is added after the
@@ -2298,6 +2299,21 @@
mStackScrollAlgorithm.setIsExpanded(isExpanded);
if (changed) {
updateNotificationAnimationStates();
+ updateChronometers();
+ }
+ }
+
+ private void updateChronometers() {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ updateChronometerForChild(getChildAt(i));
+ }
+ }
+
+ private void updateChronometerForChild(View child) {
+ if (child instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ row.setChronometerRunning(mIsExpanded);
}
}
@@ -2320,6 +2336,7 @@
}
mStackScrollAlgorithm.onReset(view);
updateAnimationState(view);
+ updateChronometerForChild(view);
}
private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 87b490d..496e4df 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -109,6 +109,9 @@
private static final String ACTION_STEP_IDLE_STATE =
"com.android.server.device_idle.STEP_IDLE_STATE";
+ private static final String ACTION_STEP_LIGHT_IDLE_STATE =
+ "com.android.server.device_idle.STEP_LIGHT_IDLE_STATE";
+
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
private PowerManagerInternal mLocalPowerManager;
@@ -118,16 +121,16 @@
private Sensor mMotionSensor;
private LocationManager mLocationManager;
private LocationRequest mLocationRequest;
- private PendingIntent mSensingAlarmIntent;
private PendingIntent mAlarmIntent;
+ private PendingIntent mLightAlarmIntent;
private Intent mIdleIntent;
+ private Intent mLightIdleIntent;
private Display mCurDisplay;
private AnyMotionDetector mAnyMotionDetector;
private boolean mEnabled;
private boolean mForceIdle;
private boolean mScreenOn;
private boolean mCharging;
- private boolean mSensing;
private boolean mNotMoving;
private boolean mLocating;
private boolean mLocated;
@@ -138,7 +141,7 @@
/** Device is currently active. */
private static final int STATE_ACTIVE = 0;
- /** Device is inactve (screen off, no motion) and we are waiting to for idle. */
+ /** Device is inactive (screen off, no motion) and we are waiting to for idle. */
private static final int STATE_INACTIVE = 1;
/** Device is past the initial inactive period, and waiting for the next idle period. */
private static final int STATE_IDLE_PENDING = 2;
@@ -163,12 +166,35 @@
}
}
+ /** Device is currently active. */
+ private static final int LIGHT_STATE_ACTIVE = 0;
+ /** Device is inactive (screen off) and we are waiting to for the first light idle. */
+ private static final int LIGHT_STATE_INACTIVE = 1;
+ /** Device is in the light idle state, trying to stay asleep as much as possible. */
+ private static final int LIGHT_STATE_IDLE = 2;
+ /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
+ private static final int LIGHT_STATE_IDLE_MAINTENANCE = 3;
+ /** Device light idle state is overriden, now applying full doze state. */
+ private static final int LIGHT_STATE_OVERRIDE = 4;
+ private static String lightStateToString(int state) {
+ switch (state) {
+ case LIGHT_STATE_ACTIVE: return "ACTIVE";
+ case LIGHT_STATE_INACTIVE: return "INACTIVE";
+ case LIGHT_STATE_IDLE: return "IDLE";
+ case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
+ case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
+ default: return Integer.toString(state);
+ }
+ }
+
private int mState;
+ private int mLightState;
private long mInactiveTimeout;
private long mNextAlarmTime;
private long mNextIdlePendingDelay;
private long mNextIdleDelay;
+ private long mNextLightAlarmTime;
public final AtomicFile mConfigFile;
@@ -250,10 +276,14 @@
if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
Uri data = intent.getData();
String ssp;
- if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+ if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
removePowerSaveWhitelistAppInternal(ssp);
}
}
+ } else if (ACTION_STEP_LIGHT_IDLE_STATE.equals(intent.getAction())) {
+ synchronized (DeviceIdleController.this) {
+ stepLightIdleStateLocked();
+ }
} else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
synchronized (DeviceIdleController.this) {
stepIdleStateLocked();
@@ -305,7 +335,7 @@
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public boolean registerLocked() {
- boolean success = false;
+ boolean success;
if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
} else {
@@ -380,6 +410,8 @@
*/
private final class Constants extends ContentObserver {
// Key names stored in the settings value.
+ private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
+ private static final String KEY_LIGHT_IDLE_PENDING_TIMEOUT = "light_idle_pending_to";
private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
private static final String KEY_SENSING_TIMEOUT = "sensing_to";
private static final String KEY_LOCATING_TIMEOUT = "locating_to";
@@ -401,6 +433,22 @@
"sms_temp_app_whitelist_duration";
/**
+ * This is the time, after becoming inactive, that we will start going
+ * in to light-weight idle mode.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_LIGHT_IDLE_TIMEOUT
+ */
+ public long LIGHT_IDLE_TIMEOUT;
+
+ /**
+ * This is the initial time, after light idle idle, that we will will sit in the
+ * LIGHT_IDLE_MAINTENANCE period for the system to run normally before returning to idle.
+ * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+ * @see #KEY_LIGHT_IDLE_PENDING_TIMEOUT
+ */
+ public long LIGHT_IDLE_PENDING_TIMEOUT;
+
+ /**
* This is the time, after becoming inactive, at which we start looking at the
* motion sensor to determine if the device is being left alone. We don't do this
* immediately after going inactive just because we don't want to be continually running
@@ -455,7 +503,8 @@
/**
* This is the initial time, after being idle, that we will allow ourself to be back
- * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
+ * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
+ * idle.
* @see Settings.Global#DEVICE_IDLE_CONSTANTS
* @see #KEY_IDLE_PENDING_TIMEOUT
*/
@@ -555,6 +604,10 @@
Slog.e(TAG, "Bad device idle settings", e);
}
+ LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT,
+ !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
+ LIGHT_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_PENDING_TIMEOUT,
+ !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
!COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
@@ -592,6 +645,14 @@
void dump(PrintWriter pw) {
pw.println(" Settings:");
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
+ TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
+ pw.println();
+
+ pw.print(" "); pw.print(KEY_LIGHT_IDLE_PENDING_TIMEOUT); pw.print("=");
+ TimeUtils.formatDuration(LIGHT_IDLE_PENDING_TIMEOUT, pw);
+ pw.println();
+
pw.print(" "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
pw.println();
@@ -689,9 +750,10 @@
static final int MSG_WRITE_CONFIG = 1;
static final int MSG_REPORT_IDLE_ON = 2;
- static final int MSG_REPORT_IDLE_OFF = 3;
- static final int MSG_REPORT_ACTIVE = 4;
- static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
+ static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
+ static final int MSG_REPORT_IDLE_OFF = 4;
+ static final int MSG_REPORT_ACTIVE = 5;
+ static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -704,43 +766,70 @@
case MSG_WRITE_CONFIG: {
handleWriteConfigFile();
} break;
- case MSG_REPORT_IDLE_ON: {
+ case MSG_REPORT_IDLE_ON:
+ case MSG_REPORT_IDLE_ON_LIGHT: {
EventLogTags.writeDeviceIdleOnStart();
- mLocalPowerManager.setDeviceIdleMode(true);
+ final boolean fullChanged;
+ final boolean lightChanged;
+ if (msg.what == MSG_REPORT_IDLE_ON) {
+ fullChanged = mLocalPowerManager.setDeviceIdleMode(true);
+ lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
+ } else {
+ fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+ lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
+ }
try {
mNetworkPolicyManager.setDeviceIdleMode(true);
- mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
+ mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
+ ? BatteryStats.DEVICE_IDLE_MODE_FULL
+ : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
} catch (RemoteException e) {
}
- getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ if (fullChanged) {
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ }
+ if (lightChanged) {
+ getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
+ }
EventLogTags.writeDeviceIdleOnComplete();
} break;
case MSG_REPORT_IDLE_OFF: {
EventLogTags.writeDeviceIdleOffStart("unknown");
- mLocalPowerManager.setDeviceIdleMode(false);
+ final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+ final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
- mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
+ mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
+ null, Process.myUid());
} catch (RemoteException e) {
}
- getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ if (fullChanged) {
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ }
+ if (lightChanged) {
+ getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
+ }
EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_REPORT_ACTIVE: {
String activeReason = (String)msg.obj;
int activeUid = msg.arg1;
- boolean needBroadcast = msg.arg2 != 0;
EventLogTags.writeDeviceIdleOffStart(
activeReason != null ? activeReason : "unknown");
- mLocalPowerManager.setDeviceIdleMode(false);
+ final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+ final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
- mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
+ mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
+ activeReason, activeUid);
} catch (RemoteException e) {
}
- if (needBroadcast) {
+ if (fullChanged) {
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
}
+ if (lightChanged) {
+ getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
+ }
EventLogTags.writeDeviceIdleOffComplete();
} break;
case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
@@ -909,6 +998,7 @@
// a battery update the next time the level drops.
mCharging = true;
mState = STATE_ACTIVE;
+ mLightState = LIGHT_STATE_ACTIVE;
mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
}
@@ -967,18 +1057,22 @@
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
- Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
+ Intent intentLight = new Intent(ACTION_STEP_LIGHT_IDLE_STATE)
.setPackage("android")
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
+ mLightAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentLight, 0);
mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
+ mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
+ mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ACTION_STEP_IDLE_STATE);
+ filter.addAction(ACTION_STEP_LIGHT_IDLE_STATE);
getContext().registerReceiver(mReceiver, filter);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -1283,32 +1377,43 @@
}
void scheduleReportActiveLocked(String activeReason, int activeUid) {
- Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
- mState == STATE_IDLE ? 1 : 0, activeReason);
+ Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
mHandler.sendMessage(msg);
}
void becomeActiveLocked(String activeReason, int activeUid) {
if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
- if (mState != STATE_ACTIVE) {
+ if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
+ EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
scheduleReportActiveLocked(activeReason, activeUid);
mState = STATE_ACTIVE;
+ mLightState = LIGHT_STATE_ACTIVE;
mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
resetIdleManagementLocked();
+ resetLightIdleManagementLocked();
}
}
void becomeInactiveIfAppropriateLocked() {
if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
- if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
+ if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled) {
// Screen has turned off; we are now going to become inactive and start
// waiting to see if we will ultimately go idle.
- mState = STATE_INACTIVE;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
- resetIdleManagementLocked();
- scheduleAlarmLocked(mInactiveTimeout, false);
- EventLogTags.writeDeviceIdle(mState, "no activity");
+ if (mState == STATE_ACTIVE) {
+ mState = STATE_INACTIVE;
+ if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
+ resetIdleManagementLocked();
+ scheduleAlarmLocked(mInactiveTimeout, false);
+ EventLogTags.writeDeviceIdle(mState, "no activity");
+ }
+ if (mLightState == LIGHT_STATE_ACTIVE) {
+ mLightState = LIGHT_STATE_INACTIVE;
+ if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
+ resetLightIdleManagementLocked();
+ scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
+ EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
+ }
}
}
@@ -1316,12 +1421,15 @@
mNextIdlePendingDelay = 0;
mNextIdleDelay = 0;
cancelAlarmLocked();
- cancelSensingAlarmLocked();
cancelLocatingLocked();
stopMonitoringMotionLocked();
mAnyMotionDetector.stop();
}
+ void resetLightIdleManagementLocked() {
+ cancelLightAlarmLocked();
+ }
+
void exitForceIdleLocked() {
if (mForceIdle) {
mForceIdle = false;
@@ -1331,6 +1439,37 @@
}
}
+ void stepLightIdleStateLocked() {
+ if (mLightState == LIGHT_STATE_OVERRIDE) {
+ // If we are already in full device idle mode, then
+ // there is nothing left to do for light mode.
+ return;
+ }
+
+ if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
+ EventLogTags.writeDeviceIdleLightStep();
+
+ switch (mLightState) {
+ case LIGHT_STATE_INACTIVE:
+ case LIGHT_STATE_IDLE_MAINTENANCE:
+ scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
+ if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
+ mLightState = LIGHT_STATE_IDLE;
+ EventLogTags.writeDeviceIdleLight(mLightState, "step");
+ mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
+ break;
+ case LIGHT_STATE_IDLE:
+ // We have been idling long enough, now it is time to do some work.
+ scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_PENDING_TIMEOUT);
+ if (DEBUG) Slog.d(TAG,
+ "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
+ mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
+ EventLogTags.writeDeviceIdleLight(mLightState, "step");
+ mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
+ break;
+ }
+ }
+
void stepIdleStateLocked() {
if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
EventLogTags.writeDeviceIdleStep();
@@ -1361,8 +1500,7 @@
mState = STATE_SENSING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
EventLogTags.writeDeviceIdle(mState, "step");
- scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
- cancelSensingAlarmLocked();
+ cancelAlarmLocked();
cancelLocatingLocked();
mAnyMotionDetector.checkForAnyMotion();
mNotMoving = false;
@@ -1374,8 +1512,7 @@
mState = STATE_LOCATING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
EventLogTags.writeDeviceIdle(mState, "step");
- cancelSensingAlarmLocked();
- scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
+ scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
if (mLocationManager != null
&& mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
mLocationManager.requestLocationUpdates(mLocationRequest,
@@ -1401,7 +1538,7 @@
// Otherwise, we have to move from locating into idle maintenance.
case STATE_LOCATING:
- cancelSensingAlarmLocked();
+ cancelAlarmLocked();
cancelLocatingLocked();
mAnyMotionDetector.stop();
case STATE_IDLE_MAINTENANCE:
@@ -1412,6 +1549,10 @@
if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
mState = STATE_IDLE;
+ if (mLightState != LIGHT_STATE_OVERRIDE) {
+ mLightState = LIGHT_STATE_OVERRIDE;
+ cancelLightAlarmLocked();
+ }
EventLogTags.writeDeviceIdle(mState, "step");
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
break;
@@ -1439,11 +1580,22 @@
// The device is not yet active, so we want to go back to the pending idle
// state to wait again for no motion. Note that we only monitor for motion
// after moving out of the inactive state, so no need to worry about that.
+ boolean becomeInactive = false;
if (mState != STATE_ACTIVE) {
scheduleReportActiveLocked(type, Process.myUid());
mState = STATE_ACTIVE;
mInactiveTimeout = timeout;
EventLogTags.writeDeviceIdle(mState, type);
+ becomeInactive = true;
+ }
+ if (mLightState == LIGHT_STATE_OVERRIDE) {
+ // We went out of light idle mode because we had started full idle mode... let's
+ // now go back and reset things so we resume light idling if appropriate.
+ mLightState = STATE_ACTIVE;
+ EventLogTags.writeDeviceIdleLight(mLightState, type);
+ becomeInactive = true;
+ }
+ if (becomeInactive) {
becomeInactiveIfAppropriateLocked();
}
}
@@ -1501,11 +1653,10 @@
}
}
- void cancelSensingAlarmLocked() {
- if (mSensing) {
- if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
- mAlarmManager.cancel(mSensingAlarmIntent);
- mSensing = false;
+ void cancelLightAlarmLocked() {
+ if (mNextLightAlarmTime != 0) {
+ mNextLightAlarmTime = 0;
+ mAlarmManager.cancel(mLightAlarmIntent);
}
}
@@ -1536,13 +1687,18 @@
}
}
- void scheduleSensingAlarmLocked(long delay) {
- if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
- cancelSensingAlarmLocked();
- mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
+ void scheduleLightAlarmLocked(long delay) {
+ if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
+ if (mMotionSensor == null) {
+ // If there is no motion sensor on this device, then we won't schedule
+ // alarms, because we can't determine if the device is not moving. This effectively
+ // turns off normal execution of device idling, although it is still possible to
+ // manually poke it by pretending like the alarm is going off.
+ return;
+ }
+ mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- mNextAlarmTime, mSensingAlarmIntent);
- mSensing = true;
+ mNextLightAlarmTime, mLightAlarmIntent);
}
private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
@@ -1778,7 +1934,21 @@
try {
exitForceIdleLocked();
stepIdleStateLocked();
- pw.print("Stepped to: "); pw.println(stateToString(mState));
+ pw.print("Stepped to: ");
+ pw.println(stateToString(mState));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ } else if ("light-step".equals(cmd)) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ synchronized (this) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ exitForceIdleLocked();
+ stepLightIdleStateLocked();
+ pw.print("Stepped to: "); pw.println(lightStateToString(mLightState));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2041,8 +2211,7 @@
pw.print(" mScreenOn="); pw.println(mScreenOn);
pw.print(" mCharging="); pw.println(mCharging);
pw.print(" mMotionActive="); pw.println(mMotionListener.active);
- pw.print(" mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
- pw.println(mNotMoving);
+ pw.print(" mNotMoving="); pw.println(mNotMoving);
pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
pw.print(mHasGps); pw.print(" mHasNetwork=");
pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
@@ -2052,7 +2221,9 @@
if (mLastGpsLocation != null) {
pw.print(" mLastGpsLocation="); pw.println(mLastGpsLocation);
}
- pw.print(" mState="); pw.println(stateToString(mState));
+ pw.print(" mState="); pw.print(stateToString(mState));
+ pw.print(" mLightState=");
+ pw.println(lightStateToString(mLightState));
pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
pw.println();
if (mNextAlarmTime != 0) {
@@ -2070,6 +2241,11 @@
TimeUtils.formatDuration(mNextIdleDelay, pw);
pw.println();
}
+ if (mNextLightAlarmTime != 0) {
+ pw.print(" mNextLightAlarmTime=");
+ TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
+ pw.println();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 9bf2aaa..516e2f4 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -194,6 +194,8 @@
34006 device_idle_off_start (reason|3)
34007 device_idle_off_phase (what|3)
34008 device_idle_off_complete
+34009 device_idle_light (state|1|5), (reason|3)
+34010 device_idle_light_step
# ---------------------------
# DisplayManagerService.java
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index de48e71..7c0a820 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -25,6 +25,7 @@
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
+import android.os.SystemProperties;
import android.os.UserManager;
import android.util.ArrayMap;
import android.util.Log;
@@ -386,6 +387,12 @@
}
private int getUserParentOrSelfId(int userId) {
+ // Device supports File Based Encryption, and lock is applied per-user
+ if ("file".equals(SystemProperties.get("ro.crypto.type", "none"))) {
+ return userId;
+ }
+ // Device uses Block Based Encryption, and the parent user's lock is used for the whole
+ // device.
if (userId != 0) {
final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final UserInfo pi = um.getProfileParent(userId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ee8a5e8..7df50d5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1229,7 +1229,6 @@
int mSamplingInterval = 0;
boolean mAutoStopProfiler = false;
int mProfileType = 0;
- String mOpenGlTraceApp = null;
final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
String mMemWatchDumpProcName;
String mMemWatchDumpFile;
@@ -6161,11 +6160,6 @@
samplingInterval = mSamplingInterval;
profileAutoStop = mAutoStopProfiler;
}
- boolean enableOpenGlTrace = false;
- if (mOpenGlTraceApp != null && mOpenGlTraceApp.equals(processName)) {
- enableOpenGlTrace = true;
- mOpenGlTraceApp = null;
- }
boolean enableTrackAllocation = false;
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
enableTrackAllocation = true;
@@ -6199,9 +6193,9 @@
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
- mBinderTransactionTrackingEnabled, enableOpenGlTrace,
- enableTrackAllocation, isRestrictedBackupMode || !normalMode,
- app.persistent, new Configuration(mConfiguration), app.compat,
+ mBinderTransactionTrackingEnabled, enableTrackAllocation,
+ isRestrictedBackupMode || !normalMode, app.persistent,
+ new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
@@ -10809,19 +10803,6 @@
}
}
- void setOpenGlTraceApp(ApplicationInfo app, String processName) {
- synchronized (this) {
- boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
- if (!isDebuggable) {
- if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
- throw new SecurityException("Process not debuggable: " + app.packageName);
- }
- }
-
- mOpenGlTraceApp = processName;
- }
- }
-
void setTrackAllocationApp(ApplicationInfo app, String processName) {
synchronized (this) {
boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
@@ -13936,15 +13917,6 @@
pw.print(" mMemWatchDumpPid="); pw.print(mMemWatchDumpPid);
pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid);
}
- if (mOpenGlTraceApp != null) {
- if (dumpPackage == null || dumpPackage.equals(mOpenGlTraceApp)) {
- if (needSep) {
- pw.println();
- needSep = false;
- }
- pw.println(" mOpenGlTraceApp=" + mOpenGlTraceApp);
- }
- }
if (mTrackAllocationApp != null) {
if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
if (needSep) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 00664b4..a59f7ef 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -901,14 +901,8 @@
prev.task.touchActiveTime();
clearLaunchTime(prev);
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
- // In freeform mode we only update the thumbnail when there is no thumbnail yet since every
- // focus change will request a thumbnail to be taken.
- // Note furthermore that since windows can change their content in freeform mode all the
- // time a thumbnail is possibly constantly outdated.
- if (mService.mHasRecents &&
- (next == null || next.noDisplay || next.task != prev.task || uiSleeping) &&
- (!prev.task.hasThumbnail() ||
- prev.task.stack.mStackId != FREEFORM_WORKSPACE_STACK_ID)) {
+ if (mService.mHasRecents
+ && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
prev.updateThumbnailLocked(screenshotActivities(prev), null);
}
stopFullyDrawnTraceIfNeeded();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 2a36230..d6ad547 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -922,10 +922,6 @@
mService.setDebugApp(aInfo.processName, true, false);
}
- if ((startFlags & ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
- mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
- }
-
if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
mService.setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 62768c3..c7228ce 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -834,10 +834,10 @@
}
@Override
- public void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid) {
+ public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteDeviceIdleModeLocked(enabled, activeReason, activeUid);
+ mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid);
}
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 5d5b5fe..1999f49 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -485,14 +485,6 @@
}
/**
- * Returns true when we have a thumbnail.
- * @return Returns true if there is a thumbnail.
- */
- boolean hasThumbnail() {
- return mLastThumbnail != null;
- }
-
- /**
* Sets the last thumbnail.
* @return whether the thumbnail was set
*/
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e6dc895..15e5393 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -104,6 +104,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Random;
import java.util.Set;
@@ -258,7 +259,8 @@
private BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
- boolean idle = mPowerManager.isDeviceIdleMode();
+ boolean idle = mPowerManager.isDeviceIdleMode()
+ || mPowerManager.isLightDeviceIdleMode();
mDeviceIsIdle = idle;
if (idle) {
cancelActiveSync(
@@ -478,6 +480,7 @@
context.registerReceiver(mStorageIntentReceiver, intentFilter);
intentFilter = new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ intentFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
context.registerReceiver(mDeviceIdleReceiver, intentFilter);
intentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
@@ -3370,7 +3373,7 @@
if (!smaller.containsKey(key)) {
return false;
}
- if (!bigger.get(key).equals(smaller.get(key))) {
+ if (!Objects.equals(bigger.get(key), smaller.get(key))) {
return false;
}
}
@@ -3378,7 +3381,6 @@
}
/**
- * TODO: Get rid of this when we separate sync settings extras from dev specified extras.
* @return true if the provided key is used by the SyncManager in scheduling the sync.
*/
private static boolean isSyncSetting(String key) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 3c50102..2b535b9 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -162,8 +162,12 @@
Slog.d(TAG, "Removing jobs for user: " + userId);
}
cancelJobsForUser(userId);
- } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
- updateIdleMode(mPowerManager != null ? mPowerManager.isDeviceIdleMode() : false);
+ } else if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())
+ || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
+ updateIdleMode(mPowerManager != null
+ ? (mPowerManager.isDeviceIdleMode()
+ || mPowerManager.isLightDeviceIdleMode())
+ : false);
}
}
};
@@ -340,6 +344,7 @@
mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ userFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
diff --git a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
index db2b941..b06fe58 100644
--- a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
@@ -131,7 +131,7 @@
}
break;
case MotionEvent.ACTION_HOVER_MOVE:
- if (event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
+ if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (!mMouseHoveringAtEdge && event.getY() == 0) {
mCallbacks.onMouseHoverAtTop();
mMouseHoveringAtEdge = true;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ced0433..6498dd9 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -444,6 +444,9 @@
// True if we are currently in device idle mode.
private boolean mDeviceIdleMode;
+ // True if we are currently in light device idle mode.
+ private boolean mLightDeviceIdleMode;
+
// Set of app ids that we will always respect the wake locks for.
int[] mDeviceIdleWhitelist = new int[0];
@@ -2292,12 +2295,18 @@
}
}
- private boolean isDeviceIdleModeInternal() {
+ boolean isDeviceIdleModeInternal() {
synchronized (mLock) {
return mDeviceIdleMode;
}
}
+ boolean isLightDeviceIdleModeInternal() {
+ synchronized (mLock) {
+ return mLightDeviceIdleMode;
+ }
+ }
+
private void handleBatteryStateChangedLocked() {
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
@@ -2368,7 +2377,7 @@
}
}
- void setDeviceIdleModeInternal(boolean enabled) {
+ boolean setDeviceIdleModeInternal(boolean enabled) {
synchronized (mLock) {
if (mDeviceIdleMode != enabled) {
mDeviceIdleMode = enabled;
@@ -2378,7 +2387,19 @@
} else {
EventLogTags.writeDeviceIdleOffPhase("power");
}
+ return true;
}
+ return false;
+ }
+ }
+
+ boolean setLightDeviceIdleModeInternal(boolean enabled) {
+ synchronized (mLock) {
+ if (mLightDeviceIdleMode != enabled) {
+ mLightDeviceIdleMode = enabled;
+ return true;
+ }
+ return false;
}
}
@@ -2671,6 +2692,7 @@
pw.println(" mSandmanSummoned=" + mSandmanSummoned);
pw.println(" mLowPowerModeEnabled=" + mLowPowerModeEnabled);
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
+ pw.println(" mLightDeviceIdleMode=" + mLightDeviceIdleMode);
pw.println(" mDeviceIdleMode=" + mDeviceIdleMode);
pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
@@ -3308,6 +3330,16 @@
}
}
+ @Override // Binder call
+ public boolean isLightDeviceIdleMode() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isLightDeviceIdleModeInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
/**
* Reboots the device.
*
@@ -3576,8 +3608,13 @@
}
@Override
- public void setDeviceIdleMode(boolean enabled) {
- setDeviceIdleModeInternal(enabled);
+ public boolean setDeviceIdleMode(boolean enabled) {
+ return setDeviceIdleModeInternal(enabled);
+ }
+
+ @Override
+ public boolean setLightDeviceIdleMode(boolean enabled) {
+ return setLightDeviceIdleModeInternal(enabled);
}
@Override
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 9f44fea..7abc048 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -16,6 +16,30 @@
package com.android.server.wm;
+import static android.view.WindowManagerInternal.AppTransitionListener;
+import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
+
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -49,30 +73,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-import static android.view.WindowManagerInternal.AppTransitionListener;
-import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
-
// State management of app transitions. When we are preparing for a
// transition, mNextAppTransition will be the kind of transition to
// perform or TRANSIT_NONE if we are not waiting. If we are waiting,
@@ -543,14 +543,15 @@
final int appWidth = appFrame.width();
final int appHeight = appFrame.height();
+ // mTmpStartRect will contain an area around the launcher icon that was pressed. We will
+ // clip reveal from that area in the final area of the app.
getDefaultNextAppTransitionStartRect(mTmpStartRect);
float t = 0f;
if (appHeight > 0) {
t = (float) mTmpStartRect.left / appHeight;
}
- int translationY = mClipRevealTranslationY
- + (int)(appHeight / 7f * t);
+ int translationY = mClipRevealTranslationY + (int)(appHeight / 7f * t);
int centerX = mTmpStartRect.centerX();
int centerY = mTmpStartRect.centerY();
@@ -562,15 +563,20 @@
centerX - halfWidth, centerX + halfWidth, 0, appWidth);
clipAnimLR.setInterpolator(mClipHorizontalInterpolator);
clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f));
+
Animation clipAnimTB = new ClipRectTBAnimation(centerY - halfHeight - translationY,
centerY + halfHeight/ 2 - translationY, 0, appHeight);
clipAnimTB.setInterpolator(mTouchResponseInterpolator);
clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
- TranslateYAnimation translateY = new TranslateYAnimation(
- Animation.ABSOLUTE, translationY, Animation.ABSOLUTE, 0);
- translateY.setInterpolator(mLinearOutSlowInInterpolator);
- translateY.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+ // We might be animating entrance of a docked task, so we need the translate to account
+ // for the app frame in which the window will reside. Every other calculation here
+ // is performed as if the window started at 0,0.
+ translationY -= appFrame.top;
+ TranslateAnimation translate = new TranslateAnimation(-appFrame.left, 0, translationY,
+ 0);
+ translate.setInterpolator(mLinearOutSlowInInterpolator);
+ translate.setDuration(DEFAULT_APP_TRANSITION_DURATION);
// Quick fade-in from icon to app window
final int alphaDuration = DEFAULT_APP_TRANSITION_DURATION / 4;
@@ -581,7 +587,7 @@
AnimationSet set = new AnimationSet(false);
set.addAnimation(clipAnimLR);
set.addAnimation(clipAnimTB);
- set.addAnimation(translateY);
+ set.addAnimation(translate);
set.addAnimation(alpha);
set.setZAdjustment(Animation.ZORDER_TOP);
set.initialize(appWidth, appHeight, appWidth, appHeight);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b409cea..6734fd6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -16,10 +16,14 @@
package com.android.server.wm;
-import static android.app.ActivityManager.*;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.app.ActivityManager.FIRST_STATIC_STACK_ID;
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.LAST_STATIC_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
-import static com.android.server.wm.WindowManagerService.H.UNUSED;
import static com.android.server.wm.WindowManagerService.TAG;
import android.annotation.IntDef;
@@ -30,8 +34,8 @@
import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayInfo;
-
import android.view.Surface;
+
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -424,12 +428,19 @@
return;
}
- final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
+ final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
if (dockedStack == null) {
// Not sure why you are calling this method when there is no docked stack...
throw new IllegalStateException(
"Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
}
+ if (!dockedStack.isVisibleLocked()) {
+ // The docked stack is being dismissed, but we caught before it finished being
+ // dismissed. In that case we want to treat it as if it is not occupying any space and
+ // let others occupy the whole display.
+ mDisplayContent.getLogicalDisplayRect(mTmpRect);
+ return;
+ }
@DockSide
final int dockedSide = dockedStack.getDockSide();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f571d9c..cd5fbb0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2886,6 +2886,8 @@
// isn't affected by the window insets.
contentInsets.set(win.mContentInsets);
appFrame.set(win.mFrame);
+ } else {
+ appFrame.set(containingFrame);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0860f02..4748c96 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3700,7 +3700,10 @@
return;
}
enforceCrossUserPermission(userHandle);
- enforceNotManagedProfile(userHandle, "set the active password");
+ // Managed Profile password can only be changed when file based encryption is present.
+ if (!"file".equals(SystemProperties.get("ro.crypto.type", "none"))) {
+ enforceNotManagedProfile(userHandle, "set the active password");
+ }
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java b/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java
new file mode 100644
index 0000000..be6861c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java
@@ -0,0 +1,64 @@
+package com.android.server.content;
+
+import android.os.Bundle;
+
+import junit.framework.TestCase;
+
+public class SyncManagerTest extends TestCase {
+
+ final String KEY_1 = "key_1";
+ final String KEY_2 = "key_2";
+
+ public void testSyncExtrasEquals_WithNull() throws Exception {
+ Bundle b1 = new Bundle();
+ Bundle b2 = new Bundle();
+
+ b1.putString(KEY_1, null);
+ b2.putString(KEY_1, null);
+
+ assertTrue("Null extra not properly compared between bundles.",
+ SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+ }
+
+ public void testSyncExtrasEqualsBigger_WithNull() throws Exception {
+ Bundle b1 = new Bundle();
+ Bundle b2 = new Bundle();
+
+ b1.putString(KEY_1, null);
+ b2.putString(KEY_1, null);
+
+ b1.putString(KEY_2, "bla");
+ b2.putString(KEY_2, "bla");
+
+ assertTrue("Extras not properly compared between bundles.",
+ SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+ }
+
+ public void testSyncExtrasEqualsFails_differentValues() throws Exception {
+ Bundle b1 = new Bundle();
+ Bundle b2 = new Bundle();
+
+ b1.putString(KEY_1, null);
+ b2.putString(KEY_1, null);
+
+ b1.putString(KEY_2, "bla");
+ b2.putString(KEY_2, "ble"); // different key
+
+ assertFalse("Extras considered equal when they are different.",
+ SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+ }
+
+ public void testSyncExtrasEqualsFails_differentNulls() throws Exception {
+ Bundle b1 = new Bundle();
+ Bundle b2 = new Bundle();
+
+ b1.putString(KEY_1, null);
+ b2.putString(KEY_1, "bla"); // different key
+
+ b1.putString(KEY_2, "ble");
+ b2.putString(KEY_2, "ble");
+
+ assertFalse("Extras considered equal when they are different.",
+ SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+ }
+}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index abb8803..703564c 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -122,6 +122,14 @@
public static final int CAPABILITY_CALL_SUBJECT = 0x40;
/**
+ * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls.
+ * <p>
+ * See {@link #getCapabilities}
+ * @hide
+ */
+ public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
+
+ /**
* URI scheme for telephone number URIs.
*/
public static final String SCHEME_TEL = "tel";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index a410c53..e9b7819 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -152,6 +152,11 @@
}
@Override
+ public boolean isLightDeviceIdleMode() throws RemoteException {
+ return false;
+ }
+
+ @Override
public boolean isScreenBrightnessBoosted() throws RemoteException {
return false;
}