Merge "Fix floating toolbar rendering."
diff --git a/Android.mk b/Android.mk
index 1d797c4..ad164e20 100644
--- a/Android.mk
+++ b/Android.mk
@@ -187,6 +187,8 @@
 	core/java/android/hardware/location/IGeofenceHardware.aidl \
 	core/java/android/hardware/location/IGeofenceHardwareCallback.aidl \
 	core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \
+	core/java/android/hardware/location/IContextHubCallback.aidl \
+	core/java/android/hardware/location/IContextHubService.aidl \
 	core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl \
 	core/java/android/hardware/usb/IUsbManager.aidl \
 	core/java/android/net/ICaptivePortal.aidl \
@@ -288,6 +290,7 @@
 	core/java/com/android/internal/app/IBatteryStats.aidl \
 	core/java/com/android/internal/app/IEphemeralResolver.aidl \
 	core/java/com/android/internal/app/IProcessStats.aidl \
+	core/java/com/android/internal/app/ISoundTriggerService.aidl \
 	core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \
 	core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl \
 	core/java/com/android/internal/app/IVoiceInteractor.aidl \
@@ -330,10 +333,10 @@
 	location/java/android/location/IFusedProvider.aidl \
 	location/java/android/location/IGeocodeProvider.aidl \
 	location/java/android/location/IGeofenceProvider.aidl \
+	location/java/android/location/IGnssStatusListener.aidl \
+	location/java/android/location/IGnssStatusProvider.aidl \
 	location/java/android/location/IGpsMeasurementsListener.aidl \
 	location/java/android/location/IGpsNavigationMessageListener.aidl \
-	location/java/android/location/IGpsStatusListener.aidl \
-	location/java/android/location/IGpsStatusProvider.aidl \
 	location/java/android/location/ILocationListener.aidl \
 	location/java/android/location/ILocationManager.aidl \
 	location/java/android/location/IFusedGeofenceHardware.aidl \
@@ -384,6 +387,8 @@
 	media/java/android/media/tv/ITvInputSessionCallback.aidl \
 	media/java/android/service/media/IMediaBrowserService.aidl \
 	media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl \
+	telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl \
+	telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl \
 	telecomm/java/com/android/internal/telecom/IVideoCallback.aidl \
 	telecomm/java/com/android/internal/telecom/IVideoProvider.aidl \
 	telecomm/java/com/android/internal/telecom/IConnectionService.aidl \
@@ -414,6 +419,7 @@
 	telephony/java/com/android/internal/telephony/ISub.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
 	telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl \
+	telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl \
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
 	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 93884aa..a501ce7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -33,6 +33,7 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -505,6 +506,8 @@
     field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
+    field public static final int endX = 16844051; // 0x1010513
+    field public static final int endY = 16844052; // 0x1010514
     field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
     field public static final int entries = 16842930; // 0x10100b2
@@ -880,6 +883,7 @@
     field public static final int numbersTextColor = 16843937; // 0x10104a1
     field public static final deprecated int numeric = 16843109; // 0x1010165
     field public static final int numericShortcut = 16843236; // 0x10101e4
+    field public static final int offset = 16844053; // 0x1010515
     field public static final int onClick = 16843375; // 0x101026f
     field public static final int oneshot = 16843159; // 0x1010197
     field public static final int opacity = 16843550; // 0x101031e
@@ -1127,6 +1131,8 @@
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
+    field public static final int startX = 16844049; // 0x1010511
+    field public static final int startY = 16844050; // 0x1010512
     field public static final deprecated int startYear = 16843132; // 0x101017c
     field public static final int stateListAnimator = 16843848; // 0x1010448
     field public static final int stateNotNeeded = 16842774; // 0x1010016
@@ -4636,6 +4642,7 @@
     method public android.content.Context getContext();
     method public android.content.Context getTargetContext();
     method public android.app.UiAutomation getUiAutomation();
+    method public android.app.UiAutomation getUiAutomation(int);
     method public boolean invokeContextMenuAction(android.app.Activity, int, int);
     method public boolean invokeMenuActionSync(android.app.Activity, int, int);
     method public boolean isProfiling();
@@ -5532,6 +5539,7 @@
   public final class UiAutomation {
     method public void clearWindowAnimationFrameStats();
     method public boolean clearWindowContentFrameStats(int);
+    method public void destroy();
     method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
     method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -5548,6 +5556,7 @@
     method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
     method public android.graphics.Bitmap takeScreenshot();
     method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
+    field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1
     field public static final int ROTATION_FREEZE_0 = 0; // 0x0
     field public static final int ROTATION_FREEZE_180 = 2; // 0x2
     field public static final int ROTATION_FREEZE_270 = 3; // 0x3
@@ -5788,6 +5797,7 @@
     method public void clearCrossProfileIntentFilters(android.content.ComponentName);
     method public void clearDeviceOwnerApp(java.lang.String);
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
+    method public void clearProfileOwner(android.content.ComponentName);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
     method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
     method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
@@ -5814,6 +5824,7 @@
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
+    method public java.lang.String getOrganizationName(android.content.ComponentName);
     method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -5883,6 +5894,7 @@
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setOrganizationColor(android.content.ComponentName, int);
+    method public void setOrganizationName(android.content.ComponentName, java.lang.String);
     method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
     method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -6509,8 +6521,9 @@
     field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
     field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
     field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_DEVICE_LOCKED = 210007; // 0x33457
-    field public static final int TAG_DEVICE_UNLOCK_ATTEMPT = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
     field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
     field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
   }
@@ -8037,6 +8050,7 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
+    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
     field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler";
@@ -9946,7 +9960,7 @@
     method public final long skip(long) throws java.io.IOException;
   }
 
-  public class ColorStateList implements android.os.Parcelable {
+  public class ColorStateList extends android.content.res.ComplexColor implements android.os.Parcelable {
     ctor public ColorStateList(int[][], int[]);
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -9955,13 +9969,18 @@
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
-    method public boolean isStateful();
     method public static android.content.res.ColorStateList valueOf(int);
     method public android.content.res.ColorStateList withAlpha(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR;
   }
 
+  public abstract class ComplexColor {
+    ctor public ComplexColor();
+    method public abstract int getDefaultColor();
+    method public boolean isStateful();
+  }
+
   public final class Configuration implements java.lang.Comparable android.os.Parcelable {
     ctor public Configuration();
     ctor public Configuration(android.content.res.Configuration);
@@ -10065,6 +10084,11 @@
     field public int uiMode;
   }
 
+  public class GradientColor extends android.content.res.ComplexColor {
+    method public static android.content.res.GradientColor createFromXml(android.content.res.Resources, android.content.res.XmlResourceParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public int getDefaultColor();
+  }
+
   public class ObbInfo implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10124,6 +10148,7 @@
     method public void getValue(java.lang.String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
     method public void getValueForDensity(int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
     method public android.content.res.XmlResourceParser getXml(int) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.ComplexColor loadComplexColor(android.util.TypedValue, int, android.content.res.Resources.Theme);
     method public final android.content.res.Resources.Theme newTheme();
     method public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]);
     method public android.content.res.TypedArray obtainTypedArray(int) throws android.content.res.Resources.NotFoundException;
@@ -10159,6 +10184,7 @@
     method public int getChangingConfigurations();
     method public int getColor(int, int);
     method public android.content.res.ColorStateList getColorStateList(int);
+    method public android.content.res.ComplexColor getComplexColor(int);
     method public float getDimension(int, float);
     method public int getDimensionPixelOffset(int, int);
     method public int getDimensionPixelSize(int, int);
@@ -13355,6 +13381,7 @@
     method public float getResolution();
     method public java.lang.String getStringType();
     method public int getType();
+    method public java.util.UUID getUuid();
     method public java.lang.String getVendor();
     method public int getVersion();
     method public boolean isWakeUpSensor();
@@ -13369,11 +13396,13 @@
     field public static final java.lang.String STRING_TYPE_GRAVITY = "android.sensor.gravity";
     field public static final java.lang.String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
     field public static final java.lang.String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
+    field public static final java.lang.String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
     field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
     field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
     field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
+    field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
     field public static final deprecated java.lang.String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
     field public static final java.lang.String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
     field public static final java.lang.String STRING_TYPE_PRESSURE = "android.sensor.pressure";
@@ -13381,6 +13410,7 @@
     field public static final java.lang.String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
     field public static final java.lang.String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
     field public static final java.lang.String STRING_TYPE_SIGNIFICANT_MOTION = "android.sensor.significant_motion";
+    field public static final java.lang.String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
     field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
     field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
     field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
@@ -13392,11 +13422,13 @@
     field public static final int TYPE_GRAVITY = 9; // 0x9
     field public static final int TYPE_GYROSCOPE = 4; // 0x4
     field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
+    field public static final int TYPE_HEART_BEAT = 31; // 0x1f
     field public static final int TYPE_HEART_RATE = 21; // 0x15
     field public static final int TYPE_LIGHT = 5; // 0x5
     field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
     field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
     field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
+    field public static final int TYPE_MOTION_DETECT = 30; // 0x1e
     field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
     field public static final int TYPE_POSE_6DOF = 28; // 0x1c
     field public static final int TYPE_PRESSURE = 6; // 0x6
@@ -13404,11 +13436,27 @@
     field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
     field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
     field public static final int TYPE_SIGNIFICANT_MOTION = 17; // 0x11
+    field public static final int TYPE_STATIONARY_DETECT = 29; // 0x1d
     field public static final int TYPE_STEP_COUNTER = 19; // 0x13
     field public static final int TYPE_STEP_DETECTOR = 18; // 0x12
     field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
   }
 
+  public class SensorAdditionalInfo {
+    field public static final int TYPE_FRAME_BEGIN = 0; // 0x0
+    field public static final int TYPE_FRAME_END = 1; // 0x1
+    field public static final int TYPE_INTERNAL_TEMPERATURE = 65537; // 0x10001
+    field public static final int TYPE_SAMPLING = 65540; // 0x10004
+    field public static final int TYPE_SENSOR_PLACEMENT = 65539; // 0x10003
+    field public static final int TYPE_UNTRACKED_DELAY = 65536; // 0x10000
+    field public static final int TYPE_VEC3_CALIBRATION = 65538; // 0x10002
+    field public final float[] floatValues;
+    field public final int[] intValues;
+    field public final android.hardware.Sensor sensor;
+    field public final int serial;
+    field public final int type;
+  }
+
   public class SensorEvent {
     field public int accuracy;
     field public android.hardware.Sensor sensor;
@@ -13416,6 +13464,14 @@
     field public final float[] values;
   }
 
+  public abstract class SensorEventCallback implements android.hardware.SensorEventListener2 {
+    ctor public SensorEventCallback();
+    method public void onAccuracyChanged(android.hardware.Sensor, int);
+    method public void onFlushCompleted(android.hardware.Sensor);
+    method public void onSensorAdditionalInfo(android.hardware.SensorAdditionalInfo);
+    method public void onSensorChanged(android.hardware.SensorEvent);
+  }
+
   public abstract interface SensorEventListener {
     method public abstract void onAccuracyChanged(android.hardware.Sensor, int);
     method public abstract void onSensorChanged(android.hardware.SensorEvent);
@@ -13437,6 +13493,7 @@
     method public static void getAngleChange(float[], float[], float[]);
     method public android.hardware.Sensor getDefaultSensor(int);
     method public android.hardware.Sensor getDefaultSensor(int, boolean);
+    method public java.util.List<android.hardware.Sensor> getDynamicSensorList(int);
     method public static float getInclination(float[]);
     method public static float[] getOrientation(float[], float[]);
     method public static void getQuaternionFromVector(float[], float[]);
@@ -13444,6 +13501,8 @@
     method public static void getRotationMatrixFromVector(float[], float[]);
     method public java.util.List<android.hardware.Sensor> getSensorList(int);
     method public deprecated int getSensors();
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13452,6 +13511,7 @@
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
     method public static boolean remapCoordinateSystem(float[], int, int, float[]);
     method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
     method public deprecated void unregisterListener(android.hardware.SensorListener);
     method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13516,6 +13576,12 @@
     field public static final float STANDARD_GRAVITY = 9.80665f;
   }
 
+  public static abstract class SensorManager.DynamicSensorConnectionCallback {
+    ctor public SensorManager.DynamicSensorConnectionCallback();
+    method public void onDynamicSensorConnected(android.hardware.Sensor);
+    method public void onDynamicSensorDisconnected(android.hardware.Sensor);
+  }
+
   public final class TriggerEvent {
     field public android.hardware.Sensor sensor;
     field public long timestamp;
@@ -19016,6 +19082,288 @@
     method public static boolean isPresent();
   }
 
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public float getAzimuth(int);
+    method public int getConstellationType(int);
+    method public float getElevation(int);
+    method public int getNumSatellites();
+    method public int getPrn(int);
+    method public float getSnr(int);
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+    method public boolean usedInFix(int);
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+  }
+
+  public abstract class GnssStatusCallback {
+    ctor public GnssStatusCallback();
+    method public void onFirstFix(int);
+    method public void onSatelliteStatusChanged(android.location.GnssStatus);
+    method public void onStarted();
+    method public void onStopped();
+  }
+
+  public final class GpsClock implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getBiasInNs();
+    method public double getBiasUncertaintyInNs();
+    method public double getDriftInNsPerSec();
+    method public double getDriftUncertaintyInNsPerSec();
+    method public long getFullBiasInNs();
+    method public short getLeapSecond();
+    method public long getTimeInNs();
+    method public long getTimeOfLastHwClockDiscontinuityInNs();
+    method public double getTimeUncertaintyInNs();
+    method public byte getType();
+    method public boolean hasBiasInNs();
+    method public boolean hasBiasUncertaintyInNs();
+    method public boolean hasDriftInNsPerSec();
+    method public boolean hasDriftUncertaintyInNsPerSec();
+    method public boolean hasFullBiasInNs();
+    method public boolean hasLeapSecond();
+    method public boolean hasTimeUncertaintyInNs();
+    method public void reset();
+    method public void resetBiasInNs();
+    method public void resetBiasUncertaintyInNs();
+    method public void resetDriftInNsPerSec();
+    method public void resetDriftUncertaintyInNsPerSec();
+    method public void resetFullBiasInNs();
+    method public void resetLeapSecond();
+    method public void resetTimeUncertaintyInNs();
+    method public void set(android.location.GpsClock);
+    method public void setBiasInNs(double);
+    method public void setBiasUncertaintyInNs(double);
+    method public void setDriftInNsPerSec(double);
+    method public void setDriftUncertaintyInNsPerSec(double);
+    method public void setFullBiasInNs(long);
+    method public void setLeapSecond(short);
+    method public void setTimeInNs(long);
+    method public void setTimeOfLastHwClockDiscontinuityInNs(long);
+    method public void setTimeUncertaintyInNs(double);
+    method public void setType(byte);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
+    field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
+    field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
+    field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+  }
+
+  public static abstract class GpsClock.GpsClockType implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsMeasurement implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getAccumulatedDeltaRangeInMeters();
+    method public short getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyInMeters();
+    method public double getAzimuthInDeg();
+    method public double getAzimuthUncertaintyInDeg();
+    method public int getBitNumber();
+    method public long getCarrierCycles();
+    method public float getCarrierFrequencyInHz();
+    method public double getCarrierPhase();
+    method public double getCarrierPhaseUncertainty();
+    method public double getCn0InDbHz();
+    method public double getCodePhaseInChips();
+    method public double getCodePhaseUncertaintyInChips();
+    method public double getDopplerShiftInHz();
+    method public double getDopplerShiftUncertaintyInHz();
+    method public double getElevationInDeg();
+    method public double getElevationUncertaintyInDeg();
+    method public byte getLossOfLock();
+    method public byte getMultipathIndicator();
+    method public byte getPrn();
+    method public double getPseudorangeInMeters();
+    method public double getPseudorangeRateCarrierInMetersPerSec();
+    method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
+    method public double getPseudorangeRateInMetersPerSec();
+    method public double getPseudorangeRateUncertaintyInMetersPerSec();
+    method public double getPseudorangeUncertaintyInMeters();
+    method public long getReceivedGpsTowInNs();
+    method public long getReceivedGpsTowUncertaintyInNs();
+    method public double getSnrInDb();
+    method public short getState();
+    method public short getTimeFromLastBitInMs();
+    method public double getTimeOffsetInNs();
+    method public boolean hasAzimuthInDeg();
+    method public boolean hasAzimuthUncertaintyInDeg();
+    method public boolean hasBitNumber();
+    method public boolean hasCarrierCycles();
+    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierPhase();
+    method public boolean hasCarrierPhaseUncertainty();
+    method public boolean hasCodePhaseInChips();
+    method public boolean hasCodePhaseUncertaintyInChips();
+    method public boolean hasDopplerShiftInHz();
+    method public boolean hasDopplerShiftUncertaintyInHz();
+    method public boolean hasElevationInDeg();
+    method public boolean hasElevationUncertaintyInDeg();
+    method public boolean hasPseudorangeInMeters();
+    method public boolean hasPseudorangeUncertaintyInMeters();
+    method public boolean hasSnrInDb();
+    method public boolean hasTimeFromLastBitInMs();
+    method public boolean isPseudorangeRateCorrected();
+    method public boolean isUsedInFix();
+    method public void reset();
+    method public void resetAzimuthInDeg();
+    method public void resetAzimuthUncertaintyInDeg();
+    method public void resetBitNumber();
+    method public void resetCarrierCycles();
+    method public void resetCarrierFrequencyInHz();
+    method public void resetCarrierPhase();
+    method public void resetCarrierPhaseUncertainty();
+    method public void resetCodePhaseInChips();
+    method public void resetCodePhaseUncertaintyInChips();
+    method public void resetDopplerShiftInHz();
+    method public void resetDopplerShiftUncertaintyInHz();
+    method public void resetElevationInDeg();
+    method public void resetElevationUncertaintyInDeg();
+    method public void resetPseudorangeInMeters();
+    method public void resetPseudorangeUncertaintyInMeters();
+    method public void resetSnrInDb();
+    method public void resetTimeFromLastBitInMs();
+    method public void set(android.location.GpsMeasurement);
+    method public void setAccumulatedDeltaRangeInMeters(double);
+    method public void setAccumulatedDeltaRangeState(short);
+    method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
+    method public void setAzimuthInDeg(double);
+    method public void setAzimuthUncertaintyInDeg(double);
+    method public void setBitNumber(int);
+    method public void setCarrierCycles(long);
+    method public void setCarrierFrequencyInHz(float);
+    method public void setCarrierPhase(double);
+    method public void setCarrierPhaseUncertainty(double);
+    method public void setCn0InDbHz(double);
+    method public void setCodePhaseInChips(double);
+    method public void setCodePhaseUncertaintyInChips(double);
+    method public void setDopplerShiftInHz(double);
+    method public void setDopplerShiftUncertaintyInHz(double);
+    method public void setElevationInDeg(double);
+    method public void setElevationUncertaintyInDeg(double);
+    method public void setLossOfLock(byte);
+    method public void setMultipathIndicator(byte);
+    method public void setPrn(byte);
+    method public void setPseudorangeInMeters(double);
+    method public void setPseudorangeRateCarrierInMetersPerSec(double);
+    method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
+    method public void setPseudorangeRateInMetersPerSec(double);
+    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
+    method public void setPseudorangeUncertaintyInMeters(double);
+    method public void setReceivedGpsTowInNs(long);
+    method public void setReceivedGpsTowUncertaintyInNs(long);
+    method public void setSnrInDb(double);
+    method public void setState(short);
+    method public void setTimeFromLastBitInMs(short);
+    method public void setTimeOffsetInNs(double);
+    method public void setUsedInFix(boolean);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final short ADR_STATE_RESET = 2; // 0x2
+    field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final short ADR_STATE_VALID = 1; // 0x1
+    field public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
+    field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
+    field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
+    field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
+    field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final short STATE_BIT_SYNC = 2; // 0x2
+    field public static final short STATE_CODE_LOCK = 1; // 0x1
+    field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final short STATE_TOW_DECODED = 8; // 0x8
+    field public static final short STATE_UNKNOWN = 0; // 0x0
+  }
+
+  public static abstract class GpsMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class GpsMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsMeasurementsEvent implements android.os.Parcelable {
+    ctor public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
+    method public int describeContents();
+    method public android.location.GpsClock getClock();
+    method public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
+    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
+  }
+
+  public static abstract class GpsMeasurementsEvent.Callback {
+    ctor public GpsMeasurementsEvent.Callback();
+    method public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public static abstract class GpsMeasurementsEvent.GpsMeasurementsStatus implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsNavigationMessage implements android.os.Parcelable {
+    method public int describeContents();
+    method public byte[] getData();
+    method public short getMessageId();
+    method public byte getPrn();
+    method public short getStatus();
+    method public short getSubmessageId();
+    method public byte getType();
+    method public void reset();
+    method public void set(android.location.GpsNavigationMessage);
+    method public void setData(byte[]);
+    method public void setMessageId(short);
+    method public void setPrn(byte);
+    method public void setStatus(short);
+    method public void setSubmessageId(short);
+    method public void setType(byte);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+    field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
+    field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
+    field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
+    field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
+    field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final short STATUS_UNKNOWN = 0; // 0x0
+  }
+
+  public static abstract class GpsNavigationMessage.GpsNavigationMessageType implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsNavigationMessageEvent implements android.os.Parcelable {
+    ctor public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
+    method public int describeContents();
+    method public android.location.GpsNavigationMessage getNavigationMessage();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
+    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
+  }
+
+  public static abstract class GpsNavigationMessageEvent.Callback {
+    ctor public GpsNavigationMessageEvent.Callback();
+    method public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public static abstract class GpsNavigationMessageEvent.GpsNavigationMessageStatus implements java.lang.annotation.Annotation {
+  }
+
   public final class GpsSatellite {
     method public float getAzimuth();
     method public float getElevation();
@@ -19100,8 +19448,10 @@
   }
 
   public class LocationManager {
-    method public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
-    method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+    method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
     method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
     method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
     method public void clearTestProviderEnabled(java.lang.String);
@@ -19109,14 +19459,21 @@
     method public void clearTestProviderStatus(java.lang.String);
     method public java.util.List<java.lang.String> getAllProviders();
     method public java.lang.String getBestProvider(android.location.Criteria, boolean);
-    method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
+    method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
     method public android.location.Location getLastKnownLocation(java.lang.String);
     method public android.location.LocationProvider getProvider(java.lang.String);
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
-    method public void removeGpsStatusListener(android.location.GpsStatus.Listener);
-    method public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
+    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
+    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback, android.os.Handler);
+    method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
+    method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public void removeNmeaListener(android.location.GnssNmeaListener);
     method public void removeProximityAlert(android.app.PendingIntent);
     method public void removeTestProvider(java.lang.String);
     method public void removeUpdates(android.location.LocationListener);
@@ -19134,6 +19491,9 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+    method public void unregisterGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
+    method public void unregisterGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
     field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
     field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -19200,6 +19560,7 @@
     field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
     field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
     field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
+    field public static final int FLAG_LOW_LATENCY = 256; // 0x100
     field public static final int USAGE_ALARM = 4; // 0x4
     field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
     field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -19319,6 +19680,7 @@
     field public static final int ENCODING_DTS = 7; // 0x7
     field public static final int ENCODING_DTS_HD = 8; // 0x8
     field public static final int ENCODING_E_AC3 = 6; // 0x6
+    field public static final int ENCODING_IEC61937 = 13; // 0xd
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
     field public static final int ENCODING_PCM_8BIT = 3; // 0x3
@@ -19514,6 +19876,7 @@
     method public android.media.AudioDeviceInfo getRoutedDevice();
     method public int getSampleRate();
     method public int getState();
+    method public int getTimestamp(android.media.AudioTimestamp, int);
     method public int read(byte[], int, int);
     method public int read(byte[], int, int, int);
     method public int read(short[], int, int);
@@ -19563,8 +19926,11 @@
 
   public class AudioRecordConfiguration implements android.os.Parcelable {
     method public int describeContents();
-    method public int getAudioSessionId();
+    method public android.media.AudioDeviceInfo getAudioDevice();
+    method public int getClientAudioSessionId();
     method public int getClientAudioSource();
+    method public android.media.AudioFormat getClientFormat();
+    method public android.media.AudioFormat getFormat();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
   }
@@ -19582,6 +19948,8 @@
 
   public final class AudioTimestamp {
     ctor public AudioTimestamp();
+    field public static final int TIMEBASE_BOOTTIME = 1; // 0x1
+    field public static final int TIMEBASE_MONOTONIC = 0; // 0x0
     field public long framePosition;
     field public long nanoTime;
   }
@@ -19596,6 +19964,7 @@
     method public void flush();
     method public int getAudioFormat();
     method public int getAudioSessionId();
+    method public int getBufferCapacityInFrames();
     method public int getBufferSizeInFrames();
     method public int getChannelConfiguration();
     method public int getChannelCount();
@@ -19617,6 +19986,7 @@
     method public int getState();
     method public int getStreamType();
     method public boolean getTimestamp(android.media.AudioTimestamp);
+    method public int getUnderrunCount();
     method public void pause() throws java.lang.IllegalStateException;
     method public void play() throws java.lang.IllegalStateException;
     method public void release();
@@ -19624,6 +19994,7 @@
     method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
     method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public int setAuxEffectSendLevel(float);
+    method public int setBufferSizeInFrames(int);
     method public int setLoopPoints(int, int, int);
     method public int setNotificationMarkerPosition(int);
     method public int setPlaybackHeadPosition(int);
@@ -19735,6 +20106,16 @@
     ctor public DeniedByServerException(java.lang.String);
   }
 
+  public abstract class DrmInitData {
+    ctor public DrmInitData();
+    method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
+  }
+
+  public static final class DrmInitData.SchemeInitData {
+    field public final byte[] data;
+    field public final java.lang.String mimeType;
+  }
+
   public class ExifInterface {
     ctor public ExifInterface(java.lang.String) throws java.io.IOException;
     method public double getAltitude(double);
@@ -20082,6 +20463,7 @@
     field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
     field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+    field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
     field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
     field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
     field public int[] colorFormats;
@@ -20124,6 +20506,21 @@
     field public static final int AVCProfileHigh422 = 32; // 0x20
     field public static final int AVCProfileHigh444 = 64; // 0x40
     field public static final int AVCProfileMain = 2; // 0x2
+    field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
+    field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
+    field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
+    field public static final int DolbyVisionLevelHd24 = 1; // 0x1
+    field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+    field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
+    field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
+    field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
+    field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
+    field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
+    field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
+    field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
+    field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
+    field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
+    field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
     field public static final int H263Level10 = 1; // 0x1
     field public static final int H263Level20 = 2; // 0x2
     field public static final int H263Level30 = 4; // 0x4
@@ -20208,6 +20605,24 @@
     field public static final int VP8Level_Version2 = 4; // 0x4
     field public static final int VP8Level_Version3 = 8; // 0x8
     field public static final int VP8ProfileMain = 1; // 0x1
+    field public static final int VP9Level1 = 0; // 0x0
+    field public static final int VP9Level11 = 1; // 0x1
+    field public static final int VP9Level2 = 2; // 0x2
+    field public static final int VP9Level21 = 4; // 0x4
+    field public static final int VP9Level3 = 8; // 0x8
+    field public static final int VP9Level31 = 16; // 0x10
+    field public static final int VP9Level4 = 32; // 0x20
+    field public static final int VP9Level41 = 64; // 0x40
+    field public static final int VP9Level5 = 128; // 0x80
+    field public static final int VP9Level51 = 256; // 0x100
+    field public static final int VP9Level52 = 512; // 0x200
+    field public static final int VP9Level6 = 1024; // 0x400
+    field public static final int VP9Level61 = 2048; // 0x800
+    field public static final int VP9Level62 = 4096; // 0x1000
+    field public static final int VP9Profile0 = 0; // 0x0
+    field public static final int VP9Profile1 = 1; // 0x1
+    field public static final int VP9Profile2 = 2; // 0x2
+    field public static final int VP9Profile3 = 3; // 0x3
     field public int level;
     field public int profile;
   }
@@ -20391,6 +20806,7 @@
     ctor public MediaExtractor();
     method public boolean advance();
     method public long getCachedDuration();
+    method public android.media.DrmInitData getDrmInitData();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -20435,6 +20851,16 @@
     method public final void setInteger(java.lang.String, int);
     method public final void setLong(java.lang.String, long);
     method public final void setString(java.lang.String, java.lang.String);
+    field public static final int COLOR_RANGE_FULL = 1; // 0x1
+    field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
+    field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
+    field public static final int COLOR_STANDARD_BT601_NTSC = 4; // 0x4
+    field public static final int COLOR_STANDARD_BT601_PAL = 2; // 0x2
+    field public static final int COLOR_STANDARD_BT709 = 1; // 0x1
+    field public static final int COLOR_TRANSFER_HLG = 7; // 0x7
+    field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
+    field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
+    field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
     field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
     field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
     field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression";
@@ -20450,11 +20876,15 @@
     field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
     field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
     field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
+    field public static final java.lang.String KEY_COLOR_RANGE = "color-range";
+    field public static final java.lang.String KEY_COLOR_STANDARD = "color-standard";
+    field public static final java.lang.String KEY_COLOR_TRANSFER = "color-transfer";
     field public static final java.lang.String KEY_COMPLEXITY = "complexity";
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
     field public static final java.lang.String KEY_HEIGHT = "height";
+    field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
     field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect";
     field public static final java.lang.String KEY_IS_DEFAULT = "is-default";
@@ -20776,9 +21206,11 @@
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
     method public android.view.Surface getSurface();
+    method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void release();
     method public void reset();
+    method public void resume() throws java.lang.IllegalStateException;
     method public void setAudioChannels(int);
     method public void setAudioEncoder(int) throws java.lang.IllegalStateException;
     method public void setAudioEncodingBitRate(int);
@@ -22072,6 +22504,7 @@
     method public void setRatingType(int);
     method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
@@ -22150,6 +22583,7 @@
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
+    field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
@@ -22466,7 +22900,7 @@
     method public void onInputAdded(java.lang.String);
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
-    method public void onTvInputInfoChanged(java.lang.String, android.media.tv.TvInputInfo);
+    method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
   public abstract class TvInputService extends android.app.Service {
@@ -22474,7 +22908,7 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public android.media.tv.TvInputService.RecordingSession onCreateRecordingSession(java.lang.String);
     method public abstract android.media.tv.TvInputService.Session onCreateSession(java.lang.String);
-    method public final void setTvInputInfo(java.lang.String, android.media.tv.TvInputInfo);
+    method public static final void setTvInputInfo(android.content.Context, android.media.tv.TvInputInfo);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
     field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
   }
@@ -22737,6 +23171,7 @@
     field public static final int OPERATION_GET_OBJECT_PROP_VALUE = 38915; // 0x9803
     field public static final int OPERATION_GET_OBJECT_REFERENCES = 38928; // 0x9810
     field public static final int OPERATION_GET_PARTIAL_OBJECT = 4123; // 0x101b
+    field public static final int OPERATION_GET_PARTIAL_OBJECT_64 = 38337; // 0x95c1
     field public static final int OPERATION_GET_STORAGE_INFO = 4101; // 0x1005
     field public static final int OPERATION_GET_STORAGE_I_DS = 4100; // 0x1004
     field public static final int OPERATION_GET_THUMB = 4106; // 0x100a
@@ -22774,6 +23209,7 @@
     method public android.mtp.MtpObjectInfo getObjectInfo(int);
     method public long getParent(int);
     method public long getPartialObject(int, long, long, byte[]) throws java.io.IOException;
+    method public long getPartialObject64(int, long, long, byte[]) throws java.io.IOException;
     method public long getStorageId(int);
     method public int[] getStorageIds();
     method public android.mtp.MtpStorageInfo getStorageInfo(int);
@@ -22782,7 +23218,7 @@
     method public boolean importFile(int, android.os.ParcelFileDescriptor);
     method public boolean open(android.hardware.usb.UsbDeviceConnection);
     method public android.mtp.MtpEvent readEvent(android.os.CancellationSignal);
-    method public boolean sendObject(int, int, android.os.ParcelFileDescriptor);
+    method public boolean sendObject(int, long, android.os.ParcelFileDescriptor);
     method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
   }
 
@@ -22813,23 +23249,31 @@
     method public final int getAssociationDesc();
     method public final int getAssociationType();
     method public final int getCompressedSize();
+    method public final long getCompressedSizeLong();
     method public final long getDateCreated();
     method public final long getDateModified();
     method public final int getFormat();
     method public final int getImagePixDepth();
+    method public final long getImagePixDepthLong();
     method public final int getImagePixHeight();
+    method public final long getImagePixHeightLong();
     method public final int getImagePixWidth();
+    method public final long getImagePixWidthLong();
     method public final java.lang.String getKeywords();
     method public final java.lang.String getName();
     method public final int getObjectHandle();
     method public final int getParent();
     method public final int getProtectionStatus();
     method public final int getSequenceNumber();
+    method public final long getSequenceNumberLong();
     method public final int getStorageId();
     method public final int getThumbCompressedSize();
+    method public final long getThumbCompressedSizeLong();
     method public final int getThumbFormat();
     method public final int getThumbPixHeight();
+    method public final long getThumbPixHeightLong();
     method public final int getThumbPixWidth();
+    method public final long getThumbPixWidthLong();
   }
 
   public static class MtpObjectInfo.Builder {
@@ -22838,24 +23282,24 @@
     method public android.mtp.MtpObjectInfo build();
     method public android.mtp.MtpObjectInfo.Builder setAssociationDesc(int);
     method public android.mtp.MtpObjectInfo.Builder setAssociationType(int);
-    method public android.mtp.MtpObjectInfo.Builder setCompressedSize(int);
+    method public android.mtp.MtpObjectInfo.Builder setCompressedSize(long);
     method public android.mtp.MtpObjectInfo.Builder setDateCreated(long);
     method public android.mtp.MtpObjectInfo.Builder setDateModified(long);
     method public android.mtp.MtpObjectInfo.Builder setFormat(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(int);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(long);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(long);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(long);
     method public android.mtp.MtpObjectInfo.Builder setKeywords(java.lang.String);
     method public android.mtp.MtpObjectInfo.Builder setName(java.lang.String);
     method public android.mtp.MtpObjectInfo.Builder setObjectHandle(int);
     method public android.mtp.MtpObjectInfo.Builder setParent(int);
     method public android.mtp.MtpObjectInfo.Builder setProtectionStatus(int);
-    method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(int);
+    method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(long);
     method public android.mtp.MtpObjectInfo.Builder setStorageId(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(int);
+    method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(long);
     method public android.mtp.MtpObjectInfo.Builder setThumbFormat(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(int);
+    method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(long);
+    method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(long);
   }
 
   public final class MtpStorageInfo {
@@ -27892,6 +28336,14 @@
     method public final synchronized android.os.CountDownTimer start();
   }
 
+  public final class CpuUsageInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getActive();
+    method public long getTotal();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.CpuUsageInfo> CREATOR;
+  }
+
   public class DeadObjectException extends android.os.RemoteException {
     ctor public DeadObjectException();
     ctor public DeadObjectException(java.lang.String);
@@ -28094,6 +28546,10 @@
     field public static final int OPEN = 32; // 0x20
   }
 
+  public class FileUriExposedException extends java.lang.RuntimeException {
+    ctor public FileUriExposedException(java.lang.String);
+  }
+
   public class Handler {
     ctor public Handler();
     ctor public Handler(android.os.Handler.Callback);
@@ -28144,6 +28600,18 @@
     method public boolean quitSafely();
   }
 
+  public class HardwarePropertiesManager {
+    method public android.os.CpuUsageInfo[] getCpuUsages();
+    method public float[] getDeviceTemperatures(int);
+    method public float[] getFanSpeeds();
+    field public static final int DEVICE_TEMPERATURE_BATTERY = 2; // 0x2
+    field public static final int DEVICE_TEMPERATURE_CPU = 0; // 0x0
+    field public static final int DEVICE_TEMPERATURE_GPU = 1; // 0x1
+  }
+
+  public static abstract class HardwarePropertiesManager.DeviceTemperatureType implements java.lang.annotation.Annotation {
+  }
+
   public abstract interface IBinder {
     method public abstract void dump(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
     method public abstract void dumpAsync(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
@@ -28513,6 +28981,7 @@
     field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+    field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
   }
 
   public final class PowerManager.WakeLock {
@@ -28672,6 +29141,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
+    method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox();
     method public android.os.StrictMode.VmPolicy.Builder penaltyLog();
     method public android.os.StrictMode.VmPolicy.Builder setClassInstanceLimit(java.lang.Class, int);
@@ -28778,6 +29248,8 @@
     field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
     field public static final java.lang.String ENSURE_VERIFY_APPS = "ensure_verify_apps";
     field public static final java.lang.String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
+    field public static final int USER_CREATION_FAILED_NOT_PERMITTED = 1; // 0x1
+    field public static final int USER_CREATION_FAILED_NO_MORE_USERS = 2; // 0x2
   }
 
   public abstract class Vibrator {
@@ -29135,6 +29607,8 @@
     method public static void setDefaultValues(android.content.Context, java.lang.String, int, int, boolean);
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
+    method public void setStorageDefault();
+    method public void setStorageDeviceEncrypted();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -31129,7 +31603,9 @@
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
     method public static java.lang.String getTreeDocumentId(android.net.Uri);
     method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
+    method public static boolean isTreeUri(android.net.Uri);
     method public static android.net.Uri moveDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri, android.net.Uri);
+    method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
     method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String);
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
@@ -31155,6 +31631,7 @@
     field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
     field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
+    field public static final int FLAG_SUPPORTS_REMOVE = 2048; // 0x800
     field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -31202,6 +31679,7 @@
     method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+    method public boolean removeDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String renameDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final void revokeDocumentPermission(java.lang.String);
     method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
@@ -31581,6 +32059,7 @@
     field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
     field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
+    field public static final java.lang.String ACTION_KEYBOARD_LAYOUT_SETTINGS = "android.settings.KEYBOARD_LAYOUT_SETTINGS";
     field public static final java.lang.String ACTION_LOCALE_SETTINGS = "android.settings.LOCALE_SETTINGS";
     field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
@@ -32242,6 +32721,7 @@
   public class VoicemailContract {
     field public static final java.lang.String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
     field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+    field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
     field public static final java.lang.String AUTHORITY = "com.android.voicemail";
     field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
     field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
@@ -32256,8 +32736,13 @@
     field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+    field public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3; // 0x3
+    field public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4; // 0x4
     field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+    field public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2; // 0x2
     field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6; // 0x6
+    field public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5; // 0x5
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
     field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
@@ -32355,6 +32840,7 @@
     method public void copyTo(short[]);
     method public void copyTo(int[]);
     method public void copyTo(float[]);
+    method public static android.renderscript.Allocation[] createAllocations(android.renderscript.RenderScript, android.renderscript.Type, int, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
     method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -32370,9 +32856,12 @@
     method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int);
     method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type);
     method public void generateMipmaps();
+    method public java.nio.ByteBuffer getByteBuffer();
     method public int getBytesSize();
     method public android.renderscript.Element getElement();
+    method public long getStride();
     method public android.view.Surface getSurface();
+    method public long getTimeStamp();
     method public android.renderscript.Type getType();
     method public int getUsage();
     method public void ioReceive();
@@ -33897,6 +34386,7 @@
     field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
     field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
     field public static final int REASON_TOPIC_BANNED = 14; // 0xe
     field public static final int REASON_USER_STOPPED = 6; // 0x6
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -35312,6 +35802,30 @@
     field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
   }
 
+  public abstract class CallScreeningService extends android.app.Service {
+    ctor public CallScreeningService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onScreenCall(android.telecom.Call.Details);
+    method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+  }
+
+  public static class CallScreeningService.CallResponse {
+    method public boolean getDisallowCall();
+    method public boolean getRejectCall();
+    method public boolean getSkipCallLog();
+    method public boolean getSkipNotification();
+  }
+
+  public static class CallScreeningService.CallResponse.Builder {
+    ctor public CallScreeningService.CallResponse.Builder();
+    method public android.telecom.CallScreeningService.CallResponse build();
+    method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+  }
+
   public abstract class Conference extends android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
@@ -35551,6 +36065,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -35811,6 +36326,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
     field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
@@ -35962,6 +36478,7 @@
     field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
     field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
     field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+    field public static final java.lang.String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
     field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
@@ -35979,6 +36496,8 @@
 
   public final class CellIdentityGsm implements android.os.Parcelable {
     method public int describeContents();
+    method public int getArfcn();
+    method public int getBsic();
     method public int getCid();
     method public int getLac();
     method public int getMcc();
@@ -35991,6 +36510,7 @@
   public final class CellIdentityLte implements android.os.Parcelable {
     method public int describeContents();
     method public int getCi();
+    method public int getEarfcn();
     method public int getMcc();
     method public int getMnc();
     method public int getPci();
@@ -36006,6 +36526,7 @@
     method public int getMcc();
     method public int getMnc();
     method public int getPsc();
+    method public int getUarfcn();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityWcdma> CREATOR;
   }
@@ -36683,7 +37204,7 @@
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
     ctor public deprecated ActivityInstrumentationTestCase2(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase2(java.lang.Class<T>);
     method public T getActivity();
@@ -36691,14 +37212,14 @@
     method public void setActivityIntent(android.content.Intent);
   }
 
-  public abstract class ActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class ActivityTestCase extends android.test.InstrumentationTestCase {
     ctor public ActivityTestCase();
     method protected android.app.Activity getActivity();
     method protected void scrubClass(java.lang.Class<?>) throws java.lang.IllegalAccessException;
     method protected void setActivity(android.app.Activity);
   }
 
-  public abstract class ActivityUnitTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityUnitTestCase extends android.test.ActivityTestCase {
     ctor public ActivityUnitTestCase(java.lang.Class<T>);
     method public T getActivity();
     method public int getFinishedActivityRequest();
@@ -36711,7 +37232,7 @@
     method protected T startActivity(android.content.Intent, android.os.Bundle, java.lang.Object);
   }
 
-  public class AndroidTestCase extends junit.framework.TestCase {
+  public deprecated class AndroidTestCase extends junit.framework.TestCase {
     ctor public AndroidTestCase();
     method public void assertActivityRequiresPermission(java.lang.String, java.lang.String, java.lang.String);
     method public void assertReadingContentUriRequiresPermission(android.net.Uri, java.lang.String);
@@ -36723,7 +37244,7 @@
     field protected android.content.Context mContext;
   }
 
-  public class AndroidTestRunner extends junit.runner.BaseTestRunner {
+  public deprecated class AndroidTestRunner extends junit.runner.BaseTestRunner {
     ctor public AndroidTestRunner();
     method public void addTestListener(junit.framework.TestListener);
     method public void clearTestListeners();
@@ -36744,7 +37265,7 @@
     method public void testStarted(java.lang.String);
   }
 
-  public abstract class ApplicationTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ApplicationTestCase extends android.test.AndroidTestCase {
     ctor public ApplicationTestCase(java.lang.Class<T>);
     method protected final void createApplication();
     method public T getApplication();
@@ -36762,10 +37283,10 @@
     ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String);
   }
 
-  public abstract class FlakyTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class FlakyTest implements java.lang.annotation.Annotation {
   }
 
-  public class InstrumentationTestCase extends junit.framework.TestCase {
+  public deprecated class InstrumentationTestCase extends junit.framework.TestCase {
     ctor public InstrumentationTestCase();
     method public android.app.Instrumentation getInstrumentation();
     method public deprecated void injectInsrumentation(android.app.Instrumentation);
@@ -36778,7 +37299,7 @@
     method public void sendRepeatedKeys(int...);
   }
 
-  public class InstrumentationTestRunner extends android.app.Instrumentation implements android.test.TestSuiteProvider {
+  public deprecated class InstrumentationTestRunner extends android.app.Instrumentation implements android.test.TestSuiteProvider {
     ctor public InstrumentationTestRunner();
     method public junit.framework.TestSuite getAllTests();
     method protected android.test.AndroidTestRunner getAndroidTestRunner();
@@ -36797,14 +37318,14 @@
     field public static final int REPORT_VALUE_RESULT_START = 1; // 0x1
   }
 
-  public class InstrumentationTestSuite extends junit.framework.TestSuite {
+  public deprecated class InstrumentationTestSuite extends junit.framework.TestSuite {
     ctor public InstrumentationTestSuite(android.app.Instrumentation);
     ctor public InstrumentationTestSuite(java.lang.String, android.app.Instrumentation);
     ctor public InstrumentationTestSuite(java.lang.Class, android.app.Instrumentation);
     method public void addTestSuite(java.lang.Class);
   }
 
-  public class IsolatedContext extends android.content.ContextWrapper {
+  public deprecated class IsolatedContext extends android.content.ContextWrapper {
     ctor public IsolatedContext(android.content.ContentResolver, android.content.Context);
     method public java.util.List<android.content.Intent> getAndClearBroadcastIntents();
   }
@@ -36814,7 +37335,7 @@
     method public T getLoaderResultSynchronously(android.content.Loader<T>);
   }
 
-  public final class MoreAsserts {
+  public final deprecated class MoreAsserts {
     method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Object);
     method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Class<?>);
     method public static java.util.regex.MatchResult assertContainsRegex(java.lang.String, java.lang.String, java.lang.String);
@@ -36853,7 +37374,7 @@
     method public static void checkEqualsAndHashCodeMethods(java.lang.Object, java.lang.Object, boolean);
   }
 
-  public abstract interface PerformanceTestCase {
+  public abstract deprecated interface PerformanceTestCase {
     method public abstract boolean isPerformanceOnly();
     method public abstract int startPerformance(android.test.PerformanceTestCase.Intermediates);
   }
@@ -36882,7 +37403,7 @@
     method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public class RenamingDelegatingContext extends android.content.ContextWrapper {
+  public deprecated class RenamingDelegatingContext extends android.content.ContextWrapper {
     ctor public RenamingDelegatingContext(android.content.Context, java.lang.String);
     ctor public RenamingDelegatingContext(android.content.Context, android.content.Context, java.lang.String);
     method public java.lang.String getDatabasePrefix();
@@ -36891,7 +37412,7 @@
     method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract class ServiceTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ServiceTestCase extends android.test.AndroidTestCase {
     ctor public ServiceTestCase(java.lang.Class<T>);
     method protected android.os.IBinder bindService(android.content.Intent);
     method public android.app.Application getApplication();
@@ -36904,23 +37425,23 @@
     method public void testServiceTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
     ctor public SingleLaunchActivityTestCase(java.lang.String, java.lang.Class<T>);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public class SyncBaseInstrumentation extends android.test.InstrumentationTestCase {
+  public deprecated class SyncBaseInstrumentation extends android.test.InstrumentationTestCase {
     ctor public SyncBaseInstrumentation();
     method protected void cancelSyncsandDisableAutoSync();
     method protected void syncProvider(android.net.Uri, java.lang.String, java.lang.String) throws java.lang.Exception;
   }
 
-  public abstract interface TestSuiteProvider {
+  public abstract deprecated interface TestSuiteProvider {
     method public abstract junit.framework.TestSuite getTestSuite();
   }
 
-  public class TouchUtils {
+  public deprecated class TouchUtils {
     ctor public TouchUtils();
     method public static void clickView(android.test.InstrumentationTestCase, android.view.View);
     method public static deprecated void drag(android.test.ActivityInstrumentationTestCase, float, float, float, float, int);
@@ -36955,10 +37476,10 @@
     method public static void touchAndCancelView(android.test.InstrumentationTestCase, android.view.View);
   }
 
-  public abstract class UiThreadTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class UiThreadTest implements java.lang.annotation.Annotation {
   }
 
-  public class ViewAsserts {
+  public deprecated class ViewAsserts {
     method public static void assertBaselineAligned(android.view.View, android.view.View);
     method public static void assertBottomAligned(android.view.View, android.view.View);
     method public static void assertBottomAligned(android.view.View, android.view.View, int);
@@ -36983,11 +37504,11 @@
 
 package android.test.mock {
 
-  public class MockApplication extends android.app.Application {
+  public deprecated class MockApplication extends android.app.Application {
     ctor public MockApplication();
   }
 
-  public class MockContentProvider extends android.content.ContentProvider {
+  public deprecated class MockContentProvider extends android.content.ContentProvider {
     ctor protected MockContentProvider();
     ctor public MockContentProvider(android.content.Context);
     ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
@@ -36999,13 +37520,13 @@
     method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
-  public class MockContentResolver extends android.content.ContentResolver {
+  public deprecated class MockContentResolver extends android.content.ContentResolver {
     ctor public MockContentResolver();
     ctor public MockContentResolver(android.content.Context);
     method public void addProvider(java.lang.String, android.content.ContentProvider);
   }
 
-  public class MockContext extends android.content.Context {
+  public deprecated class MockContext extends android.content.Context {
     ctor public MockContext();
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(java.lang.String);
@@ -37105,7 +37626,7 @@
     method public void unregisterReceiver(android.content.BroadcastReceiver);
   }
 
-  public class MockCursor implements android.database.Cursor {
+  public deprecated class MockCursor implements android.database.Cursor {
     ctor public MockCursor();
     method public void close();
     method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
@@ -37150,13 +37671,13 @@
     method public void unregisterDataSetObserver(android.database.DataSetObserver);
   }
 
-  public class MockDialogInterface implements android.content.DialogInterface {
+  public deprecated class MockDialogInterface implements android.content.DialogInterface {
     ctor public MockDialogInterface();
     method public void cancel();
     method public void dismiss();
   }
 
-  public class MockPackageManager extends android.content.pm.PackageManager {
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
     ctor public MockPackageManager();
     method public void addPackageToPreferred(java.lang.String);
     method public boolean addPermission(android.content.pm.PermissionInfo);
@@ -37243,7 +37764,7 @@
     method public void verifyPendingInstall(int, int);
   }
 
-  public class MockResources extends android.content.res.Resources {
+  public deprecated class MockResources extends android.content.res.Resources {
     ctor public MockResources();
   }
 
@@ -37284,19 +37805,19 @@
 
 package android.test.suitebuilder.annotation {
 
-  public abstract class LargeTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class LargeTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class MediumTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class MediumTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class SmallTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class SmallTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class Smoke implements java.lang.annotation.Annotation {
+  public abstract deprecated class Smoke implements java.lang.annotation.Annotation {
   }
 
-  public abstract class Suppress implements java.lang.annotation.Annotation {
+  public abstract deprecated class Suppress implements java.lang.annotation.Annotation {
   }
 
 }
@@ -48309,7 +48830,6 @@
     method public boolean setReadable(boolean);
     method public boolean setWritable(boolean, boolean);
     method public boolean setWritable(boolean);
-    method public java.nio.file.Path toPath();
     method public java.net.URI toURI();
     method public deprecated java.net.URL toURL() throws java.net.MalformedURLException;
     field public static final java.lang.String pathSeparator;
@@ -49862,6 +50382,9 @@
     field public static final java.lang.Class<java.lang.Float> TYPE;
   }
 
+  public abstract class FunctionalInterface implements java.lang.annotation.Annotation {
+  }
+
   public class IllegalAccessError extends java.lang.IncompatibleClassChangeError {
     ctor public IllegalAccessError();
     ctor public IllegalAccessError(java.lang.String);
@@ -50793,6 +51316,9 @@
   public abstract class Inherited implements java.lang.annotation.Annotation {
   }
 
+  public abstract class Repeatable implements java.lang.annotation.Annotation {
+  }
+
   public abstract class Retention implements java.lang.annotation.Annotation {
   }
 
@@ -52405,25 +52931,6 @@
     ctor public AsynchronousCloseException();
   }
 
-  public abstract class AsynchronousFileChannel implements java.nio.channels.AsynchronousChannel {
-    ctor protected AsynchronousFileChannel();
-    method public abstract void force(boolean) throws java.io.IOException;
-    method public abstract void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public final void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public abstract java.util.concurrent.Future<java.nio.channels.FileLock> lock(long, long, boolean);
-    method public final java.util.concurrent.Future<java.nio.channels.FileLock> lock();
-    method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer, long);
-    method public abstract long size() throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousFileChannel truncate(long) throws java.io.IOException;
-    method public abstract java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException;
-    method public final java.nio.channels.FileLock tryLock() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer, long);
-  }
-
   public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
     method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
@@ -52532,8 +53039,6 @@
     method public abstract java.nio.channels.FileLock lock(long, long, boolean) throws java.io.IOException;
     method public final java.nio.channels.FileLock lock() throws java.io.IOException;
     method public abstract java.nio.MappedByteBuffer map(java.nio.channels.FileChannel.MapMode, long, long) throws java.io.IOException;
-    method public static java.nio.channels.FileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.FileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
     method public abstract long position() throws java.io.IOException;
     method public abstract java.nio.channels.FileChannel position(long) throws java.io.IOException;
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
@@ -52560,7 +53065,6 @@
 
   public abstract class FileLock implements java.lang.AutoCloseable {
     ctor protected FileLock(java.nio.channels.FileChannel, long, long, boolean);
-    ctor protected FileLock(java.nio.channels.AsynchronousFileChannel, long, long, boolean);
     method public java.nio.channels.Channel acquiredBy();
     method public final java.nio.channels.FileChannel channel();
     method public final void close() throws java.io.IOException;
@@ -53010,592 +53514,6 @@
 
 }
 
-package java.nio.file {
-
-  public class AccessDeniedException extends java.nio.file.FileSystemException {
-    ctor public AccessDeniedException(java.lang.String);
-    ctor public AccessDeniedException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public final class AccessMode extends java.lang.Enum {
-    method public static java.nio.file.AccessMode valueOf(java.lang.String);
-    method public static final java.nio.file.AccessMode[] values();
-    enum_constant public static final java.nio.file.AccessMode EXECUTE;
-    enum_constant public static final java.nio.file.AccessMode READ;
-    enum_constant public static final java.nio.file.AccessMode WRITE;
-  }
-
-  public class AtomicMoveNotSupportedException extends java.nio.file.FileSystemException {
-    ctor public AtomicMoveNotSupportedException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public class ClosedDirectoryStreamException extends java.lang.IllegalStateException {
-    ctor public ClosedDirectoryStreamException();
-  }
-
-  public class ClosedFileSystemException extends java.lang.IllegalStateException {
-    ctor public ClosedFileSystemException();
-  }
-
-  public class ClosedWatchServiceException extends java.lang.IllegalStateException {
-    ctor public ClosedWatchServiceException();
-  }
-
-  public abstract interface CopyOption {
-  }
-
-  public final class DirectoryIteratorException extends java.util.ConcurrentModificationException {
-    ctor public DirectoryIteratorException(java.io.IOException);
-  }
-
-  public class DirectoryNotEmptyException extends java.nio.file.FileSystemException {
-    ctor public DirectoryNotEmptyException(java.lang.String);
-  }
-
-  public abstract interface DirectoryStream implements java.io.Closeable java.lang.Iterable {
-    method public abstract java.util.Iterator<T> iterator();
-  }
-
-  public static abstract interface DirectoryStream.Filter {
-    method public abstract boolean accept(T) throws java.io.IOException;
-  }
-
-  public class FileAlreadyExistsException extends java.nio.file.FileSystemException {
-    ctor public FileAlreadyExistsException(java.lang.String);
-    ctor public FileAlreadyExistsException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public abstract class FileStore {
-    ctor protected FileStore();
-    method public abstract java.lang.Object getAttribute(java.lang.String) throws java.io.IOException;
-    method public abstract V getFileStoreAttributeView(java.lang.Class<V>);
-    method public abstract long getTotalSpace() throws java.io.IOException;
-    method public abstract long getUnallocatedSpace() throws java.io.IOException;
-    method public abstract long getUsableSpace() throws java.io.IOException;
-    method public abstract boolean isReadOnly();
-    method public abstract java.lang.String name();
-    method public abstract boolean supportsFileAttributeView(java.lang.Class<? extends java.nio.file.attribute.FileAttributeView>);
-    method public abstract boolean supportsFileAttributeView(java.lang.String);
-    method public abstract java.lang.String type();
-  }
-
-  public abstract class FileSystem implements java.io.Closeable {
-    ctor protected FileSystem();
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.lang.Iterable<java.nio.file.FileStore> getFileStores();
-    method public abstract java.nio.file.Path getPath(java.lang.String, java.lang.String...);
-    method public abstract java.nio.file.PathMatcher getPathMatcher(java.lang.String);
-    method public abstract java.lang.Iterable<java.nio.file.Path> getRootDirectories();
-    method public abstract java.lang.String getSeparator();
-    method public abstract java.nio.file.attribute.UserPrincipalLookupService getUserPrincipalLookupService();
-    method public abstract boolean isOpen();
-    method public abstract boolean isReadOnly();
-    method public abstract java.nio.file.WatchService newWatchService() throws java.io.IOException;
-    method public abstract java.nio.file.spi.FileSystemProvider provider();
-    method public abstract java.util.Set<java.lang.String> supportedFileAttributeViews();
-  }
-
-  public class FileSystemAlreadyExistsException extends java.lang.RuntimeException {
-    ctor public FileSystemAlreadyExistsException();
-    ctor public FileSystemAlreadyExistsException(java.lang.String);
-  }
-
-  public class FileSystemException extends java.io.IOException {
-    ctor public FileSystemException(java.lang.String);
-    ctor public FileSystemException(java.lang.String, java.lang.String, java.lang.String);
-    method public java.lang.String getFile();
-    method public java.lang.String getOtherFile();
-    method public java.lang.String getReason();
-  }
-
-  public class FileSystemLoopException extends java.nio.file.FileSystemException {
-    ctor public FileSystemLoopException(java.lang.String);
-  }
-
-  public class FileSystemNotFoundException extends java.lang.RuntimeException {
-    ctor public FileSystemNotFoundException();
-    ctor public FileSystemNotFoundException(java.lang.String);
-  }
-
-  public final class FileSystems {
-    method public static java.nio.file.FileSystem getDefault();
-    method public static java.nio.file.FileSystem getFileSystem(java.net.URI);
-    method public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>, java.lang.ClassLoader) throws java.io.IOException;
-    method public static java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.lang.ClassLoader) throws java.io.IOException;
-  }
-
-  public final class FileVisitOption extends java.lang.Enum {
-    method public static java.nio.file.FileVisitOption valueOf(java.lang.String);
-    method public static final java.nio.file.FileVisitOption[] values();
-    enum_constant public static final java.nio.file.FileVisitOption FOLLOW_LINKS;
-  }
-
-  public final class FileVisitResult extends java.lang.Enum {
-    method public static java.nio.file.FileVisitResult valueOf(java.lang.String);
-    method public static final java.nio.file.FileVisitResult[] values();
-    enum_constant public static final java.nio.file.FileVisitResult CONTINUE;
-    enum_constant public static final java.nio.file.FileVisitResult SKIP_SIBLINGS;
-    enum_constant public static final java.nio.file.FileVisitResult SKIP_SUBTREE;
-    enum_constant public static final java.nio.file.FileVisitResult TERMINATE;
-  }
-
-  public abstract interface FileVisitor {
-    method public abstract java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult visitFile(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult visitFileFailed(T, java.io.IOException) throws java.io.IOException;
-  }
-
-  public final class Files {
-    method public static java.nio.file.Path copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static long copy(java.io.InputStream, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static long copy(java.nio.file.Path, java.io.OutputStream) throws java.io.IOException;
-    method public static java.nio.file.Path createDirectories(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createFile(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createLink(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempDirectory(java.nio.file.Path, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempDirectory(java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempFile(java.nio.file.Path, java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempFile(java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static void delete(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean exists(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public static java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.attribute.FileTime getLastModifiedTime(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.attribute.UserPrincipal getOwner(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.util.Set<java.nio.file.attribute.PosixFilePermission> getPosixFilePermissions(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static boolean isDirectory(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static boolean isExecutable(java.nio.file.Path);
-    method public static boolean isHidden(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean isReadable(java.nio.file.Path);
-    method public static boolean isRegularFile(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static boolean isSameFile(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public static boolean isSymbolicLink(java.nio.file.Path);
-    method public static boolean isWritable(java.nio.file.Path);
-    method public static java.nio.file.Path move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static java.io.BufferedReader newBufferedReader(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
-    method public static java.io.BufferedWriter newBufferedWriter(java.nio.file.Path, java.nio.charset.Charset, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.lang.String) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static boolean notExists(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static java.lang.String probeContentType(java.nio.file.Path) throws java.io.IOException;
-    method public static byte[] readAllBytes(java.nio.file.Path) throws java.io.IOException;
-    method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
-    method public static A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.Path setLastModifiedTime(java.nio.file.Path, java.nio.file.attribute.FileTime) throws java.io.IOException;
-    method public static java.nio.file.Path setOwner(java.nio.file.Path, java.nio.file.attribute.UserPrincipal) throws java.io.IOException;
-    method public static java.nio.file.Path setPosixFilePermissions(java.nio.file.Path, java.util.Set<java.nio.file.attribute.PosixFilePermission>) throws java.io.IOException;
-    method public static long size(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path walkFileTree(java.nio.file.Path, java.util.Set<java.nio.file.FileVisitOption>, int, java.nio.file.FileVisitor<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.nio.file.Path walkFileTree(java.nio.file.Path, java.nio.file.FileVisitor<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.nio.file.Path write(java.nio.file.Path, byte[], java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.file.Path write(java.nio.file.Path, java.lang.Iterable<? extends java.lang.CharSequence>, java.nio.charset.Charset, java.nio.file.OpenOption...) throws java.io.IOException;
-  }
-
-  public class InvalidPathException extends java.lang.IllegalArgumentException {
-    ctor public InvalidPathException(java.lang.String, java.lang.String, int);
-    ctor public InvalidPathException(java.lang.String, java.lang.String);
-    method public int getIndex();
-    method public java.lang.String getInput();
-    method public java.lang.String getReason();
-  }
-
-  public final class LinkOption extends java.lang.Enum implements java.nio.file.CopyOption java.nio.file.OpenOption {
-    method public static java.nio.file.LinkOption valueOf(java.lang.String);
-    method public static final java.nio.file.LinkOption[] values();
-    enum_constant public static final java.nio.file.LinkOption NOFOLLOW_LINKS;
-  }
-
-  public final class LinkPermission extends java.security.BasicPermission {
-    ctor public LinkPermission(java.lang.String);
-    ctor public LinkPermission(java.lang.String, java.lang.String);
-  }
-
-  public class NoSuchFileException extends java.nio.file.FileSystemException {
-    ctor public NoSuchFileException(java.lang.String);
-    ctor public NoSuchFileException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public class NotDirectoryException extends java.nio.file.FileSystemException {
-    ctor public NotDirectoryException(java.lang.String);
-  }
-
-  public class NotLinkException extends java.nio.file.FileSystemException {
-    ctor public NotLinkException(java.lang.String);
-    ctor public NotLinkException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public abstract interface OpenOption {
-  }
-
-  public abstract interface Path implements java.lang.Comparable java.lang.Iterable java.nio.file.Watchable {
-    method public abstract int compareTo(java.nio.file.Path);
-    method public abstract boolean endsWith(java.nio.file.Path);
-    method public abstract boolean endsWith(java.lang.String);
-    method public abstract boolean equals(java.lang.Object);
-    method public abstract java.nio.file.Path getFileName();
-    method public abstract java.nio.file.FileSystem getFileSystem();
-    method public abstract java.nio.file.Path getName(int);
-    method public abstract int getNameCount();
-    method public abstract java.nio.file.Path getParent();
-    method public abstract java.nio.file.Path getRoot();
-    method public abstract int hashCode();
-    method public abstract boolean isAbsolute();
-    method public abstract java.util.Iterator<java.nio.file.Path> iterator();
-    method public abstract java.nio.file.Path normalize();
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>[], java.nio.file.WatchEvent.Modifier...) throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.Path relativize(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolve(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolve(java.lang.String);
-    method public abstract java.nio.file.Path resolveSibling(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolveSibling(java.lang.String);
-    method public abstract boolean startsWith(java.nio.file.Path);
-    method public abstract boolean startsWith(java.lang.String);
-    method public abstract java.nio.file.Path subpath(int, int);
-    method public abstract java.nio.file.Path toAbsolutePath();
-    method public abstract java.io.File toFile();
-    method public abstract java.nio.file.Path toRealPath(java.nio.file.LinkOption...) throws java.io.IOException;
-    method public abstract java.lang.String toString();
-    method public abstract java.net.URI toUri();
-  }
-
-  public abstract interface PathMatcher {
-    method public abstract boolean matches(java.nio.file.Path);
-  }
-
-  public final class Paths {
-    method public static java.nio.file.Path get(java.lang.String, java.lang.String...);
-    method public static java.nio.file.Path get(java.net.URI);
-  }
-
-  public class ProviderMismatchException extends java.lang.IllegalArgumentException {
-    ctor public ProviderMismatchException();
-    ctor public ProviderMismatchException(java.lang.String);
-  }
-
-  public class ProviderNotFoundException extends java.lang.RuntimeException {
-    ctor public ProviderNotFoundException();
-    ctor public ProviderNotFoundException(java.lang.String);
-  }
-
-  public class ReadOnlyFileSystemException extends java.lang.UnsupportedOperationException {
-    ctor public ReadOnlyFileSystemException();
-  }
-
-  public abstract interface SecureDirectoryStream implements java.nio.file.DirectoryStream {
-    method public abstract void deleteDirectory(T) throws java.io.IOException;
-    method public abstract void deleteFile(T) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.lang.Class<V>);
-    method public abstract V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public abstract void move(T, java.nio.file.SecureDirectoryStream<T>, T) throws java.io.IOException;
-    method public abstract java.nio.channels.SeekableByteChannel newByteChannel(T, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.SecureDirectoryStream<T> newDirectoryStream(T, java.nio.file.LinkOption...) throws java.io.IOException;
-  }
-
-  public final class StandardCopyOption extends java.lang.Enum implements java.nio.file.CopyOption {
-    method public static java.nio.file.StandardCopyOption valueOf(java.lang.String);
-    method public static final java.nio.file.StandardCopyOption[] values();
-    enum_constant public static final java.nio.file.StandardCopyOption ATOMIC_MOVE;
-    enum_constant public static final java.nio.file.StandardCopyOption COPY_ATTRIBUTES;
-    enum_constant public static final java.nio.file.StandardCopyOption REPLACE_EXISTING;
-  }
-
-  public final class StandardOpenOption extends java.lang.Enum implements java.nio.file.OpenOption {
-    method public static java.nio.file.StandardOpenOption valueOf(java.lang.String);
-    method public static final java.nio.file.StandardOpenOption[] values();
-    enum_constant public static final java.nio.file.StandardOpenOption APPEND;
-    enum_constant public static final java.nio.file.StandardOpenOption CREATE;
-    enum_constant public static final java.nio.file.StandardOpenOption CREATE_NEW;
-    enum_constant public static final java.nio.file.StandardOpenOption DELETE_ON_CLOSE;
-    enum_constant public static final java.nio.file.StandardOpenOption DSYNC;
-    enum_constant public static final java.nio.file.StandardOpenOption READ;
-    enum_constant public static final java.nio.file.StandardOpenOption SPARSE;
-    enum_constant public static final java.nio.file.StandardOpenOption SYNC;
-    enum_constant public static final java.nio.file.StandardOpenOption TRUNCATE_EXISTING;
-    enum_constant public static final java.nio.file.StandardOpenOption WRITE;
-  }
-
-  public final class StandardWatchEventKinds {
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_CREATE;
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_DELETE;
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_MODIFY;
-    field public static final java.nio.file.WatchEvent.Kind<java.lang.Object> OVERFLOW;
-  }
-
-  public abstract interface WatchEvent {
-    method public abstract T context();
-    method public abstract int count();
-    method public abstract java.nio.file.WatchEvent.Kind<T> kind();
-  }
-
-  public static abstract interface WatchEvent.Kind {
-    method public abstract java.lang.String name();
-    method public abstract java.lang.Class<T> type();
-  }
-
-  public static abstract interface WatchEvent.Modifier {
-    method public abstract java.lang.String name();
-  }
-
-  public abstract interface WatchKey {
-    method public abstract void cancel();
-    method public abstract boolean isValid();
-    method public abstract java.util.List<java.nio.file.WatchEvent<?>> pollEvents();
-    method public abstract boolean reset();
-    method public abstract java.nio.file.Watchable watchable();
-  }
-
-  public abstract interface WatchService implements java.io.Closeable {
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey poll();
-    method public abstract java.nio.file.WatchKey poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract java.nio.file.WatchKey take() throws java.lang.InterruptedException;
-  }
-
-  public abstract interface Watchable {
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>[], java.nio.file.WatchEvent.Modifier...) throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>...) throws java.io.IOException;
-  }
-
-}
-
-package java.nio.file.attribute {
-
-  public final class AclEntry {
-    method public java.util.Set<java.nio.file.attribute.AclEntryFlag> flags();
-    method public static java.nio.file.attribute.AclEntry.Builder newBuilder();
-    method public static java.nio.file.attribute.AclEntry.Builder newBuilder(java.nio.file.attribute.AclEntry);
-    method public java.util.Set<java.nio.file.attribute.AclEntryPermission> permissions();
-    method public java.nio.file.attribute.UserPrincipal principal();
-    method public java.nio.file.attribute.AclEntryType type();
-  }
-
-  public static final class AclEntry.Builder {
-    method public java.nio.file.attribute.AclEntry build();
-    method public java.nio.file.attribute.AclEntry.Builder setFlags(java.util.Set<java.nio.file.attribute.AclEntryFlag>);
-    method public java.nio.file.attribute.AclEntry.Builder setFlags(java.nio.file.attribute.AclEntryFlag...);
-    method public java.nio.file.attribute.AclEntry.Builder setPermissions(java.util.Set<java.nio.file.attribute.AclEntryPermission>);
-    method public java.nio.file.attribute.AclEntry.Builder setPermissions(java.nio.file.attribute.AclEntryPermission...);
-    method public java.nio.file.attribute.AclEntry.Builder setPrincipal(java.nio.file.attribute.UserPrincipal);
-    method public java.nio.file.attribute.AclEntry.Builder setType(java.nio.file.attribute.AclEntryType);
-  }
-
-  public final class AclEntryFlag extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryFlag valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryFlag[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag DIRECTORY_INHERIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag FILE_INHERIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag INHERIT_ONLY;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag NO_PROPAGATE_INHERIT;
-  }
-
-  public final class AclEntryPermission extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryPermission valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryPermission[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission APPEND_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE_CHILD;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission EXECUTE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ACL;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ATTRIBUTES;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_NAMED_ATTRS;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission SYNCHRONIZE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ACL;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ATTRIBUTES;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_NAMED_ATTRS;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_OWNER;
-    field public static final java.nio.file.attribute.AclEntryPermission ADD_FILE;
-    field public static final java.nio.file.attribute.AclEntryPermission ADD_SUBDIRECTORY;
-    field public static final java.nio.file.attribute.AclEntryPermission LIST_DIRECTORY;
-  }
-
-  public final class AclEntryType extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryType valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryType[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryType ALARM;
-    enum_constant public static final java.nio.file.attribute.AclEntryType ALLOW;
-    enum_constant public static final java.nio.file.attribute.AclEntryType AUDIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryType DENY;
-  }
-
-  public abstract interface AclFileAttributeView implements java.nio.file.attribute.FileOwnerAttributeView {
-    method public abstract java.util.List<java.nio.file.attribute.AclEntry> getAcl() throws java.io.IOException;
-    method public abstract java.lang.String name();
-    method public abstract void setAcl(java.util.List<java.nio.file.attribute.AclEntry>) throws java.io.IOException;
-  }
-
-  public abstract interface AttributeView {
-    method public abstract java.lang.String name();
-  }
-
-  public abstract interface BasicFileAttributeView implements java.nio.file.attribute.FileAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.BasicFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setTimes(java.nio.file.attribute.FileTime, java.nio.file.attribute.FileTime, java.nio.file.attribute.FileTime) throws java.io.IOException;
-  }
-
-  public abstract interface BasicFileAttributes {
-    method public abstract java.nio.file.attribute.FileTime creationTime();
-    method public abstract java.lang.Object fileKey();
-    method public abstract boolean isDirectory();
-    method public abstract boolean isOther();
-    method public abstract boolean isRegularFile();
-    method public abstract boolean isSymbolicLink();
-    method public abstract java.nio.file.attribute.FileTime lastAccessTime();
-    method public abstract java.nio.file.attribute.FileTime lastModifiedTime();
-    method public abstract long size();
-  }
-
-  public abstract interface DosFileAttributeView implements java.nio.file.attribute.BasicFileAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.DosFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setArchive(boolean) throws java.io.IOException;
-    method public abstract void setHidden(boolean) throws java.io.IOException;
-    method public abstract void setReadOnly(boolean) throws java.io.IOException;
-    method public abstract void setSystem(boolean) throws java.io.IOException;
-  }
-
-  public abstract interface DosFileAttributes implements java.nio.file.attribute.BasicFileAttributes {
-    method public abstract boolean isArchive();
-    method public abstract boolean isHidden();
-    method public abstract boolean isReadOnly();
-    method public abstract boolean isSystem();
-  }
-
-  public abstract interface FileAttribute {
-    method public abstract java.lang.String name();
-    method public abstract T value();
-  }
-
-  public abstract interface FileAttributeView implements java.nio.file.attribute.AttributeView {
-  }
-
-  public abstract interface FileOwnerAttributeView implements java.nio.file.attribute.FileAttributeView {
-    method public abstract java.nio.file.attribute.UserPrincipal getOwner() throws java.io.IOException;
-    method public abstract java.lang.String name();
-    method public abstract void setOwner(java.nio.file.attribute.UserPrincipal) throws java.io.IOException;
-  }
-
-  public abstract interface FileStoreAttributeView implements java.nio.file.attribute.AttributeView {
-  }
-
-  public final class FileTime implements java.lang.Comparable {
-    method public int compareTo(java.nio.file.attribute.FileTime);
-    method public static java.nio.file.attribute.FileTime from(long, java.util.concurrent.TimeUnit);
-    method public static java.nio.file.attribute.FileTime fromMillis(long);
-    method public long to(java.util.concurrent.TimeUnit);
-    method public long toMillis();
-  }
-
-  public abstract interface GroupPrincipal implements java.nio.file.attribute.UserPrincipal {
-  }
-
-  public abstract interface PosixFileAttributeView implements java.nio.file.attribute.BasicFileAttributeView java.nio.file.attribute.FileOwnerAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.PosixFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setGroup(java.nio.file.attribute.GroupPrincipal) throws java.io.IOException;
-    method public abstract void setPermissions(java.util.Set<java.nio.file.attribute.PosixFilePermission>) throws java.io.IOException;
-  }
-
-  public abstract interface PosixFileAttributes implements java.nio.file.attribute.BasicFileAttributes {
-    method public abstract java.nio.file.attribute.GroupPrincipal group();
-    method public abstract java.nio.file.attribute.UserPrincipal owner();
-    method public abstract java.util.Set<java.nio.file.attribute.PosixFilePermission> permissions();
-  }
-
-  public final class PosixFilePermission extends java.lang.Enum {
-    method public static java.nio.file.attribute.PosixFilePermission valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.PosixFilePermission[] values();
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_WRITE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_WRITE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_WRITE;
-  }
-
-  public final class PosixFilePermissions {
-    method public static java.nio.file.attribute.FileAttribute<java.util.Set<java.nio.file.attribute.PosixFilePermission>> asFileAttribute(java.util.Set<java.nio.file.attribute.PosixFilePermission>);
-    method public static java.util.Set<java.nio.file.attribute.PosixFilePermission> fromString(java.lang.String);
-    method public static java.lang.String toString(java.util.Set<java.nio.file.attribute.PosixFilePermission>);
-  }
-
-  public abstract interface UserPrincipal implements java.security.Principal {
-  }
-
-  public abstract class UserPrincipalLookupService {
-    ctor protected UserPrincipalLookupService();
-    method public abstract java.nio.file.attribute.GroupPrincipal lookupPrincipalByGroupName(java.lang.String) throws java.io.IOException;
-    method public abstract java.nio.file.attribute.UserPrincipal lookupPrincipalByName(java.lang.String) throws java.io.IOException;
-  }
-
-  public class UserPrincipalNotFoundException extends java.io.IOException {
-    ctor public UserPrincipalNotFoundException(java.lang.String);
-    method public java.lang.String getName();
-  }
-
-}
-
-package java.nio.file.spi {
-
-  public abstract class FileSystemProvider {
-    ctor protected FileSystemProvider();
-    method public abstract void checkAccess(java.nio.file.Path, java.nio.file.AccessMode...) throws java.io.IOException;
-    method public abstract void copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public abstract void createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public void createLink(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public void createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract void delete(java.nio.file.Path) throws java.io.IOException;
-    method public boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public abstract java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
-    method public abstract java.nio.file.FileSystem getFileSystem(java.net.URI);
-    method public abstract java.nio.file.Path getPath(java.net.URI);
-    method public abstract java.lang.String getScheme();
-    method public static java.util.List<java.nio.file.spi.FileSystemProvider> installedProviders();
-    method public abstract boolean isHidden(java.nio.file.Path) throws java.io.IOException;
-    method public abstract boolean isSameFile(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public abstract void move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public java.nio.channels.AsynchronousFileChannel newAsynchronousFileChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) throws java.io.IOException;
-    method public java.nio.channels.FileChannel newFileChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public abstract java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
-    method public abstract void setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
-  }
-
-  public abstract class FileTypeDetector {
-    ctor protected FileTypeDetector();
-    method public abstract java.lang.String probeContentType(java.nio.file.Path) throws java.io.IOException;
-  }
-
-}
-
 package java.security {
 
   public final class AccessControlContext {
@@ -58192,8 +58110,6 @@
     ctor public Scanner(java.io.InputStream, java.lang.String);
     ctor public Scanner(java.io.File) throws java.io.FileNotFoundException;
     ctor public Scanner(java.io.File, java.lang.String) throws java.io.FileNotFoundException;
-    ctor public Scanner(java.nio.file.Path) throws java.io.IOException;
-    ctor public Scanner(java.nio.file.Path, java.lang.String) throws java.io.IOException;
     ctor public Scanner(java.lang.String);
     ctor public Scanner(java.nio.channels.ReadableByteChannel);
     ctor public Scanner(java.nio.channels.ReadableByteChannel, java.lang.String);
diff --git a/api/removed.txt b/api/removed.txt
index 6b7961e..2c6729d 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -201,7 +201,7 @@
 
 package android.test.mock {
 
-  public class MockPackageManager extends android.content.pm.PackageManager {
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
     method public deprecated java.lang.String getDefaultBrowserPackageName(int);
     method public deprecated boolean setDefaultBrowserPackageName(java.lang.String, int);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 3fc6437..dc8e5da 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -46,6 +46,7 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
@@ -600,6 +601,8 @@
     field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
+    field public static final int endX = 16844051; // 0x1010513
+    field public static final int endY = 16844052; // 0x1010514
     field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
     field public static final int entries = 16842930; // 0x10100b2
@@ -975,6 +978,7 @@
     field public static final int numbersTextColor = 16843937; // 0x10104a1
     field public static final deprecated int numeric = 16843109; // 0x1010165
     field public static final int numericShortcut = 16843236; // 0x10101e4
+    field public static final int offset = 16844053; // 0x1010515
     field public static final int onClick = 16843375; // 0x101026f
     field public static final int oneshot = 16843159; // 0x1010197
     field public static final int opacity = 16843550; // 0x101031e
@@ -1226,6 +1230,8 @@
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
+    field public static final int startX = 16844049; // 0x1010511
+    field public static final int startY = 16844050; // 0x1010512
     field public static final deprecated int startYear = 16843132; // 0x101017c
     field public static final int stateListAnimator = 16843848; // 0x1010448
     field public static final int stateNotNeeded = 16842774; // 0x1010016
@@ -4768,6 +4774,7 @@
     method public android.content.Context getContext();
     method public android.content.Context getTargetContext();
     method public android.app.UiAutomation getUiAutomation();
+    method public android.app.UiAutomation getUiAutomation(int);
     method public boolean invokeContextMenuAction(android.app.Activity, int, int);
     method public boolean invokeMenuActionSync(android.app.Activity, int, int);
     method public boolean isProfiling();
@@ -5664,6 +5671,7 @@
   public final class UiAutomation {
     method public void clearWindowAnimationFrameStats();
     method public boolean clearWindowContentFrameStats(int);
+    method public void destroy();
     method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
     method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -5680,6 +5688,7 @@
     method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
     method public android.graphics.Bitmap takeScreenshot();
     method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
+    field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1
     field public static final int ROTATION_FREEZE_0 = 0; // 0x0
     field public static final int ROTATION_FREEZE_180 = 2; // 0x2
     field public static final int ROTATION_FREEZE_270 = 3; // 0x3
@@ -5955,6 +5964,7 @@
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
+    method public java.lang.String getOrganizationName(android.content.ComponentName);
     method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -6030,6 +6040,7 @@
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setOrganizationColor(android.content.ComponentName, int);
+    method public void setOrganizationName(android.content.ComponentName, java.lang.String);
     method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
     method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -6768,8 +6779,9 @@
     field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
     field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
     field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_DEVICE_LOCKED = 210007; // 0x33457
-    field public static final int TAG_DEVICE_UNLOCK_ATTEMPT = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
     field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
     field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
   }
@@ -7607,6 +7619,8 @@
     method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
     method public void startScan(android.bluetooth.le.ScanCallback);
     method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+    method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
+    method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
     method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
     method public void stopScan(android.bluetooth.le.ScanCallback);
   }
@@ -8331,6 +8345,7 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
+    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
     field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
@@ -9946,6 +9961,7 @@
     method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public abstract boolean isSafeMode();
     method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
+    method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(android.content.Intent, int, android.os.UserHandle);
     method public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(java.lang.String, int, int);
     method public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
     method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int);
@@ -10345,7 +10361,7 @@
     method public final long skip(long) throws java.io.IOException;
   }
 
-  public class ColorStateList implements android.os.Parcelable {
+  public class ColorStateList extends android.content.res.ComplexColor implements android.os.Parcelable {
     ctor public ColorStateList(int[][], int[]);
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -10354,13 +10370,18 @@
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
-    method public boolean isStateful();
     method public static android.content.res.ColorStateList valueOf(int);
     method public android.content.res.ColorStateList withAlpha(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR;
   }
 
+  public abstract class ComplexColor {
+    ctor public ComplexColor();
+    method public abstract int getDefaultColor();
+    method public boolean isStateful();
+  }
+
   public final class Configuration implements java.lang.Comparable android.os.Parcelable {
     ctor public Configuration();
     ctor public Configuration(android.content.res.Configuration);
@@ -10464,6 +10485,11 @@
     field public int uiMode;
   }
 
+  public class GradientColor extends android.content.res.ComplexColor {
+    method public static android.content.res.GradientColor createFromXml(android.content.res.Resources, android.content.res.XmlResourceParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public int getDefaultColor();
+  }
+
   public class ObbInfo implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10523,6 +10549,7 @@
     method public void getValue(java.lang.String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
     method public void getValueForDensity(int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
     method public android.content.res.XmlResourceParser getXml(int) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.ComplexColor loadComplexColor(android.util.TypedValue, int, android.content.res.Resources.Theme);
     method public final android.content.res.Resources.Theme newTheme();
     method public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]);
     method public android.content.res.TypedArray obtainTypedArray(int) throws android.content.res.Resources.NotFoundException;
@@ -10558,6 +10585,7 @@
     method public int getChangingConfigurations();
     method public int getColor(int, int);
     method public android.content.res.ColorStateList getColorStateList(int);
+    method public android.content.res.ComplexColor getComplexColor(int);
     method public float getDimension(int, float);
     method public int getDimensionPixelOffset(int, int);
     method public int getDimensionPixelSize(int, int);
@@ -13754,6 +13782,7 @@
     method public float getResolution();
     method public java.lang.String getStringType();
     method public int getType();
+    method public java.util.UUID getUuid();
     method public java.lang.String getVendor();
     method public int getVersion();
     method public boolean isDataInjectionSupported();
@@ -13764,16 +13793,19 @@
     field public static final int REPORTING_MODE_SPECIAL_TRIGGER = 3; // 0x3
     field public static final java.lang.String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer";
     field public static final java.lang.String STRING_TYPE_AMBIENT_TEMPERATURE = "android.sensor.ambient_temperature";
+    field public static final java.lang.String STRING_TYPE_DYNAMIC_SENSOR_META = "android.sensor.dynamic_sensor_meta";
     field public static final java.lang.String STRING_TYPE_GAME_ROTATION_VECTOR = "android.sensor.game_rotation_vector";
     field public static final java.lang.String STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR = "android.sensor.geomagnetic_rotation_vector";
     field public static final java.lang.String STRING_TYPE_GRAVITY = "android.sensor.gravity";
     field public static final java.lang.String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
     field public static final java.lang.String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
+    field public static final java.lang.String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
     field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
     field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
     field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
+    field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
     field public static final deprecated java.lang.String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
     field public static final java.lang.String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
     field public static final java.lang.String STRING_TYPE_PRESSURE = "android.sensor.pressure";
@@ -13781,6 +13813,7 @@
     field public static final java.lang.String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
     field public static final java.lang.String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
     field public static final java.lang.String STRING_TYPE_SIGNIFICANT_MOTION = "android.sensor.significant_motion";
+    field public static final java.lang.String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
     field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
     field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
     field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
@@ -13788,16 +13821,19 @@
     field public static final int TYPE_ACCELEROMETER = 1; // 0x1
     field public static final int TYPE_ALL = -1; // 0xffffffff
     field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
+    field public static final int TYPE_DYNAMIC_SENSOR_META = 32; // 0x20
     field public static final int TYPE_GAME_ROTATION_VECTOR = 15; // 0xf
     field public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20; // 0x14
     field public static final int TYPE_GRAVITY = 9; // 0x9
     field public static final int TYPE_GYROSCOPE = 4; // 0x4
     field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
+    field public static final int TYPE_HEART_BEAT = 31; // 0x1f
     field public static final int TYPE_HEART_RATE = 21; // 0x15
     field public static final int TYPE_LIGHT = 5; // 0x5
     field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
     field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
     field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
+    field public static final int TYPE_MOTION_DETECT = 30; // 0x1e
     field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
     field public static final int TYPE_POSE_6DOF = 28; // 0x1c
     field public static final int TYPE_PRESSURE = 6; // 0x6
@@ -13805,12 +13841,28 @@
     field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
     field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
     field public static final int TYPE_SIGNIFICANT_MOTION = 17; // 0x11
+    field public static final int TYPE_STATIONARY_DETECT = 29; // 0x1d
     field public static final int TYPE_STEP_COUNTER = 19; // 0x13
     field public static final int TYPE_STEP_DETECTOR = 18; // 0x12
     field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
     field public static final int TYPE_WRIST_TILT_GESTURE = 26; // 0x1a
   }
 
+  public class SensorAdditionalInfo {
+    field public static final int TYPE_FRAME_BEGIN = 0; // 0x0
+    field public static final int TYPE_FRAME_END = 1; // 0x1
+    field public static final int TYPE_INTERNAL_TEMPERATURE = 65537; // 0x10001
+    field public static final int TYPE_SAMPLING = 65540; // 0x10004
+    field public static final int TYPE_SENSOR_PLACEMENT = 65539; // 0x10003
+    field public static final int TYPE_UNTRACKED_DELAY = 65536; // 0x10000
+    field public static final int TYPE_VEC3_CALIBRATION = 65538; // 0x10002
+    field public final float[] floatValues;
+    field public final int[] intValues;
+    field public final android.hardware.Sensor sensor;
+    field public final int serial;
+    field public final int type;
+  }
+
   public class SensorEvent {
     field public int accuracy;
     field public android.hardware.Sensor sensor;
@@ -13818,6 +13870,14 @@
     field public final float[] values;
   }
 
+  public abstract class SensorEventCallback implements android.hardware.SensorEventListener2 {
+    ctor public SensorEventCallback();
+    method public void onAccuracyChanged(android.hardware.Sensor, int);
+    method public void onFlushCompleted(android.hardware.Sensor);
+    method public void onSensorAdditionalInfo(android.hardware.SensorAdditionalInfo);
+    method public void onSensorChanged(android.hardware.SensorEvent);
+  }
+
   public abstract interface SensorEventListener {
     method public abstract void onAccuracyChanged(android.hardware.Sensor, int);
     method public abstract void onSensorChanged(android.hardware.SensorEvent);
@@ -13839,6 +13899,7 @@
     method public static void getAngleChange(float[], float[], float[]);
     method public android.hardware.Sensor getDefaultSensor(int);
     method public android.hardware.Sensor getDefaultSensor(int, boolean);
+    method public java.util.List<android.hardware.Sensor> getDynamicSensorList(int);
     method public static float getInclination(float[]);
     method public static float[] getOrientation(float[], float[]);
     method public static void getQuaternionFromVector(float[], float[]);
@@ -13848,6 +13909,8 @@
     method public deprecated int getSensors();
     method public boolean initDataInjection(boolean);
     method public boolean injectSensorData(android.hardware.Sensor, float[], int, long);
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13856,6 +13919,7 @@
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
     method public static boolean remapCoordinateSystem(float[], int, int, float[]);
     method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
     method public deprecated void unregisterListener(android.hardware.SensorListener);
     method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13920,6 +13984,12 @@
     field public static final float STANDARD_GRAVITY = 9.80665f;
   }
 
+  public static abstract class SensorManager.DynamicSensorConnectionCallback {
+    ctor public SensorManager.DynamicSensorConnectionCallback();
+    method public void onDynamicSensorConnected(android.hardware.Sensor);
+    method public void onDynamicSensorDisconnected(android.hardware.Sensor);
+  }
+
   public final class TriggerEvent {
     field public android.hardware.Sensor sensor;
     field public long timestamp;
@@ -15059,6 +15129,66 @@
 
 package android.hardware.location {
 
+  public class ContextHubInfo {
+    ctor public ContextHubInfo();
+    method public int describeContents();
+    method public int getId();
+    method public android.hardware.location.MemoryRegion[] getMemoryRegions();
+    method public java.lang.String getName();
+    method public float getPeakMips();
+    method public float getPeakPowerDrawMw();
+    method public int getPlatformVersion();
+    method public float getSleepPowerDrawMw();
+    method public int getStaticSwVersion();
+    method public float getStoppedPowerDrawMw();
+    method public int[] getSupportedSensors();
+    method public java.lang.String getToolchain();
+    method public int getToolchainVersion();
+    method public java.lang.String getVendor();
+    method public void setId(int);
+    method public void setMemoryRegions(android.hardware.location.MemoryRegion[]);
+    method public void setName(java.lang.String);
+    method public void setPeakMips(float);
+    method public void setPeakPowerDrawMw(float);
+    method public void setPlatformVersion(int);
+    method public void setSleepPowerDrawMw(float);
+    method public void setStaticSwVersion(int);
+    method public void setStoppedPowerDrawMw(float);
+    method public void setSupportedSensors(int[]);
+    method public void setToolchain(java.lang.String);
+    method public void setToolchainVersion(int);
+    method public void setVendor(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubInfo> CREATOR;
+  }
+
+  public final class ContextHubManager {
+    method public java.lang.Integer[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
+    method public int[] getContexthubHandles();
+    method public android.hardware.location.ContextHubInfo getContexthubInfo(int);
+    method public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
+    method public int loadNanoApp(int, android.hardware.location.NanoApp);
+    method public int sendMessage(int, int, android.hardware.location.ContextHubMessage);
+    method public int unloadNanoApp(int);
+    field public static final int ANY_HUB = -1; // 0xffffffff
+    field public static final int MSG_DATA_SEND = 3; // 0x3
+    field public static final int MSG_LOAD_NANO_APP = 1; // 0x1
+    field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2
+  }
+
+  public class ContextHubMessage {
+    ctor public ContextHubMessage(int, int, byte[]);
+    method public int describeContents();
+    method public byte[] getData();
+    method public int getMsgType();
+    method public int getVersion();
+    method public void setMsgData(byte[]);
+    method public void setMsgType(int);
+    method public void setVersion(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubMessage> CREATOR;
+  }
+
   public final class GeofenceHardware {
     ctor public GeofenceHardware(android.hardware.location.IGeofenceHardware);
     method public boolean addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback);
@@ -15175,6 +15305,89 @@
     method public abstract void onMonitoringSystemChange(android.hardware.location.GeofenceHardwareMonitorEvent) throws android.os.RemoteException;
   }
 
+  public class MemoryRegion implements android.os.Parcelable {
+    ctor public MemoryRegion(android.os.Parcel);
+    method public int describeContents();
+    method public int getCapacityBytes();
+    method public int getFreeCapacityBytes();
+    method public boolean isExecutable();
+    method public boolean isReadable();
+    method public boolean isWritable();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.location.MemoryRegion> CREATOR;
+  }
+
+  public class NanoApp {
+    ctor public NanoApp();
+    method public int describeContents();
+    method public byte[] getAppBinary();
+    method public int getAppId();
+    method public int getAppVersion();
+    method public java.lang.String getName();
+    method public int getNeededExecMemBytes();
+    method public int getNeededReadMemBytes();
+    method public int[] getNeededSensors();
+    method public int getNeededWriteMemBytes();
+    method public int[] getOutputEvents();
+    method public java.lang.String getPublisher();
+    method public void setAppBinary(byte[]);
+    method public void setAppId(int);
+    method public void setAppVersion(int);
+    method public void setName(java.lang.String);
+    method public void setNeededExecMemBytes(int);
+    method public void setNeededReadMemBytes(int);
+    method public void setNeededSensors(int[]);
+    method public void setNeededWriteMemBytes(int);
+    method public void setOutputEvents(int[]);
+    method public void setPublisher(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.location.NanoApp> CREATOR;
+  }
+
+  public class NanoAppFilter {
+    ctor public NanoAppFilter(long, int, int, long);
+    method public int describeContents();
+    method public boolean testMatch(android.hardware.location.NanoAppInstanceInfo);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int APP_ANY = -1; // 0xffffffff
+    field public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppFilter> CREATOR;
+    field public static final int FLAGS_VERSION_ANY = -1; // 0xffffffff
+    field public static final int FLAGS_VERSION_GREAT_THAN = 2; // 0x2
+    field public static final int FLAGS_VERSION_LESS_THAN = 4; // 0x4
+    field public static final int FLAGS_VERSION_STRICTLY_EQUAL = 8; // 0x8
+    field public static final int HUB_ANY = -1; // 0xffffffff
+    field public static final int VENDOR_ANY = -1; // 0xffffffff
+  }
+
+  public class NanoAppInstanceInfo {
+    ctor public NanoAppInstanceInfo();
+    method public int describeContents();
+    method public int getAppId();
+    method public int getAppVersion();
+    method public int getContexthubId();
+    method public int getHandle();
+    method public java.lang.String getName();
+    method public int getNeededExecMemBytes();
+    method public int getNeededReadMemBytes();
+    method public int[] getNeededSensors();
+    method public int getNeededWriteMemBytes();
+    method public int[] getOutputEvents();
+    method public java.lang.String getPublisher();
+    method public void setAppId(int);
+    method public void setAppVersion(int);
+    method public void setContexthubId(int);
+    method public void setHandle(int);
+    method public void setName(java.lang.String);
+    method public void setNeededExecMemBytes(int);
+    method public void setNeededReadMemBytes(int);
+    method public void setNeededSensors(int[]);
+    method public void setNeededWriteMemBytes(int);
+    method public void setOutputEvents(int[]);
+    method public void setPublisher(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppInstanceInfo> CREATOR;
+  }
+
 }
 
 package android.hardware.radio {
@@ -20049,7 +20262,38 @@
     method public static boolean isPresent();
   }
 
-  public class GpsClock implements android.os.Parcelable {
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public float getAzimuth(int);
+    method public int getConstellationType(int);
+    method public float getElevation(int);
+    method public int getNumSatellites();
+    method public int getPrn(int);
+    method public float getSnr(int);
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+    method public boolean usedInFix(int);
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+  }
+
+  public abstract class GnssStatusCallback {
+    ctor public GnssStatusCallback();
+    method public void onFirstFix(int);
+    method public void onSatelliteStatusChanged(android.location.GnssStatus);
+    method public void onStarted();
+    method public void onStopped();
+  }
+
+  public final class GpsClock implements android.os.Parcelable {
     method public int describeContents();
     method public double getBiasInNs();
     method public double getBiasUncertaintyInNs();
@@ -20058,6 +20302,7 @@
     method public long getFullBiasInNs();
     method public short getLeapSecond();
     method public long getTimeInNs();
+    method public long getTimeOfLastHwClockDiscontinuityInNs();
     method public double getTimeUncertaintyInNs();
     method public byte getType();
     method public boolean hasBiasInNs();
@@ -20083,16 +20328,20 @@
     method public void setFullBiasInNs(long);
     method public void setLeapSecond(short);
     method public void setTimeInNs(long);
+    method public void setTimeOfLastHwClockDiscontinuityInNs(long);
     method public void setTimeUncertaintyInNs(double);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
+    field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
+    field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
     field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
-    field public static final byte TYPE_GPS_TIME = 2; // 0x2
-    field public static final byte TYPE_LOCAL_HW_TIME = 1; // 0x1
-    field public static final byte TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public class GpsMeasurement implements android.os.Parcelable {
+  public static abstract class GpsClock.GpsClockType implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsMeasurement implements android.os.Parcelable {
     method public int describeContents();
     method public double getAccumulatedDeltaRangeInMeters();
     method public short getAccumulatedDeltaRangeState();
@@ -20115,6 +20364,8 @@
     method public byte getMultipathIndicator();
     method public byte getPrn();
     method public double getPseudorangeInMeters();
+    method public double getPseudorangeRateCarrierInMetersPerSec();
+    method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
     method public double getPseudorangeRateInMetersPerSec();
     method public double getPseudorangeRateUncertaintyInMetersPerSec();
     method public double getPseudorangeUncertaintyInMeters();
@@ -20183,6 +20434,8 @@
     method public void setMultipathIndicator(byte);
     method public void setPrn(byte);
     method public void setPseudorangeInMeters(double);
+    method public void setPseudorangeRateCarrierInMetersPerSec(double);
+    method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
     method public void setPseudorangeRateInMetersPerSec(double);
     method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
     method public void setPseudorangeUncertaintyInMeters(double);
@@ -20213,7 +20466,13 @@
     field public static final short STATE_UNKNOWN = 0; // 0x0
   }
 
-  public class GpsMeasurementsEvent implements android.os.Parcelable {
+  public static abstract class GpsMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class GpsMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsMeasurementsEvent implements android.os.Parcelable {
     ctor public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
     method public int describeContents();
     method public android.location.GpsClock getClock();
@@ -20225,12 +20484,16 @@
     field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract interface GpsMeasurementsEvent.Listener {
-    method public abstract void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
-    method public abstract void onStatusChanged(int);
+  public static abstract class GpsMeasurementsEvent.Callback {
+    ctor public GpsMeasurementsEvent.Callback();
+    method public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+    method public void onStatusChanged(int);
   }
 
-  public class GpsNavigationMessage implements android.os.Parcelable {
+  public static abstract class GpsMeasurementsEvent.GpsMeasurementsStatus implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
@@ -20248,30 +20511,37 @@
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+    field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
+    field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
+    field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
+    field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
+    field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
     field public static final short STATUS_PARITY_PASSED = 1; // 0x1
     field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
     field public static final short STATUS_UNKNOWN = 0; // 0x0
-    field public static final byte TYPE_CNAV2 = 4; // 0x4
-    field public static final byte TYPE_L1CA = 1; // 0x1
-    field public static final byte TYPE_L2CNAV = 2; // 0x2
-    field public static final byte TYPE_L5CNAV = 3; // 0x3
-    field public static final byte TYPE_UNKNOWN = 0; // 0x0
   }
 
-  public class GpsNavigationMessageEvent implements android.os.Parcelable {
+  public static abstract class GpsNavigationMessage.GpsNavigationMessageType implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsNavigationMessageEvent implements android.os.Parcelable {
     ctor public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
     method public int describeContents();
     method public android.location.GpsNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
-    field public static int STATUS_GPS_LOCATION_DISABLED;
-    field public static int STATUS_NOT_SUPPORTED;
-    field public static int STATUS_READY;
+    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static abstract interface GpsNavigationMessageEvent.Listener {
-    method public abstract void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
-    method public abstract void onStatusChanged(int);
+  public static abstract class GpsNavigationMessageEvent.Callback {
+    ctor public GpsNavigationMessageEvent.Callback();
+    method public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public static abstract class GpsNavigationMessageEvent.GpsNavigationMessageStatus implements java.lang.annotation.Annotation {
   }
 
   public final class GpsSatellite {
@@ -20378,10 +20648,10 @@
   }
 
   public class LocationManager {
-    method public boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
-    method public boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
-    method public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
-    method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+    method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
     method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
     method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
     method public void clearTestProviderEnabled(java.lang.String);
@@ -20389,16 +20659,21 @@
     method public void clearTestProviderStatus(java.lang.String);
     method public java.util.List<java.lang.String> getAllProviders();
     method public java.lang.String getBestProvider(android.location.Criteria, boolean);
-    method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
+    method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
     method public android.location.Location getLastKnownLocation(java.lang.String);
     method public android.location.LocationProvider getProvider(java.lang.String);
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
-    method public void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
-    method public void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
-    method public void removeGpsStatusListener(android.location.GpsStatus.Listener);
-    method public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
+    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
+    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback, android.os.Handler);
+    method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
+    method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public void removeNmeaListener(android.location.GnssNmeaListener);
     method public void removeProximityAlert(android.app.PendingIntent);
     method public void removeTestProvider(java.lang.String);
     method public void removeUpdates(android.location.LocationListener);
@@ -20418,6 +20693,9 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+    method public void unregisterGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
+    method public void unregisterGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
     field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
     field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -20524,6 +20802,7 @@
     field public static final int FLAG_BYPASS_MUTE = 128; // 0x80
     field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
     field public static final int FLAG_HW_HOTWORD = 32; // 0x20
+    field public static final int FLAG_LOW_LATENCY = 256; // 0x100
     field public static final int USAGE_ALARM = 4; // 0x4
     field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
     field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -20657,6 +20936,7 @@
     field public static final int ENCODING_DTS = 7; // 0x7
     field public static final int ENCODING_DTS_HD = 8; // 0x8
     field public static final int ENCODING_E_AC3 = 6; // 0x6
+    field public static final int ENCODING_IEC61937 = 13; // 0xd
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
     field public static final int ENCODING_PCM_8BIT = 3; // 0x3
@@ -20862,6 +21142,7 @@
     method public android.media.AudioDeviceInfo getRoutedDevice();
     method public int getSampleRate();
     method public int getState();
+    method public int getTimestamp(android.media.AudioTimestamp, int);
     method public int read(byte[], int, int);
     method public int read(byte[], int, int, int);
     method public int read(short[], int, int);
@@ -20913,8 +21194,11 @@
 
   public class AudioRecordConfiguration implements android.os.Parcelable {
     method public int describeContents();
-    method public int getAudioSessionId();
+    method public android.media.AudioDeviceInfo getAudioDevice();
+    method public int getClientAudioSessionId();
     method public int getClientAudioSource();
+    method public android.media.AudioFormat getClientFormat();
+    method public android.media.AudioFormat getFormat();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
   }
@@ -20932,6 +21216,8 @@
 
   public final class AudioTimestamp {
     ctor public AudioTimestamp();
+    field public static final int TIMEBASE_BOOTTIME = 1; // 0x1
+    field public static final int TIMEBASE_MONOTONIC = 0; // 0x0
     field public long framePosition;
     field public long nanoTime;
   }
@@ -20946,6 +21232,7 @@
     method public void flush();
     method public int getAudioFormat();
     method public int getAudioSessionId();
+    method public int getBufferCapacityInFrames();
     method public int getBufferSizeInFrames();
     method public int getChannelConfiguration();
     method public int getChannelCount();
@@ -20967,6 +21254,7 @@
     method public int getState();
     method public int getStreamType();
     method public boolean getTimestamp(android.media.AudioTimestamp);
+    method public int getUnderrunCount();
     method public void pause() throws java.lang.IllegalStateException;
     method public void play() throws java.lang.IllegalStateException;
     method public void release();
@@ -20974,6 +21262,7 @@
     method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
     method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public int setAuxEffectSendLevel(float);
+    method public int setBufferSizeInFrames(int);
     method public int setLoopPoints(int, int, int);
     method public int setNotificationMarkerPosition(int);
     method public int setPlaybackHeadPosition(int);
@@ -21085,6 +21374,16 @@
     ctor public DeniedByServerException(java.lang.String);
   }
 
+  public abstract class DrmInitData {
+    ctor public DrmInitData();
+    method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
+  }
+
+  public static final class DrmInitData.SchemeInitData {
+    field public final byte[] data;
+    field public final java.lang.String mimeType;
+  }
+
   public class ExifInterface {
     ctor public ExifInterface(java.lang.String) throws java.io.IOException;
     method public double getAltitude(double);
@@ -21432,6 +21731,7 @@
     field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
     field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+    field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
     field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
     field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
     field public int[] colorFormats;
@@ -21474,6 +21774,21 @@
     field public static final int AVCProfileHigh422 = 32; // 0x20
     field public static final int AVCProfileHigh444 = 64; // 0x40
     field public static final int AVCProfileMain = 2; // 0x2
+    field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
+    field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
+    field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
+    field public static final int DolbyVisionLevelHd24 = 1; // 0x1
+    field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+    field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
+    field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
+    field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
+    field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
+    field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
+    field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
+    field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
+    field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
+    field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
+    field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
     field public static final int H263Level10 = 1; // 0x1
     field public static final int H263Level20 = 2; // 0x2
     field public static final int H263Level30 = 4; // 0x4
@@ -21558,6 +21873,24 @@
     field public static final int VP8Level_Version2 = 4; // 0x4
     field public static final int VP8Level_Version3 = 8; // 0x8
     field public static final int VP8ProfileMain = 1; // 0x1
+    field public static final int VP9Level1 = 0; // 0x0
+    field public static final int VP9Level11 = 1; // 0x1
+    field public static final int VP9Level2 = 2; // 0x2
+    field public static final int VP9Level21 = 4; // 0x4
+    field public static final int VP9Level3 = 8; // 0x8
+    field public static final int VP9Level31 = 16; // 0x10
+    field public static final int VP9Level4 = 32; // 0x20
+    field public static final int VP9Level41 = 64; // 0x40
+    field public static final int VP9Level5 = 128; // 0x80
+    field public static final int VP9Level51 = 256; // 0x100
+    field public static final int VP9Level52 = 512; // 0x200
+    field public static final int VP9Level6 = 1024; // 0x400
+    field public static final int VP9Level61 = 2048; // 0x800
+    field public static final int VP9Level62 = 4096; // 0x1000
+    field public static final int VP9Profile0 = 0; // 0x0
+    field public static final int VP9Profile1 = 1; // 0x1
+    field public static final int VP9Profile2 = 2; // 0x2
+    field public static final int VP9Profile3 = 3; // 0x3
     field public int level;
     field public int profile;
   }
@@ -21741,6 +22074,7 @@
     ctor public MediaExtractor();
     method public boolean advance();
     method public long getCachedDuration();
+    method public android.media.DrmInitData getDrmInitData();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -21785,6 +22119,16 @@
     method public final void setInteger(java.lang.String, int);
     method public final void setLong(java.lang.String, long);
     method public final void setString(java.lang.String, java.lang.String);
+    field public static final int COLOR_RANGE_FULL = 1; // 0x1
+    field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
+    field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
+    field public static final int COLOR_STANDARD_BT601_NTSC = 4; // 0x4
+    field public static final int COLOR_STANDARD_BT601_PAL = 2; // 0x2
+    field public static final int COLOR_STANDARD_BT709 = 1; // 0x1
+    field public static final int COLOR_TRANSFER_HLG = 7; // 0x7
+    field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
+    field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
+    field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
     field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
     field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
     field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression";
@@ -21800,11 +22144,15 @@
     field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
     field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
     field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
+    field public static final java.lang.String KEY_COLOR_RANGE = "color-range";
+    field public static final java.lang.String KEY_COLOR_STANDARD = "color-standard";
+    field public static final java.lang.String KEY_COLOR_TRANSFER = "color-transfer";
     field public static final java.lang.String KEY_COMPLEXITY = "complexity";
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
     field public static final java.lang.String KEY_HEIGHT = "height";
+    field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
     field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect";
     field public static final java.lang.String KEY_IS_DEFAULT = "is-default";
@@ -22126,9 +22474,11 @@
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
     method public android.view.Surface getSurface();
+    method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void release();
     method public void reset();
+    method public void resume() throws java.lang.IllegalStateException;
     method public void setAudioChannels(int);
     method public void setAudioEncoder(int) throws java.lang.IllegalStateException;
     method public void setAudioEncodingBitRate(int);
@@ -23107,12 +23457,15 @@
   public class AudioMixingRule {
     field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
     field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1
+    field public static final int RULE_MATCH_UID = 4; // 0x4
   }
 
   public static class AudioMixingRule.Builder {
     ctor public AudioMixingRule.Builder();
+    method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, java.lang.Object) throws java.lang.IllegalArgumentException;
     method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
     method public android.media.audiopolicy.AudioMixingRule build();
+    method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, java.lang.Object) throws java.lang.IllegalArgumentException;
     method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException;
   }
 
@@ -23492,6 +23845,7 @@
     method public void setRatingType(int);
     method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
@@ -23570,6 +23924,7 @@
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
+    field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
@@ -23618,6 +23973,38 @@
 
 }
 
+package android.media.soundtrigger {
+
+  public final class SoundTriggerDetector {
+    method public boolean startRecognition();
+    method public boolean stopRecognition();
+  }
+
+  public abstract class SoundTriggerDetector.Callback {
+    ctor public SoundTriggerDetector.Callback();
+    method public abstract void onAvailabilityChanged(int);
+    method public abstract void onDetected();
+    method public abstract void onError();
+    method public abstract void onRecognitionPaused();
+    method public abstract void onRecognitionResumed();
+  }
+
+  public final class SoundTriggerManager {
+    method public android.media.soundtrigger.SoundTriggerDetector createSoundTriggerDetector(java.util.UUID, android.media.soundtrigger.SoundTriggerDetector.Callback, android.os.Handler);
+    method public void deleteModel(java.util.UUID);
+    method public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
+    method public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
+  }
+
+  public static class SoundTriggerManager.Model {
+    method public static android.media.soundtrigger.SoundTriggerManager.Model create(java.util.UUID, java.util.UUID, byte[]);
+    method public byte[] getModelData();
+    method public java.util.UUID getModelUuid();
+    method public java.util.UUID getVendorUuid();
+  }
+
+}
+
 package android.media.tv {
 
   public final class TvContentRating {
@@ -24028,7 +24415,7 @@
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
     method public void onInputUpdated(java.lang.String);
-    method public void onTvInputInfoChanged(java.lang.String, android.media.tv.TvInputInfo);
+    method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
   public abstract class TvInputService extends android.app.Service {
@@ -24040,7 +24427,7 @@
     method public java.lang.String onHardwareRemoved(android.media.tv.TvInputHardwareInfo);
     method public android.media.tv.TvInputInfo onHdmiDeviceAdded(android.hardware.hdmi.HdmiDeviceInfo);
     method public java.lang.String onHdmiDeviceRemoved(android.hardware.hdmi.HdmiDeviceInfo);
-    method public final void setTvInputInfo(java.lang.String, android.media.tv.TvInputInfo);
+    method public static final void setTvInputInfo(android.content.Context, android.media.tv.TvInputInfo);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
     field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
   }
@@ -24347,6 +24734,7 @@
     field public static final int OPERATION_GET_OBJECT_PROP_VALUE = 38915; // 0x9803
     field public static final int OPERATION_GET_OBJECT_REFERENCES = 38928; // 0x9810
     field public static final int OPERATION_GET_PARTIAL_OBJECT = 4123; // 0x101b
+    field public static final int OPERATION_GET_PARTIAL_OBJECT_64 = 38337; // 0x95c1
     field public static final int OPERATION_GET_STORAGE_INFO = 4101; // 0x1005
     field public static final int OPERATION_GET_STORAGE_I_DS = 4100; // 0x1004
     field public static final int OPERATION_GET_THUMB = 4106; // 0x100a
@@ -24384,6 +24772,7 @@
     method public android.mtp.MtpObjectInfo getObjectInfo(int);
     method public long getParent(int);
     method public long getPartialObject(int, long, long, byte[]) throws java.io.IOException;
+    method public long getPartialObject64(int, long, long, byte[]) throws java.io.IOException;
     method public long getStorageId(int);
     method public int[] getStorageIds();
     method public android.mtp.MtpStorageInfo getStorageInfo(int);
@@ -24392,7 +24781,7 @@
     method public boolean importFile(int, android.os.ParcelFileDescriptor);
     method public boolean open(android.hardware.usb.UsbDeviceConnection);
     method public android.mtp.MtpEvent readEvent(android.os.CancellationSignal);
-    method public boolean sendObject(int, int, android.os.ParcelFileDescriptor);
+    method public boolean sendObject(int, long, android.os.ParcelFileDescriptor);
     method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
   }
 
@@ -24423,23 +24812,31 @@
     method public final int getAssociationDesc();
     method public final int getAssociationType();
     method public final int getCompressedSize();
+    method public final long getCompressedSizeLong();
     method public final long getDateCreated();
     method public final long getDateModified();
     method public final int getFormat();
     method public final int getImagePixDepth();
+    method public final long getImagePixDepthLong();
     method public final int getImagePixHeight();
+    method public final long getImagePixHeightLong();
     method public final int getImagePixWidth();
+    method public final long getImagePixWidthLong();
     method public final java.lang.String getKeywords();
     method public final java.lang.String getName();
     method public final int getObjectHandle();
     method public final int getParent();
     method public final int getProtectionStatus();
     method public final int getSequenceNumber();
+    method public final long getSequenceNumberLong();
     method public final int getStorageId();
     method public final int getThumbCompressedSize();
+    method public final long getThumbCompressedSizeLong();
     method public final int getThumbFormat();
     method public final int getThumbPixHeight();
+    method public final long getThumbPixHeightLong();
     method public final int getThumbPixWidth();
+    method public final long getThumbPixWidthLong();
   }
 
   public static class MtpObjectInfo.Builder {
@@ -24448,24 +24845,24 @@
     method public android.mtp.MtpObjectInfo build();
     method public android.mtp.MtpObjectInfo.Builder setAssociationDesc(int);
     method public android.mtp.MtpObjectInfo.Builder setAssociationType(int);
-    method public android.mtp.MtpObjectInfo.Builder setCompressedSize(int);
+    method public android.mtp.MtpObjectInfo.Builder setCompressedSize(long);
     method public android.mtp.MtpObjectInfo.Builder setDateCreated(long);
     method public android.mtp.MtpObjectInfo.Builder setDateModified(long);
     method public android.mtp.MtpObjectInfo.Builder setFormat(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(int);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(long);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(long);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(long);
     method public android.mtp.MtpObjectInfo.Builder setKeywords(java.lang.String);
     method public android.mtp.MtpObjectInfo.Builder setName(java.lang.String);
     method public android.mtp.MtpObjectInfo.Builder setObjectHandle(int);
     method public android.mtp.MtpObjectInfo.Builder setParent(int);
     method public android.mtp.MtpObjectInfo.Builder setProtectionStatus(int);
-    method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(int);
+    method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(long);
     method public android.mtp.MtpObjectInfo.Builder setStorageId(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(int);
+    method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(long);
     method public android.mtp.MtpObjectInfo.Builder setThumbFormat(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(int);
+    method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(long);
+    method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(long);
   }
 
   public final class MtpStorageInfo {
@@ -29967,6 +30364,14 @@
     method public final synchronized android.os.CountDownTimer start();
   }
 
+  public final class CpuUsageInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getActive();
+    method public long getTotal();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.CpuUsageInfo> CREATOR;
+  }
+
   public class DeadObjectException extends android.os.RemoteException {
     ctor public DeadObjectException();
     ctor public DeadObjectException(java.lang.String);
@@ -30169,6 +30574,10 @@
     field public static final int OPEN = 32; // 0x20
   }
 
+  public class FileUriExposedException extends java.lang.RuntimeException {
+    ctor public FileUriExposedException(java.lang.String);
+  }
+
   public class Handler {
     ctor public Handler();
     ctor public Handler(android.os.Handler.Callback);
@@ -30219,6 +30628,18 @@
     method public boolean quitSafely();
   }
 
+  public class HardwarePropertiesManager {
+    method public android.os.CpuUsageInfo[] getCpuUsages();
+    method public float[] getDeviceTemperatures(int);
+    method public float[] getFanSpeeds();
+    field public static final int DEVICE_TEMPERATURE_BATTERY = 2; // 0x2
+    field public static final int DEVICE_TEMPERATURE_CPU = 0; // 0x0
+    field public static final int DEVICE_TEMPERATURE_GPU = 1; // 0x1
+  }
+
+  public static abstract class HardwarePropertiesManager.DeviceTemperatureType implements java.lang.annotation.Annotation {
+  }
+
   public abstract interface IBinder {
     method public abstract void dump(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
     method public abstract void dumpAsync(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
@@ -30591,6 +31012,7 @@
     field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+    field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
     field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
     field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
     field public static final int USER_ACTIVITY_EVENT_TOUCH = 2; // 0x2
@@ -30755,6 +31177,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
+    method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox();
     method public android.os.StrictMode.VmPolicy.Builder penaltyLog();
     method public android.os.StrictMode.VmPolicy.Builder setClassInstanceLimit(java.lang.Class, int);
@@ -30798,6 +31221,7 @@
     method public deprecated boolean isOwner();
     method public boolean isSystem();
     method public static int myUserId();
+    method public static android.os.UserHandle of(int);
     method public static android.os.UserHandle readFromParcel(android.os.Parcel);
     method public void writeToParcel(android.os.Parcel, int);
     method public static void writeToParcel(android.os.UserHandle, android.os.Parcel);
@@ -30812,6 +31236,7 @@
     method public android.os.PersistableBundle getSeedAccountOptions();
     method public java.lang.String getSeedAccountType();
     method public long getSerialNumberForUser(android.os.UserHandle);
+    method public long[] getSerialNumbersOfUsers(boolean);
     method public int getUserCount();
     method public long getUserCreationTime(android.os.UserHandle);
     method public android.os.UserHandle getUserForSerialNumber(long);
@@ -30870,6 +31295,8 @@
     field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
     field public static final java.lang.String ENSURE_VERIFY_APPS = "ensure_verify_apps";
     field public static final java.lang.String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
+    field public static final int USER_CREATION_FAILED_NOT_PERMITTED = 1; // 0x1
+    field public static final int USER_CREATION_FAILED_NO_MORE_USERS = 2; // 0x2
   }
 
   public abstract class Vibrator {
@@ -31227,6 +31654,9 @@
     method public static void setDefaultValues(android.content.Context, java.lang.String, int, int, boolean);
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
+    method public void setStorageCredentialEncrypted();
+    method public void setStorageDefault();
+    method public void setStorageDeviceEncrypted();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -33251,7 +33681,9 @@
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
     method public static java.lang.String getTreeDocumentId(android.net.Uri);
     method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
+    method public static boolean isTreeUri(android.net.Uri);
     method public static android.net.Uri moveDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri, android.net.Uri);
+    method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
     method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String);
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
@@ -33277,6 +33709,7 @@
     field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
     field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
+    field public static final int FLAG_SUPPORTS_REMOVE = 2048; // 0x800
     field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -33324,6 +33757,7 @@
     method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+    method public boolean removeDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String renameDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final void revokeDocumentPermission(java.lang.String);
     method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
@@ -33805,6 +34239,7 @@
     field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
     field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
+    field public static final java.lang.String ACTION_KEYBOARD_LAYOUT_SETTINGS = "android.settings.KEYBOARD_LAYOUT_SETTINGS";
     field public static final java.lang.String ACTION_LOCALE_SETTINGS = "android.settings.LOCALE_SETTINGS";
     field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
@@ -34467,6 +34902,7 @@
   public class VoicemailContract {
     field public static final java.lang.String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
     field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+    field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
     field public static final java.lang.String AUTHORITY = "com.android.voicemail";
     field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
     field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
@@ -34481,8 +34917,13 @@
     field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+    field public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3; // 0x3
+    field public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4; // 0x4
     field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+    field public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2; // 0x2
     field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6; // 0x6
+    field public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5; // 0x5
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
     field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
@@ -34580,6 +35021,7 @@
     method public void copyTo(short[]);
     method public void copyTo(int[]);
     method public void copyTo(float[]);
+    method public static android.renderscript.Allocation[] createAllocations(android.renderscript.RenderScript, android.renderscript.Type, int, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
     method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -34595,9 +35037,12 @@
     method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int);
     method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type);
     method public void generateMipmaps();
+    method public java.nio.ByteBuffer getByteBuffer();
     method public int getBytesSize();
     method public android.renderscript.Element getElement();
+    method public long getStride();
     method public android.view.Surface getSurface();
+    method public long getTimeStamp();
     method public android.renderscript.Type getType();
     method public int getUsage();
     method public void ioReceive();
@@ -36122,6 +36567,7 @@
     field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
     field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
     field public static final int REASON_TOPIC_BANNED = 14; // 0xe
     field public static final int REASON_USER_STOPPED = 6; // 0x6
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -37617,6 +38063,30 @@
     field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
   }
 
+  public abstract class CallScreeningService extends android.app.Service {
+    ctor public CallScreeningService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onScreenCall(android.telecom.Call.Details);
+    method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+  }
+
+  public static class CallScreeningService.CallResponse {
+    method public boolean getDisallowCall();
+    method public boolean getRejectCall();
+    method public boolean getSkipCallLog();
+    method public boolean getSkipNotification();
+  }
+
+  public static class CallScreeningService.CallResponse.Builder {
+    ctor public CallScreeningService.CallResponse.Builder();
+    method public android.telecom.CallScreeningService.CallResponse build();
+    method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+  }
+
   public abstract class Conference extends android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
@@ -37866,6 +38336,7 @@
     method public void onCanAddCallChanged(boolean);
     method public deprecated void onPhoneCreated(android.telecom.Phone);
     method public deprecated void onPhoneDestroyed(android.telecom.Phone);
+    method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -37947,6 +38418,7 @@
     method public void onCallAudioStateChanged(android.telecom.Phone, android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Phone, android.telecom.Call);
     method public void onCanAddCallChanged(android.telecom.Phone, boolean);
+    method public void onSilenceRinger(android.telecom.Phone);
   }
 
   public final class PhoneAccount implements android.os.Parcelable {
@@ -38206,6 +38678,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
     field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
@@ -38359,6 +38832,7 @@
     field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
     field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
     field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+    field public static final java.lang.String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
     field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
@@ -38376,6 +38850,8 @@
 
   public final class CellIdentityGsm implements android.os.Parcelable {
     method public int describeContents();
+    method public int getArfcn();
+    method public int getBsic();
     method public int getCid();
     method public int getLac();
     method public int getMcc();
@@ -38388,6 +38864,7 @@
   public final class CellIdentityLte implements android.os.Parcelable {
     method public int describeContents();
     method public int getCi();
+    method public int getEarfcn();
     method public int getMcc();
     method public int getMnc();
     method public int getPci();
@@ -38403,6 +38880,7 @@
     method public int getMcc();
     method public int getMnc();
     method public int getPsc();
+    method public int getUarfcn();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityWcdma> CREATOR;
   }
@@ -39133,7 +39611,7 @@
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
     ctor public deprecated ActivityInstrumentationTestCase2(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase2(java.lang.Class<T>);
     method public T getActivity();
@@ -39141,14 +39619,14 @@
     method public void setActivityIntent(android.content.Intent);
   }
 
-  public abstract class ActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class ActivityTestCase extends android.test.InstrumentationTestCase {
     ctor public ActivityTestCase();
     method protected android.app.Activity getActivity();
     method protected void scrubClass(java.lang.Class<?>) throws java.lang.IllegalAccessException;
     method protected void setActivity(android.app.Activity);
   }
 
-  public abstract class ActivityUnitTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityUnitTestCase extends android.test.ActivityTestCase {
     ctor public ActivityUnitTestCase(java.lang.Class<T>);
     method public T getActivity();
     method public int getFinishedActivityRequest();
@@ -39161,7 +39639,7 @@
     method protected T startActivity(android.content.Intent, android.os.Bundle, java.lang.Object);
   }
 
-  public class AndroidTestCase extends junit.framework.TestCase {
+  public deprecated class AndroidTestCase extends junit.framework.TestCase {
     ctor public AndroidTestCase();
     method public void assertActivityRequiresPermission(java.lang.String, java.lang.String, java.lang.String);
     method public void assertReadingContentUriRequiresPermission(android.net.Uri, java.lang.String);
@@ -39173,7 +39651,7 @@
     field protected android.content.Context mContext;
   }
 
-  public class AndroidTestRunner extends junit.runner.BaseTestRunner {
+  public deprecated class AndroidTestRunner extends junit.runner.BaseTestRunner {
     ctor public AndroidTestRunner();
     method public void addTestListener(junit.framework.TestListener);
     method public void clearTestListeners();
@@ -39194,7 +39672,7 @@
     method public void testStarted(java.lang.String);
   }
 
-  public abstract class ApplicationTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ApplicationTestCase extends android.test.AndroidTestCase {
     ctor public ApplicationTestCase(java.lang.Class<T>);
     method protected final void createApplication();
     method public T getApplication();
@@ -39212,10 +39690,10 @@
     ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String);
   }
 
-  public abstract class FlakyTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class FlakyTest implements java.lang.annotation.Annotation {
   }
 
-  public class InstrumentationTestCase extends junit.framework.TestCase {
+  public deprecated class InstrumentationTestCase extends junit.framework.TestCase {
     ctor public InstrumentationTestCase();
     method public android.app.Instrumentation getInstrumentation();
     method public deprecated void injectInsrumentation(android.app.Instrumentation);
@@ -39228,7 +39706,7 @@
     method public void sendRepeatedKeys(int...);
   }
 
-  public class InstrumentationTestRunner extends android.app.Instrumentation implements android.test.TestSuiteProvider {
+  public deprecated class InstrumentationTestRunner extends android.app.Instrumentation implements android.test.TestSuiteProvider {
     ctor public InstrumentationTestRunner();
     method public junit.framework.TestSuite getAllTests();
     method protected android.test.AndroidTestRunner getAndroidTestRunner();
@@ -39247,14 +39725,14 @@
     field public static final int REPORT_VALUE_RESULT_START = 1; // 0x1
   }
 
-  public class InstrumentationTestSuite extends junit.framework.TestSuite {
+  public deprecated class InstrumentationTestSuite extends junit.framework.TestSuite {
     ctor public InstrumentationTestSuite(android.app.Instrumentation);
     ctor public InstrumentationTestSuite(java.lang.String, android.app.Instrumentation);
     ctor public InstrumentationTestSuite(java.lang.Class, android.app.Instrumentation);
     method public void addTestSuite(java.lang.Class);
   }
 
-  public class IsolatedContext extends android.content.ContextWrapper {
+  public deprecated class IsolatedContext extends android.content.ContextWrapper {
     ctor public IsolatedContext(android.content.ContentResolver, android.content.Context);
     method public java.util.List<android.content.Intent> getAndClearBroadcastIntents();
   }
@@ -39264,7 +39742,7 @@
     method public T getLoaderResultSynchronously(android.content.Loader<T>);
   }
 
-  public final class MoreAsserts {
+  public final deprecated class MoreAsserts {
     method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Object);
     method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Class<?>);
     method public static java.util.regex.MatchResult assertContainsRegex(java.lang.String, java.lang.String, java.lang.String);
@@ -39303,7 +39781,7 @@
     method public static void checkEqualsAndHashCodeMethods(java.lang.Object, java.lang.Object, boolean);
   }
 
-  public abstract interface PerformanceTestCase {
+  public abstract deprecated interface PerformanceTestCase {
     method public abstract boolean isPerformanceOnly();
     method public abstract int startPerformance(android.test.PerformanceTestCase.Intermediates);
   }
@@ -39332,7 +39810,7 @@
     method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public class RenamingDelegatingContext extends android.content.ContextWrapper {
+  public deprecated class RenamingDelegatingContext extends android.content.ContextWrapper {
     ctor public RenamingDelegatingContext(android.content.Context, java.lang.String);
     ctor public RenamingDelegatingContext(android.content.Context, android.content.Context, java.lang.String);
     method public java.lang.String getDatabasePrefix();
@@ -39341,7 +39819,7 @@
     method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract class ServiceTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ServiceTestCase extends android.test.AndroidTestCase {
     ctor public ServiceTestCase(java.lang.Class<T>);
     method protected android.os.IBinder bindService(android.content.Intent);
     method public android.app.Application getApplication();
@@ -39354,23 +39832,23 @@
     method public void testServiceTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
     ctor public SingleLaunchActivityTestCase(java.lang.String, java.lang.Class<T>);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public class SyncBaseInstrumentation extends android.test.InstrumentationTestCase {
+  public deprecated class SyncBaseInstrumentation extends android.test.InstrumentationTestCase {
     ctor public SyncBaseInstrumentation();
     method protected void cancelSyncsandDisableAutoSync();
     method protected void syncProvider(android.net.Uri, java.lang.String, java.lang.String) throws java.lang.Exception;
   }
 
-  public abstract interface TestSuiteProvider {
+  public abstract deprecated interface TestSuiteProvider {
     method public abstract junit.framework.TestSuite getTestSuite();
   }
 
-  public class TouchUtils {
+  public deprecated class TouchUtils {
     ctor public TouchUtils();
     method public static void clickView(android.test.InstrumentationTestCase, android.view.View);
     method public static deprecated void drag(android.test.ActivityInstrumentationTestCase, float, float, float, float, int);
@@ -39405,10 +39883,10 @@
     method public static void touchAndCancelView(android.test.InstrumentationTestCase, android.view.View);
   }
 
-  public abstract class UiThreadTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class UiThreadTest implements java.lang.annotation.Annotation {
   }
 
-  public class ViewAsserts {
+  public deprecated class ViewAsserts {
     method public static void assertBaselineAligned(android.view.View, android.view.View);
     method public static void assertBottomAligned(android.view.View, android.view.View);
     method public static void assertBottomAligned(android.view.View, android.view.View, int);
@@ -39433,11 +39911,11 @@
 
 package android.test.mock {
 
-  public class MockApplication extends android.app.Application {
+  public deprecated class MockApplication extends android.app.Application {
     ctor public MockApplication();
   }
 
-  public class MockContentProvider extends android.content.ContentProvider {
+  public deprecated class MockContentProvider extends android.content.ContentProvider {
     ctor protected MockContentProvider();
     ctor public MockContentProvider(android.content.Context);
     ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
@@ -39449,13 +39927,13 @@
     method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
-  public class MockContentResolver extends android.content.ContentResolver {
+  public deprecated class MockContentResolver extends android.content.ContentResolver {
     ctor public MockContentResolver();
     ctor public MockContentResolver(android.content.Context);
     method public void addProvider(java.lang.String, android.content.ContentProvider);
   }
 
-  public class MockContext extends android.content.Context {
+  public deprecated class MockContext extends android.content.Context {
     ctor public MockContext();
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(java.lang.String);
@@ -39559,7 +40037,7 @@
     method public void unregisterReceiver(android.content.BroadcastReceiver);
   }
 
-  public class MockCursor implements android.database.Cursor {
+  public deprecated class MockCursor implements android.database.Cursor {
     ctor public MockCursor();
     method public void close();
     method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
@@ -39604,13 +40082,13 @@
     method public void unregisterDataSetObserver(android.database.DataSetObserver);
   }
 
-  public class MockDialogInterface implements android.content.DialogInterface {
+  public deprecated class MockDialogInterface implements android.content.DialogInterface {
     ctor public MockDialogInterface();
     method public void cancel();
     method public void dismiss();
   }
 
-  public class MockPackageManager extends android.content.pm.PackageManager {
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
     ctor public MockPackageManager();
     method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public void addPackageToPreferred(java.lang.String);
@@ -39704,7 +40182,7 @@
     method public void verifyPendingInstall(int, int);
   }
 
-  public class MockResources extends android.content.res.Resources {
+  public deprecated class MockResources extends android.content.res.Resources {
     ctor public MockResources();
   }
 
@@ -39745,19 +40223,19 @@
 
 package android.test.suitebuilder.annotation {
 
-  public abstract class LargeTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class LargeTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class MediumTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class MediumTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class SmallTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class SmallTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class Smoke implements java.lang.annotation.Annotation {
+  public abstract deprecated class Smoke implements java.lang.annotation.Annotation {
   }
 
-  public abstract class Suppress implements java.lang.annotation.Annotation {
+  public abstract deprecated class Suppress implements java.lang.annotation.Annotation {
   }
 
 }
@@ -51106,7 +51584,6 @@
     method public boolean setReadable(boolean);
     method public boolean setWritable(boolean, boolean);
     method public boolean setWritable(boolean);
-    method public java.nio.file.Path toPath();
     method public java.net.URI toURI();
     method public deprecated java.net.URL toURL() throws java.net.MalformedURLException;
     field public static final java.lang.String pathSeparator;
@@ -52659,6 +53136,9 @@
     field public static final java.lang.Class<java.lang.Float> TYPE;
   }
 
+  public abstract class FunctionalInterface implements java.lang.annotation.Annotation {
+  }
+
   public class IllegalAccessError extends java.lang.IncompatibleClassChangeError {
     ctor public IllegalAccessError();
     ctor public IllegalAccessError(java.lang.String);
@@ -53590,6 +54070,9 @@
   public abstract class Inherited implements java.lang.annotation.Annotation {
   }
 
+  public abstract class Repeatable implements java.lang.annotation.Annotation {
+  }
+
   public abstract class Retention implements java.lang.annotation.Annotation {
   }
 
@@ -55202,25 +55685,6 @@
     ctor public AsynchronousCloseException();
   }
 
-  public abstract class AsynchronousFileChannel implements java.nio.channels.AsynchronousChannel {
-    ctor protected AsynchronousFileChannel();
-    method public abstract void force(boolean) throws java.io.IOException;
-    method public abstract void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public final void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public abstract java.util.concurrent.Future<java.nio.channels.FileLock> lock(long, long, boolean);
-    method public final java.util.concurrent.Future<java.nio.channels.FileLock> lock();
-    method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer, long);
-    method public abstract long size() throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousFileChannel truncate(long) throws java.io.IOException;
-    method public abstract java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException;
-    method public final java.nio.channels.FileLock tryLock() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer, long);
-  }
-
   public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
     method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
@@ -55329,8 +55793,6 @@
     method public abstract java.nio.channels.FileLock lock(long, long, boolean) throws java.io.IOException;
     method public final java.nio.channels.FileLock lock() throws java.io.IOException;
     method public abstract java.nio.MappedByteBuffer map(java.nio.channels.FileChannel.MapMode, long, long) throws java.io.IOException;
-    method public static java.nio.channels.FileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.FileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
     method public abstract long position() throws java.io.IOException;
     method public abstract java.nio.channels.FileChannel position(long) throws java.io.IOException;
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
@@ -55357,7 +55819,6 @@
 
   public abstract class FileLock implements java.lang.AutoCloseable {
     ctor protected FileLock(java.nio.channels.FileChannel, long, long, boolean);
-    ctor protected FileLock(java.nio.channels.AsynchronousFileChannel, long, long, boolean);
     method public java.nio.channels.Channel acquiredBy();
     method public final java.nio.channels.FileChannel channel();
     method public final void close() throws java.io.IOException;
@@ -55807,592 +56268,6 @@
 
 }
 
-package java.nio.file {
-
-  public class AccessDeniedException extends java.nio.file.FileSystemException {
-    ctor public AccessDeniedException(java.lang.String);
-    ctor public AccessDeniedException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public final class AccessMode extends java.lang.Enum {
-    method public static java.nio.file.AccessMode valueOf(java.lang.String);
-    method public static final java.nio.file.AccessMode[] values();
-    enum_constant public static final java.nio.file.AccessMode EXECUTE;
-    enum_constant public static final java.nio.file.AccessMode READ;
-    enum_constant public static final java.nio.file.AccessMode WRITE;
-  }
-
-  public class AtomicMoveNotSupportedException extends java.nio.file.FileSystemException {
-    ctor public AtomicMoveNotSupportedException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public class ClosedDirectoryStreamException extends java.lang.IllegalStateException {
-    ctor public ClosedDirectoryStreamException();
-  }
-
-  public class ClosedFileSystemException extends java.lang.IllegalStateException {
-    ctor public ClosedFileSystemException();
-  }
-
-  public class ClosedWatchServiceException extends java.lang.IllegalStateException {
-    ctor public ClosedWatchServiceException();
-  }
-
-  public abstract interface CopyOption {
-  }
-
-  public final class DirectoryIteratorException extends java.util.ConcurrentModificationException {
-    ctor public DirectoryIteratorException(java.io.IOException);
-  }
-
-  public class DirectoryNotEmptyException extends java.nio.file.FileSystemException {
-    ctor public DirectoryNotEmptyException(java.lang.String);
-  }
-
-  public abstract interface DirectoryStream implements java.io.Closeable java.lang.Iterable {
-    method public abstract java.util.Iterator<T> iterator();
-  }
-
-  public static abstract interface DirectoryStream.Filter {
-    method public abstract boolean accept(T) throws java.io.IOException;
-  }
-
-  public class FileAlreadyExistsException extends java.nio.file.FileSystemException {
-    ctor public FileAlreadyExistsException(java.lang.String);
-    ctor public FileAlreadyExistsException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public abstract class FileStore {
-    ctor protected FileStore();
-    method public abstract java.lang.Object getAttribute(java.lang.String) throws java.io.IOException;
-    method public abstract V getFileStoreAttributeView(java.lang.Class<V>);
-    method public abstract long getTotalSpace() throws java.io.IOException;
-    method public abstract long getUnallocatedSpace() throws java.io.IOException;
-    method public abstract long getUsableSpace() throws java.io.IOException;
-    method public abstract boolean isReadOnly();
-    method public abstract java.lang.String name();
-    method public abstract boolean supportsFileAttributeView(java.lang.Class<? extends java.nio.file.attribute.FileAttributeView>);
-    method public abstract boolean supportsFileAttributeView(java.lang.String);
-    method public abstract java.lang.String type();
-  }
-
-  public abstract class FileSystem implements java.io.Closeable {
-    ctor protected FileSystem();
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.lang.Iterable<java.nio.file.FileStore> getFileStores();
-    method public abstract java.nio.file.Path getPath(java.lang.String, java.lang.String...);
-    method public abstract java.nio.file.PathMatcher getPathMatcher(java.lang.String);
-    method public abstract java.lang.Iterable<java.nio.file.Path> getRootDirectories();
-    method public abstract java.lang.String getSeparator();
-    method public abstract java.nio.file.attribute.UserPrincipalLookupService getUserPrincipalLookupService();
-    method public abstract boolean isOpen();
-    method public abstract boolean isReadOnly();
-    method public abstract java.nio.file.WatchService newWatchService() throws java.io.IOException;
-    method public abstract java.nio.file.spi.FileSystemProvider provider();
-    method public abstract java.util.Set<java.lang.String> supportedFileAttributeViews();
-  }
-
-  public class FileSystemAlreadyExistsException extends java.lang.RuntimeException {
-    ctor public FileSystemAlreadyExistsException();
-    ctor public FileSystemAlreadyExistsException(java.lang.String);
-  }
-
-  public class FileSystemException extends java.io.IOException {
-    ctor public FileSystemException(java.lang.String);
-    ctor public FileSystemException(java.lang.String, java.lang.String, java.lang.String);
-    method public java.lang.String getFile();
-    method public java.lang.String getOtherFile();
-    method public java.lang.String getReason();
-  }
-
-  public class FileSystemLoopException extends java.nio.file.FileSystemException {
-    ctor public FileSystemLoopException(java.lang.String);
-  }
-
-  public class FileSystemNotFoundException extends java.lang.RuntimeException {
-    ctor public FileSystemNotFoundException();
-    ctor public FileSystemNotFoundException(java.lang.String);
-  }
-
-  public final class FileSystems {
-    method public static java.nio.file.FileSystem getDefault();
-    method public static java.nio.file.FileSystem getFileSystem(java.net.URI);
-    method public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>, java.lang.ClassLoader) throws java.io.IOException;
-    method public static java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.lang.ClassLoader) throws java.io.IOException;
-  }
-
-  public final class FileVisitOption extends java.lang.Enum {
-    method public static java.nio.file.FileVisitOption valueOf(java.lang.String);
-    method public static final java.nio.file.FileVisitOption[] values();
-    enum_constant public static final java.nio.file.FileVisitOption FOLLOW_LINKS;
-  }
-
-  public final class FileVisitResult extends java.lang.Enum {
-    method public static java.nio.file.FileVisitResult valueOf(java.lang.String);
-    method public static final java.nio.file.FileVisitResult[] values();
-    enum_constant public static final java.nio.file.FileVisitResult CONTINUE;
-    enum_constant public static final java.nio.file.FileVisitResult SKIP_SIBLINGS;
-    enum_constant public static final java.nio.file.FileVisitResult SKIP_SUBTREE;
-    enum_constant public static final java.nio.file.FileVisitResult TERMINATE;
-  }
-
-  public abstract interface FileVisitor {
-    method public abstract java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult visitFile(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult visitFileFailed(T, java.io.IOException) throws java.io.IOException;
-  }
-
-  public final class Files {
-    method public static java.nio.file.Path copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static long copy(java.io.InputStream, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static long copy(java.nio.file.Path, java.io.OutputStream) throws java.io.IOException;
-    method public static java.nio.file.Path createDirectories(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createFile(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createLink(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempDirectory(java.nio.file.Path, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempDirectory(java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempFile(java.nio.file.Path, java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempFile(java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static void delete(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean exists(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public static java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.attribute.FileTime getLastModifiedTime(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.attribute.UserPrincipal getOwner(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.util.Set<java.nio.file.attribute.PosixFilePermission> getPosixFilePermissions(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static boolean isDirectory(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static boolean isExecutable(java.nio.file.Path);
-    method public static boolean isHidden(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean isReadable(java.nio.file.Path);
-    method public static boolean isRegularFile(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static boolean isSameFile(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public static boolean isSymbolicLink(java.nio.file.Path);
-    method public static boolean isWritable(java.nio.file.Path);
-    method public static java.nio.file.Path move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static java.io.BufferedReader newBufferedReader(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
-    method public static java.io.BufferedWriter newBufferedWriter(java.nio.file.Path, java.nio.charset.Charset, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.lang.String) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static boolean notExists(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static java.lang.String probeContentType(java.nio.file.Path) throws java.io.IOException;
-    method public static byte[] readAllBytes(java.nio.file.Path) throws java.io.IOException;
-    method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
-    method public static A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.Path setLastModifiedTime(java.nio.file.Path, java.nio.file.attribute.FileTime) throws java.io.IOException;
-    method public static java.nio.file.Path setOwner(java.nio.file.Path, java.nio.file.attribute.UserPrincipal) throws java.io.IOException;
-    method public static java.nio.file.Path setPosixFilePermissions(java.nio.file.Path, java.util.Set<java.nio.file.attribute.PosixFilePermission>) throws java.io.IOException;
-    method public static long size(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path walkFileTree(java.nio.file.Path, java.util.Set<java.nio.file.FileVisitOption>, int, java.nio.file.FileVisitor<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.nio.file.Path walkFileTree(java.nio.file.Path, java.nio.file.FileVisitor<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.nio.file.Path write(java.nio.file.Path, byte[], java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.file.Path write(java.nio.file.Path, java.lang.Iterable<? extends java.lang.CharSequence>, java.nio.charset.Charset, java.nio.file.OpenOption...) throws java.io.IOException;
-  }
-
-  public class InvalidPathException extends java.lang.IllegalArgumentException {
-    ctor public InvalidPathException(java.lang.String, java.lang.String, int);
-    ctor public InvalidPathException(java.lang.String, java.lang.String);
-    method public int getIndex();
-    method public java.lang.String getInput();
-    method public java.lang.String getReason();
-  }
-
-  public final class LinkOption extends java.lang.Enum implements java.nio.file.CopyOption java.nio.file.OpenOption {
-    method public static java.nio.file.LinkOption valueOf(java.lang.String);
-    method public static final java.nio.file.LinkOption[] values();
-    enum_constant public static final java.nio.file.LinkOption NOFOLLOW_LINKS;
-  }
-
-  public final class LinkPermission extends java.security.BasicPermission {
-    ctor public LinkPermission(java.lang.String);
-    ctor public LinkPermission(java.lang.String, java.lang.String);
-  }
-
-  public class NoSuchFileException extends java.nio.file.FileSystemException {
-    ctor public NoSuchFileException(java.lang.String);
-    ctor public NoSuchFileException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public class NotDirectoryException extends java.nio.file.FileSystemException {
-    ctor public NotDirectoryException(java.lang.String);
-  }
-
-  public class NotLinkException extends java.nio.file.FileSystemException {
-    ctor public NotLinkException(java.lang.String);
-    ctor public NotLinkException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public abstract interface OpenOption {
-  }
-
-  public abstract interface Path implements java.lang.Comparable java.lang.Iterable java.nio.file.Watchable {
-    method public abstract int compareTo(java.nio.file.Path);
-    method public abstract boolean endsWith(java.nio.file.Path);
-    method public abstract boolean endsWith(java.lang.String);
-    method public abstract boolean equals(java.lang.Object);
-    method public abstract java.nio.file.Path getFileName();
-    method public abstract java.nio.file.FileSystem getFileSystem();
-    method public abstract java.nio.file.Path getName(int);
-    method public abstract int getNameCount();
-    method public abstract java.nio.file.Path getParent();
-    method public abstract java.nio.file.Path getRoot();
-    method public abstract int hashCode();
-    method public abstract boolean isAbsolute();
-    method public abstract java.util.Iterator<java.nio.file.Path> iterator();
-    method public abstract java.nio.file.Path normalize();
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>[], java.nio.file.WatchEvent.Modifier...) throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.Path relativize(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolve(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolve(java.lang.String);
-    method public abstract java.nio.file.Path resolveSibling(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolveSibling(java.lang.String);
-    method public abstract boolean startsWith(java.nio.file.Path);
-    method public abstract boolean startsWith(java.lang.String);
-    method public abstract java.nio.file.Path subpath(int, int);
-    method public abstract java.nio.file.Path toAbsolutePath();
-    method public abstract java.io.File toFile();
-    method public abstract java.nio.file.Path toRealPath(java.nio.file.LinkOption...) throws java.io.IOException;
-    method public abstract java.lang.String toString();
-    method public abstract java.net.URI toUri();
-  }
-
-  public abstract interface PathMatcher {
-    method public abstract boolean matches(java.nio.file.Path);
-  }
-
-  public final class Paths {
-    method public static java.nio.file.Path get(java.lang.String, java.lang.String...);
-    method public static java.nio.file.Path get(java.net.URI);
-  }
-
-  public class ProviderMismatchException extends java.lang.IllegalArgumentException {
-    ctor public ProviderMismatchException();
-    ctor public ProviderMismatchException(java.lang.String);
-  }
-
-  public class ProviderNotFoundException extends java.lang.RuntimeException {
-    ctor public ProviderNotFoundException();
-    ctor public ProviderNotFoundException(java.lang.String);
-  }
-
-  public class ReadOnlyFileSystemException extends java.lang.UnsupportedOperationException {
-    ctor public ReadOnlyFileSystemException();
-  }
-
-  public abstract interface SecureDirectoryStream implements java.nio.file.DirectoryStream {
-    method public abstract void deleteDirectory(T) throws java.io.IOException;
-    method public abstract void deleteFile(T) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.lang.Class<V>);
-    method public abstract V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public abstract void move(T, java.nio.file.SecureDirectoryStream<T>, T) throws java.io.IOException;
-    method public abstract java.nio.channels.SeekableByteChannel newByteChannel(T, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.SecureDirectoryStream<T> newDirectoryStream(T, java.nio.file.LinkOption...) throws java.io.IOException;
-  }
-
-  public final class StandardCopyOption extends java.lang.Enum implements java.nio.file.CopyOption {
-    method public static java.nio.file.StandardCopyOption valueOf(java.lang.String);
-    method public static final java.nio.file.StandardCopyOption[] values();
-    enum_constant public static final java.nio.file.StandardCopyOption ATOMIC_MOVE;
-    enum_constant public static final java.nio.file.StandardCopyOption COPY_ATTRIBUTES;
-    enum_constant public static final java.nio.file.StandardCopyOption REPLACE_EXISTING;
-  }
-
-  public final class StandardOpenOption extends java.lang.Enum implements java.nio.file.OpenOption {
-    method public static java.nio.file.StandardOpenOption valueOf(java.lang.String);
-    method public static final java.nio.file.StandardOpenOption[] values();
-    enum_constant public static final java.nio.file.StandardOpenOption APPEND;
-    enum_constant public static final java.nio.file.StandardOpenOption CREATE;
-    enum_constant public static final java.nio.file.StandardOpenOption CREATE_NEW;
-    enum_constant public static final java.nio.file.StandardOpenOption DELETE_ON_CLOSE;
-    enum_constant public static final java.nio.file.StandardOpenOption DSYNC;
-    enum_constant public static final java.nio.file.StandardOpenOption READ;
-    enum_constant public static final java.nio.file.StandardOpenOption SPARSE;
-    enum_constant public static final java.nio.file.StandardOpenOption SYNC;
-    enum_constant public static final java.nio.file.StandardOpenOption TRUNCATE_EXISTING;
-    enum_constant public static final java.nio.file.StandardOpenOption WRITE;
-  }
-
-  public final class StandardWatchEventKinds {
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_CREATE;
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_DELETE;
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_MODIFY;
-    field public static final java.nio.file.WatchEvent.Kind<java.lang.Object> OVERFLOW;
-  }
-
-  public abstract interface WatchEvent {
-    method public abstract T context();
-    method public abstract int count();
-    method public abstract java.nio.file.WatchEvent.Kind<T> kind();
-  }
-
-  public static abstract interface WatchEvent.Kind {
-    method public abstract java.lang.String name();
-    method public abstract java.lang.Class<T> type();
-  }
-
-  public static abstract interface WatchEvent.Modifier {
-    method public abstract java.lang.String name();
-  }
-
-  public abstract interface WatchKey {
-    method public abstract void cancel();
-    method public abstract boolean isValid();
-    method public abstract java.util.List<java.nio.file.WatchEvent<?>> pollEvents();
-    method public abstract boolean reset();
-    method public abstract java.nio.file.Watchable watchable();
-  }
-
-  public abstract interface WatchService implements java.io.Closeable {
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey poll();
-    method public abstract java.nio.file.WatchKey poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract java.nio.file.WatchKey take() throws java.lang.InterruptedException;
-  }
-
-  public abstract interface Watchable {
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>[], java.nio.file.WatchEvent.Modifier...) throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>...) throws java.io.IOException;
-  }
-
-}
-
-package java.nio.file.attribute {
-
-  public final class AclEntry {
-    method public java.util.Set<java.nio.file.attribute.AclEntryFlag> flags();
-    method public static java.nio.file.attribute.AclEntry.Builder newBuilder();
-    method public static java.nio.file.attribute.AclEntry.Builder newBuilder(java.nio.file.attribute.AclEntry);
-    method public java.util.Set<java.nio.file.attribute.AclEntryPermission> permissions();
-    method public java.nio.file.attribute.UserPrincipal principal();
-    method public java.nio.file.attribute.AclEntryType type();
-  }
-
-  public static final class AclEntry.Builder {
-    method public java.nio.file.attribute.AclEntry build();
-    method public java.nio.file.attribute.AclEntry.Builder setFlags(java.util.Set<java.nio.file.attribute.AclEntryFlag>);
-    method public java.nio.file.attribute.AclEntry.Builder setFlags(java.nio.file.attribute.AclEntryFlag...);
-    method public java.nio.file.attribute.AclEntry.Builder setPermissions(java.util.Set<java.nio.file.attribute.AclEntryPermission>);
-    method public java.nio.file.attribute.AclEntry.Builder setPermissions(java.nio.file.attribute.AclEntryPermission...);
-    method public java.nio.file.attribute.AclEntry.Builder setPrincipal(java.nio.file.attribute.UserPrincipal);
-    method public java.nio.file.attribute.AclEntry.Builder setType(java.nio.file.attribute.AclEntryType);
-  }
-
-  public final class AclEntryFlag extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryFlag valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryFlag[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag DIRECTORY_INHERIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag FILE_INHERIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag INHERIT_ONLY;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag NO_PROPAGATE_INHERIT;
-  }
-
-  public final class AclEntryPermission extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryPermission valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryPermission[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission APPEND_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE_CHILD;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission EXECUTE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ACL;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ATTRIBUTES;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_NAMED_ATTRS;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission SYNCHRONIZE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ACL;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ATTRIBUTES;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_NAMED_ATTRS;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_OWNER;
-    field public static final java.nio.file.attribute.AclEntryPermission ADD_FILE;
-    field public static final java.nio.file.attribute.AclEntryPermission ADD_SUBDIRECTORY;
-    field public static final java.nio.file.attribute.AclEntryPermission LIST_DIRECTORY;
-  }
-
-  public final class AclEntryType extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryType valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryType[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryType ALARM;
-    enum_constant public static final java.nio.file.attribute.AclEntryType ALLOW;
-    enum_constant public static final java.nio.file.attribute.AclEntryType AUDIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryType DENY;
-  }
-
-  public abstract interface AclFileAttributeView implements java.nio.file.attribute.FileOwnerAttributeView {
-    method public abstract java.util.List<java.nio.file.attribute.AclEntry> getAcl() throws java.io.IOException;
-    method public abstract java.lang.String name();
-    method public abstract void setAcl(java.util.List<java.nio.file.attribute.AclEntry>) throws java.io.IOException;
-  }
-
-  public abstract interface AttributeView {
-    method public abstract java.lang.String name();
-  }
-
-  public abstract interface BasicFileAttributeView implements java.nio.file.attribute.FileAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.BasicFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setTimes(java.nio.file.attribute.FileTime, java.nio.file.attribute.FileTime, java.nio.file.attribute.FileTime) throws java.io.IOException;
-  }
-
-  public abstract interface BasicFileAttributes {
-    method public abstract java.nio.file.attribute.FileTime creationTime();
-    method public abstract java.lang.Object fileKey();
-    method public abstract boolean isDirectory();
-    method public abstract boolean isOther();
-    method public abstract boolean isRegularFile();
-    method public abstract boolean isSymbolicLink();
-    method public abstract java.nio.file.attribute.FileTime lastAccessTime();
-    method public abstract java.nio.file.attribute.FileTime lastModifiedTime();
-    method public abstract long size();
-  }
-
-  public abstract interface DosFileAttributeView implements java.nio.file.attribute.BasicFileAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.DosFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setArchive(boolean) throws java.io.IOException;
-    method public abstract void setHidden(boolean) throws java.io.IOException;
-    method public abstract void setReadOnly(boolean) throws java.io.IOException;
-    method public abstract void setSystem(boolean) throws java.io.IOException;
-  }
-
-  public abstract interface DosFileAttributes implements java.nio.file.attribute.BasicFileAttributes {
-    method public abstract boolean isArchive();
-    method public abstract boolean isHidden();
-    method public abstract boolean isReadOnly();
-    method public abstract boolean isSystem();
-  }
-
-  public abstract interface FileAttribute {
-    method public abstract java.lang.String name();
-    method public abstract T value();
-  }
-
-  public abstract interface FileAttributeView implements java.nio.file.attribute.AttributeView {
-  }
-
-  public abstract interface FileOwnerAttributeView implements java.nio.file.attribute.FileAttributeView {
-    method public abstract java.nio.file.attribute.UserPrincipal getOwner() throws java.io.IOException;
-    method public abstract java.lang.String name();
-    method public abstract void setOwner(java.nio.file.attribute.UserPrincipal) throws java.io.IOException;
-  }
-
-  public abstract interface FileStoreAttributeView implements java.nio.file.attribute.AttributeView {
-  }
-
-  public final class FileTime implements java.lang.Comparable {
-    method public int compareTo(java.nio.file.attribute.FileTime);
-    method public static java.nio.file.attribute.FileTime from(long, java.util.concurrent.TimeUnit);
-    method public static java.nio.file.attribute.FileTime fromMillis(long);
-    method public long to(java.util.concurrent.TimeUnit);
-    method public long toMillis();
-  }
-
-  public abstract interface GroupPrincipal implements java.nio.file.attribute.UserPrincipal {
-  }
-
-  public abstract interface PosixFileAttributeView implements java.nio.file.attribute.BasicFileAttributeView java.nio.file.attribute.FileOwnerAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.PosixFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setGroup(java.nio.file.attribute.GroupPrincipal) throws java.io.IOException;
-    method public abstract void setPermissions(java.util.Set<java.nio.file.attribute.PosixFilePermission>) throws java.io.IOException;
-  }
-
-  public abstract interface PosixFileAttributes implements java.nio.file.attribute.BasicFileAttributes {
-    method public abstract java.nio.file.attribute.GroupPrincipal group();
-    method public abstract java.nio.file.attribute.UserPrincipal owner();
-    method public abstract java.util.Set<java.nio.file.attribute.PosixFilePermission> permissions();
-  }
-
-  public final class PosixFilePermission extends java.lang.Enum {
-    method public static java.nio.file.attribute.PosixFilePermission valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.PosixFilePermission[] values();
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_WRITE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_WRITE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_WRITE;
-  }
-
-  public final class PosixFilePermissions {
-    method public static java.nio.file.attribute.FileAttribute<java.util.Set<java.nio.file.attribute.PosixFilePermission>> asFileAttribute(java.util.Set<java.nio.file.attribute.PosixFilePermission>);
-    method public static java.util.Set<java.nio.file.attribute.PosixFilePermission> fromString(java.lang.String);
-    method public static java.lang.String toString(java.util.Set<java.nio.file.attribute.PosixFilePermission>);
-  }
-
-  public abstract interface UserPrincipal implements java.security.Principal {
-  }
-
-  public abstract class UserPrincipalLookupService {
-    ctor protected UserPrincipalLookupService();
-    method public abstract java.nio.file.attribute.GroupPrincipal lookupPrincipalByGroupName(java.lang.String) throws java.io.IOException;
-    method public abstract java.nio.file.attribute.UserPrincipal lookupPrincipalByName(java.lang.String) throws java.io.IOException;
-  }
-
-  public class UserPrincipalNotFoundException extends java.io.IOException {
-    ctor public UserPrincipalNotFoundException(java.lang.String);
-    method public java.lang.String getName();
-  }
-
-}
-
-package java.nio.file.spi {
-
-  public abstract class FileSystemProvider {
-    ctor protected FileSystemProvider();
-    method public abstract void checkAccess(java.nio.file.Path, java.nio.file.AccessMode...) throws java.io.IOException;
-    method public abstract void copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public abstract void createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public void createLink(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public void createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract void delete(java.nio.file.Path) throws java.io.IOException;
-    method public boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public abstract java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
-    method public abstract java.nio.file.FileSystem getFileSystem(java.net.URI);
-    method public abstract java.nio.file.Path getPath(java.net.URI);
-    method public abstract java.lang.String getScheme();
-    method public static java.util.List<java.nio.file.spi.FileSystemProvider> installedProviders();
-    method public abstract boolean isHidden(java.nio.file.Path) throws java.io.IOException;
-    method public abstract boolean isSameFile(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public abstract void move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public java.nio.channels.AsynchronousFileChannel newAsynchronousFileChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) throws java.io.IOException;
-    method public java.nio.channels.FileChannel newFileChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public abstract java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
-    method public abstract void setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
-  }
-
-  public abstract class FileTypeDetector {
-    ctor protected FileTypeDetector();
-    method public abstract java.lang.String probeContentType(java.nio.file.Path) throws java.io.IOException;
-  }
-
-}
-
 package java.security {
 
   public final class AccessControlContext {
@@ -60989,8 +60864,6 @@
     ctor public Scanner(java.io.InputStream, java.lang.String);
     ctor public Scanner(java.io.File) throws java.io.FileNotFoundException;
     ctor public Scanner(java.io.File, java.lang.String) throws java.io.FileNotFoundException;
-    ctor public Scanner(java.nio.file.Path) throws java.io.IOException;
-    ctor public Scanner(java.nio.file.Path, java.lang.String) throws java.io.IOException;
     ctor public Scanner(java.lang.String);
     ctor public Scanner(java.nio.channels.ReadableByteChannel);
     ctor public Scanner(java.nio.channels.ReadableByteChannel, java.lang.String);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 90a5dc7..27de913 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -192,7 +192,7 @@
 
 package android.test.mock {
 
-  public class MockPackageManager extends android.content.pm.PackageManager {
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
     method public deprecated java.lang.String getDefaultBrowserPackageName(int);
     method public deprecated boolean setDefaultBrowserPackageName(java.lang.String, int);
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index e2ad761..d400113 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -33,6 +33,7 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -505,6 +506,8 @@
     field public static final int encryptionAware = 16844038; // 0x1010506
     field public static final int end = 16843996; // 0x10104dc
     field public static final int endColor = 16843166; // 0x101019e
+    field public static final int endX = 16844051; // 0x1010513
+    field public static final int endY = 16844052; // 0x1010514
     field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
     field public static final int entries = 16842930; // 0x10100b2
@@ -880,6 +883,7 @@
     field public static final int numbersTextColor = 16843937; // 0x10104a1
     field public static final deprecated int numeric = 16843109; // 0x1010165
     field public static final int numericShortcut = 16843236; // 0x10101e4
+    field public static final int offset = 16844053; // 0x1010515
     field public static final int onClick = 16843375; // 0x101026f
     field public static final int oneshot = 16843159; // 0x1010197
     field public static final int opacity = 16843550; // 0x101031e
@@ -1127,6 +1131,8 @@
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startDelay = 16843746; // 0x10103e2
     field public static final int startOffset = 16843198; // 0x10101be
+    field public static final int startX = 16844049; // 0x1010511
+    field public static final int startY = 16844050; // 0x1010512
     field public static final deprecated int startYear = 16843132; // 0x101017c
     field public static final int stateListAnimator = 16843848; // 0x1010448
     field public static final int stateNotNeeded = 16842774; // 0x1010016
@@ -4636,6 +4642,7 @@
     method public android.content.Context getContext();
     method public android.content.Context getTargetContext();
     method public android.app.UiAutomation getUiAutomation();
+    method public android.app.UiAutomation getUiAutomation(int);
     method public boolean invokeContextMenuAction(android.app.Activity, int, int);
     method public boolean invokeMenuActionSync(android.app.Activity, int, int);
     method public boolean isProfiling();
@@ -5532,6 +5539,7 @@
   public final class UiAutomation {
     method public void clearWindowAnimationFrameStats();
     method public boolean clearWindowContentFrameStats(int);
+    method public void destroy();
     method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
     method public android.os.ParcelFileDescriptor executeShellCommand(java.lang.String);
     method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
@@ -5550,6 +5558,7 @@
     method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
     method public android.graphics.Bitmap takeScreenshot();
     method public void waitForIdle(long, long) throws java.util.concurrent.TimeoutException;
+    field public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 1; // 0x1
     field public static final int ROTATION_FREEZE_0 = 0; // 0x0
     field public static final int ROTATION_FREEZE_180 = 2; // 0x2
     field public static final int ROTATION_FREEZE_270 = 3; // 0x3
@@ -5790,6 +5799,7 @@
     method public void clearCrossProfileIntentFilters(android.content.ComponentName);
     method public void clearDeviceOwnerApp(java.lang.String);
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
+    method public void clearProfileOwner(android.content.ComponentName);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
     method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
     method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
@@ -5816,6 +5826,7 @@
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
     method public long getMaximumTimeToLock(android.content.ComponentName);
     method public int getOrganizationColor(android.content.ComponentName);
+    method public java.lang.String getOrganizationName(android.content.ComponentName);
     method public boolean getPackageSuspended(android.content.ComponentName, java.lang.String);
     method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
     method public long getPasswordExpiration(android.content.ComponentName);
@@ -5885,6 +5896,7 @@
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setOrganizationColor(android.content.ComponentName, int);
+    method public void setOrganizationName(android.content.ComponentName, java.lang.String);
     method public boolean setPackageSuspended(android.content.ComponentName, java.lang.String, boolean);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
     method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -6511,8 +6523,9 @@
     field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
     field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
     field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_DEVICE_LOCKED = 210007; // 0x33457
-    field public static final int TAG_DEVICE_UNLOCK_ATTEMPT = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
     field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
     field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
   }
@@ -8041,6 +8054,7 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
+    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
     field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler";
@@ -9954,7 +9968,7 @@
     method public final long skip(long) throws java.io.IOException;
   }
 
-  public class ColorStateList implements android.os.Parcelable {
+  public class ColorStateList extends android.content.res.ComplexColor implements android.os.Parcelable {
     ctor public ColorStateList(int[][], int[]);
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
@@ -9963,13 +9977,18 @@
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
-    method public boolean isStateful();
     method public static android.content.res.ColorStateList valueOf(int);
     method public android.content.res.ColorStateList withAlpha(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR;
   }
 
+  public abstract class ComplexColor {
+    ctor public ComplexColor();
+    method public abstract int getDefaultColor();
+    method public boolean isStateful();
+  }
+
   public final class Configuration implements java.lang.Comparable android.os.Parcelable {
     ctor public Configuration();
     ctor public Configuration(android.content.res.Configuration);
@@ -10073,6 +10092,11 @@
     field public int uiMode;
   }
 
+  public class GradientColor extends android.content.res.ComplexColor {
+    method public static android.content.res.GradientColor createFromXml(android.content.res.Resources, android.content.res.XmlResourceParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public int getDefaultColor();
+  }
+
   public class ObbInfo implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10132,6 +10156,7 @@
     method public void getValue(java.lang.String, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
     method public void getValueForDensity(int, int, android.util.TypedValue, boolean) throws android.content.res.Resources.NotFoundException;
     method public android.content.res.XmlResourceParser getXml(int) throws android.content.res.Resources.NotFoundException;
+    method public android.content.res.ComplexColor loadComplexColor(android.util.TypedValue, int, android.content.res.Resources.Theme);
     method public final android.content.res.Resources.Theme newTheme();
     method public android.content.res.TypedArray obtainAttributes(android.util.AttributeSet, int[]);
     method public android.content.res.TypedArray obtainTypedArray(int) throws android.content.res.Resources.NotFoundException;
@@ -10167,6 +10192,7 @@
     method public int getChangingConfigurations();
     method public int getColor(int, int);
     method public android.content.res.ColorStateList getColorStateList(int);
+    method public android.content.res.ComplexColor getComplexColor(int);
     method public float getDimension(int, float);
     method public int getDimensionPixelOffset(int, int);
     method public int getDimensionPixelSize(int, int);
@@ -13363,6 +13389,7 @@
     method public float getResolution();
     method public java.lang.String getStringType();
     method public int getType();
+    method public java.util.UUID getUuid();
     method public java.lang.String getVendor();
     method public int getVersion();
     method public boolean isWakeUpSensor();
@@ -13377,11 +13404,13 @@
     field public static final java.lang.String STRING_TYPE_GRAVITY = "android.sensor.gravity";
     field public static final java.lang.String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
     field public static final java.lang.String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
+    field public static final java.lang.String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
     field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
     field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
     field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
     field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
+    field public static final java.lang.String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
     field public static final deprecated java.lang.String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
     field public static final java.lang.String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
     field public static final java.lang.String STRING_TYPE_PRESSURE = "android.sensor.pressure";
@@ -13389,6 +13418,7 @@
     field public static final java.lang.String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
     field public static final java.lang.String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
     field public static final java.lang.String STRING_TYPE_SIGNIFICANT_MOTION = "android.sensor.significant_motion";
+    field public static final java.lang.String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
     field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
     field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
     field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
@@ -13400,11 +13430,13 @@
     field public static final int TYPE_GRAVITY = 9; // 0x9
     field public static final int TYPE_GYROSCOPE = 4; // 0x4
     field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
+    field public static final int TYPE_HEART_BEAT = 31; // 0x1f
     field public static final int TYPE_HEART_RATE = 21; // 0x15
     field public static final int TYPE_LIGHT = 5; // 0x5
     field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
     field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
     field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
+    field public static final int TYPE_MOTION_DETECT = 30; // 0x1e
     field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
     field public static final int TYPE_POSE_6DOF = 28; // 0x1c
     field public static final int TYPE_PRESSURE = 6; // 0x6
@@ -13412,11 +13444,27 @@
     field public static final int TYPE_RELATIVE_HUMIDITY = 12; // 0xc
     field public static final int TYPE_ROTATION_VECTOR = 11; // 0xb
     field public static final int TYPE_SIGNIFICANT_MOTION = 17; // 0x11
+    field public static final int TYPE_STATIONARY_DETECT = 29; // 0x1d
     field public static final int TYPE_STEP_COUNTER = 19; // 0x13
     field public static final int TYPE_STEP_DETECTOR = 18; // 0x12
     field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
   }
 
+  public class SensorAdditionalInfo {
+    field public static final int TYPE_FRAME_BEGIN = 0; // 0x0
+    field public static final int TYPE_FRAME_END = 1; // 0x1
+    field public static final int TYPE_INTERNAL_TEMPERATURE = 65537; // 0x10001
+    field public static final int TYPE_SAMPLING = 65540; // 0x10004
+    field public static final int TYPE_SENSOR_PLACEMENT = 65539; // 0x10003
+    field public static final int TYPE_UNTRACKED_DELAY = 65536; // 0x10000
+    field public static final int TYPE_VEC3_CALIBRATION = 65538; // 0x10002
+    field public final float[] floatValues;
+    field public final int[] intValues;
+    field public final android.hardware.Sensor sensor;
+    field public final int serial;
+    field public final int type;
+  }
+
   public class SensorEvent {
     field public int accuracy;
     field public android.hardware.Sensor sensor;
@@ -13424,6 +13472,14 @@
     field public final float[] values;
   }
 
+  public abstract class SensorEventCallback implements android.hardware.SensorEventListener2 {
+    ctor public SensorEventCallback();
+    method public void onAccuracyChanged(android.hardware.Sensor, int);
+    method public void onFlushCompleted(android.hardware.Sensor);
+    method public void onSensorAdditionalInfo(android.hardware.SensorAdditionalInfo);
+    method public void onSensorChanged(android.hardware.SensorEvent);
+  }
+
   public abstract interface SensorEventListener {
     method public abstract void onAccuracyChanged(android.hardware.Sensor, int);
     method public abstract void onSensorChanged(android.hardware.SensorEvent);
@@ -13445,6 +13501,7 @@
     method public static void getAngleChange(float[], float[], float[]);
     method public android.hardware.Sensor getDefaultSensor(int);
     method public android.hardware.Sensor getDefaultSensor(int, boolean);
+    method public java.util.List<android.hardware.Sensor> getDynamicSensorList(int);
     method public static float getInclination(float[]);
     method public static float[] getOrientation(float[], float[]);
     method public static void getQuaternionFromVector(float[], float[]);
@@ -13452,6 +13509,8 @@
     method public static void getRotationMatrixFromVector(float[], float[]);
     method public java.util.List<android.hardware.Sensor> getSensorList(int);
     method public deprecated int getSensors();
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
+    method public void registerDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback, android.os.Handler);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int);
     method public deprecated boolean registerListener(android.hardware.SensorListener, int, int);
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int);
@@ -13460,6 +13519,7 @@
     method public boolean registerListener(android.hardware.SensorEventListener, android.hardware.Sensor, int, int, android.os.Handler);
     method public static boolean remapCoordinateSystem(float[], int, int, float[]);
     method public boolean requestTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+    method public void unregisterDynamicSensorCallback(android.hardware.SensorManager.DynamicSensorConnectionCallback);
     method public deprecated void unregisterListener(android.hardware.SensorListener);
     method public deprecated void unregisterListener(android.hardware.SensorListener, int);
     method public void unregisterListener(android.hardware.SensorEventListener, android.hardware.Sensor);
@@ -13524,6 +13584,12 @@
     field public static final float STANDARD_GRAVITY = 9.80665f;
   }
 
+  public static abstract class SensorManager.DynamicSensorConnectionCallback {
+    ctor public SensorManager.DynamicSensorConnectionCallback();
+    method public void onDynamicSensorConnected(android.hardware.Sensor);
+    method public void onDynamicSensorDisconnected(android.hardware.Sensor);
+  }
+
   public final class TriggerEvent {
     field public android.hardware.Sensor sensor;
     field public long timestamp;
@@ -19024,6 +19090,288 @@
     method public static boolean isPresent();
   }
 
+  public abstract interface GnssNmeaListener {
+    method public abstract void onNmeaReceived(long, java.lang.String);
+  }
+
+  public final class GnssStatus {
+    method public float getAzimuth(int);
+    method public int getConstellationType(int);
+    method public float getElevation(int);
+    method public int getNumSatellites();
+    method public int getPrn(int);
+    method public float getSnr(int);
+    method public boolean hasAlmanac(int);
+    method public boolean hasEphemeris(int);
+    method public boolean usedInFix(int);
+    field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+    field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+    field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+    field public static final int CONSTELLATION_GPS = 1; // 0x1
+    field public static final int CONSTELLATION_QZSS = 4; // 0x4
+    field public static final int CONSTELLATION_SBAS = 2; // 0x2
+    field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
+  }
+
+  public abstract class GnssStatusCallback {
+    ctor public GnssStatusCallback();
+    method public void onFirstFix(int);
+    method public void onSatelliteStatusChanged(android.location.GnssStatus);
+    method public void onStarted();
+    method public void onStopped();
+  }
+
+  public final class GpsClock implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getBiasInNs();
+    method public double getBiasUncertaintyInNs();
+    method public double getDriftInNsPerSec();
+    method public double getDriftUncertaintyInNsPerSec();
+    method public long getFullBiasInNs();
+    method public short getLeapSecond();
+    method public long getTimeInNs();
+    method public long getTimeOfLastHwClockDiscontinuityInNs();
+    method public double getTimeUncertaintyInNs();
+    method public byte getType();
+    method public boolean hasBiasInNs();
+    method public boolean hasBiasUncertaintyInNs();
+    method public boolean hasDriftInNsPerSec();
+    method public boolean hasDriftUncertaintyInNsPerSec();
+    method public boolean hasFullBiasInNs();
+    method public boolean hasLeapSecond();
+    method public boolean hasTimeUncertaintyInNs();
+    method public void reset();
+    method public void resetBiasInNs();
+    method public void resetBiasUncertaintyInNs();
+    method public void resetDriftInNsPerSec();
+    method public void resetDriftUncertaintyInNsPerSec();
+    method public void resetFullBiasInNs();
+    method public void resetLeapSecond();
+    method public void resetTimeUncertaintyInNs();
+    method public void set(android.location.GpsClock);
+    method public void setBiasInNs(double);
+    method public void setBiasUncertaintyInNs(double);
+    method public void setDriftInNsPerSec(double);
+    method public void setDriftUncertaintyInNsPerSec(double);
+    method public void setFullBiasInNs(long);
+    method public void setLeapSecond(short);
+    method public void setTimeInNs(long);
+    method public void setTimeOfLastHwClockDiscontinuityInNs(long);
+    method public void setTimeUncertaintyInNs(double);
+    method public void setType(byte);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final byte CLOCK_TYPE_GPS_TIME = 2; // 0x2
+    field public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1; // 0x1
+    field public static final byte CLOCK_TYPE_UNKNOWN = 0; // 0x0
+    field public static final android.os.Parcelable.Creator<android.location.GpsClock> CREATOR;
+  }
+
+  public static abstract class GpsClock.GpsClockType implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsMeasurement implements android.os.Parcelable {
+    method public int describeContents();
+    method public double getAccumulatedDeltaRangeInMeters();
+    method public short getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyInMeters();
+    method public double getAzimuthInDeg();
+    method public double getAzimuthUncertaintyInDeg();
+    method public int getBitNumber();
+    method public long getCarrierCycles();
+    method public float getCarrierFrequencyInHz();
+    method public double getCarrierPhase();
+    method public double getCarrierPhaseUncertainty();
+    method public double getCn0InDbHz();
+    method public double getCodePhaseInChips();
+    method public double getCodePhaseUncertaintyInChips();
+    method public double getDopplerShiftInHz();
+    method public double getDopplerShiftUncertaintyInHz();
+    method public double getElevationInDeg();
+    method public double getElevationUncertaintyInDeg();
+    method public byte getLossOfLock();
+    method public byte getMultipathIndicator();
+    method public byte getPrn();
+    method public double getPseudorangeInMeters();
+    method public double getPseudorangeRateCarrierInMetersPerSec();
+    method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
+    method public double getPseudorangeRateInMetersPerSec();
+    method public double getPseudorangeRateUncertaintyInMetersPerSec();
+    method public double getPseudorangeUncertaintyInMeters();
+    method public long getReceivedGpsTowInNs();
+    method public long getReceivedGpsTowUncertaintyInNs();
+    method public double getSnrInDb();
+    method public short getState();
+    method public short getTimeFromLastBitInMs();
+    method public double getTimeOffsetInNs();
+    method public boolean hasAzimuthInDeg();
+    method public boolean hasAzimuthUncertaintyInDeg();
+    method public boolean hasBitNumber();
+    method public boolean hasCarrierCycles();
+    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierPhase();
+    method public boolean hasCarrierPhaseUncertainty();
+    method public boolean hasCodePhaseInChips();
+    method public boolean hasCodePhaseUncertaintyInChips();
+    method public boolean hasDopplerShiftInHz();
+    method public boolean hasDopplerShiftUncertaintyInHz();
+    method public boolean hasElevationInDeg();
+    method public boolean hasElevationUncertaintyInDeg();
+    method public boolean hasPseudorangeInMeters();
+    method public boolean hasPseudorangeUncertaintyInMeters();
+    method public boolean hasSnrInDb();
+    method public boolean hasTimeFromLastBitInMs();
+    method public boolean isPseudorangeRateCorrected();
+    method public boolean isUsedInFix();
+    method public void reset();
+    method public void resetAzimuthInDeg();
+    method public void resetAzimuthUncertaintyInDeg();
+    method public void resetBitNumber();
+    method public void resetCarrierCycles();
+    method public void resetCarrierFrequencyInHz();
+    method public void resetCarrierPhase();
+    method public void resetCarrierPhaseUncertainty();
+    method public void resetCodePhaseInChips();
+    method public void resetCodePhaseUncertaintyInChips();
+    method public void resetDopplerShiftInHz();
+    method public void resetDopplerShiftUncertaintyInHz();
+    method public void resetElevationInDeg();
+    method public void resetElevationUncertaintyInDeg();
+    method public void resetPseudorangeInMeters();
+    method public void resetPseudorangeUncertaintyInMeters();
+    method public void resetSnrInDb();
+    method public void resetTimeFromLastBitInMs();
+    method public void set(android.location.GpsMeasurement);
+    method public void setAccumulatedDeltaRangeInMeters(double);
+    method public void setAccumulatedDeltaRangeState(short);
+    method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
+    method public void setAzimuthInDeg(double);
+    method public void setAzimuthUncertaintyInDeg(double);
+    method public void setBitNumber(int);
+    method public void setCarrierCycles(long);
+    method public void setCarrierFrequencyInHz(float);
+    method public void setCarrierPhase(double);
+    method public void setCarrierPhaseUncertainty(double);
+    method public void setCn0InDbHz(double);
+    method public void setCodePhaseInChips(double);
+    method public void setCodePhaseUncertaintyInChips(double);
+    method public void setDopplerShiftInHz(double);
+    method public void setDopplerShiftUncertaintyInHz(double);
+    method public void setElevationInDeg(double);
+    method public void setElevationUncertaintyInDeg(double);
+    method public void setLossOfLock(byte);
+    method public void setMultipathIndicator(byte);
+    method public void setPrn(byte);
+    method public void setPseudorangeInMeters(double);
+    method public void setPseudorangeRateCarrierInMetersPerSec(double);
+    method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
+    method public void setPseudorangeRateInMetersPerSec(double);
+    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
+    method public void setPseudorangeUncertaintyInMeters(double);
+    method public void setReceivedGpsTowInNs(long);
+    method public void setReceivedGpsTowUncertaintyInNs(long);
+    method public void setSnrInDb(double);
+    method public void setState(short);
+    method public void setTimeFromLastBitInMs(short);
+    method public void setTimeOffsetInNs(double);
+    method public void setUsedInFix(boolean);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final short ADR_STATE_RESET = 2; // 0x2
+    field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final short ADR_STATE_VALID = 1; // 0x1
+    field public static final android.os.Parcelable.Creator<android.location.GpsMeasurement> CREATOR;
+    field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
+    field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
+    field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
+    field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final short STATE_BIT_SYNC = 2; // 0x2
+    field public static final short STATE_CODE_LOCK = 1; // 0x1
+    field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final short STATE_TOW_DECODED = 8; // 0x8
+    field public static final short STATE_UNKNOWN = 0; // 0x0
+  }
+
+  public static abstract class GpsMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class GpsMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsMeasurementsEvent implements android.os.Parcelable {
+    ctor public GpsMeasurementsEvent(android.location.GpsClock, android.location.GpsMeasurement[]);
+    method public int describeContents();
+    method public android.location.GpsClock getClock();
+    method public java.util.Collection<android.location.GpsMeasurement> getMeasurements();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GpsMeasurementsEvent> CREATOR;
+    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
+  }
+
+  public static abstract class GpsMeasurementsEvent.Callback {
+    ctor public GpsMeasurementsEvent.Callback();
+    method public void onGpsMeasurementsReceived(android.location.GpsMeasurementsEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public static abstract class GpsMeasurementsEvent.GpsMeasurementsStatus implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsNavigationMessage implements android.os.Parcelable {
+    method public int describeContents();
+    method public byte[] getData();
+    method public short getMessageId();
+    method public byte getPrn();
+    method public short getStatus();
+    method public short getSubmessageId();
+    method public byte getType();
+    method public void reset();
+    method public void set(android.location.GpsNavigationMessage);
+    method public void setData(byte[]);
+    method public void setMessageId(short);
+    method public void setPrn(byte);
+    method public void setStatus(short);
+    method public void setSubmessageId(short);
+    method public void setType(byte);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessage> CREATOR;
+    field public static final byte MESSAGE_TYPE_CNAV2 = 4; // 0x4
+    field public static final byte MESSAGE_TYPE_L1CA = 1; // 0x1
+    field public static final byte MESSAGE_TYPE_L2CNAV = 2; // 0x2
+    field public static final byte MESSAGE_TYPE_L5CNAV = 3; // 0x3
+    field public static final byte MESSAGE_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final short STATUS_UNKNOWN = 0; // 0x0
+  }
+
+  public static abstract class GpsNavigationMessage.GpsNavigationMessageType implements java.lang.annotation.Annotation {
+  }
+
+  public final class GpsNavigationMessageEvent implements android.os.Parcelable {
+    ctor public GpsNavigationMessageEvent(android.location.GpsNavigationMessage);
+    method public int describeContents();
+    method public android.location.GpsNavigationMessage getNavigationMessage();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.location.GpsNavigationMessageEvent> CREATOR;
+    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+    field public static final int STATUS_READY = 1; // 0x1
+  }
+
+  public static abstract class GpsNavigationMessageEvent.Callback {
+    ctor public GpsNavigationMessageEvent.Callback();
+    method public void onGpsNavigationMessageReceived(android.location.GpsNavigationMessageEvent);
+    method public void onStatusChanged(int);
+  }
+
+  public static abstract class GpsNavigationMessageEvent.GpsNavigationMessageStatus implements java.lang.annotation.Annotation {
+  }
+
   public final class GpsSatellite {
     method public float getAzimuth();
     method public float getElevation();
@@ -19108,8 +19456,10 @@
   }
 
   public class LocationManager {
-    method public boolean addGpsStatusListener(android.location.GpsStatus.Listener);
-    method public boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
+    method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener);
+    method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
     method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
     method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
     method public void clearTestProviderEnabled(java.lang.String);
@@ -19117,14 +19467,22 @@
     method public void clearTestProviderStatus(java.lang.String);
     method public java.util.List<java.lang.String> getAllProviders();
     method public java.lang.String getBestProvider(android.location.Criteria, boolean);
-    method public android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
+    method public deprecated android.location.GpsStatus getGpsStatus(android.location.GpsStatus);
+    method public int getGpsYearOfHardware();
     method public android.location.Location getLastKnownLocation(java.lang.String);
     method public android.location.LocationProvider getProvider(java.lang.String);
     method public java.util.List<java.lang.String> getProviders(boolean);
     method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
     method public boolean isProviderEnabled(java.lang.String);
-    method public void removeGpsStatusListener(android.location.GpsStatus.Listener);
-    method public void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
+    method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
+    method public boolean registerGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
+    method public boolean registerGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback, android.os.Handler);
+    method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
+    method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
+    method public void removeNmeaListener(android.location.GnssNmeaListener);
     method public void removeProximityAlert(android.app.PendingIntent);
     method public void removeTestProvider(java.lang.String);
     method public void removeUpdates(android.location.LocationListener);
@@ -19142,6 +19500,9 @@
     method public void setTestProviderEnabled(java.lang.String, boolean);
     method public void setTestProviderLocation(java.lang.String, android.location.Location);
     method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
+    method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+    method public void unregisterGpsMeasurementCallback(android.location.GpsMeasurementsEvent.Callback);
+    method public void unregisterGpsNavigationMessageCallback(android.location.GpsNavigationMessageEvent.Callback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
     field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
     field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -19208,6 +19569,7 @@
     field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
     field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
     field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
+    field public static final int FLAG_LOW_LATENCY = 256; // 0x100
     field public static final int USAGE_ALARM = 4; // 0x4
     field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
     field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -19327,6 +19689,7 @@
     field public static final int ENCODING_DTS = 7; // 0x7
     field public static final int ENCODING_DTS_HD = 8; // 0x8
     field public static final int ENCODING_E_AC3 = 6; // 0x6
+    field public static final int ENCODING_IEC61937 = 13; // 0xd
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
     field public static final int ENCODING_PCM_8BIT = 3; // 0x3
@@ -19522,6 +19885,7 @@
     method public android.media.AudioDeviceInfo getRoutedDevice();
     method public int getSampleRate();
     method public int getState();
+    method public int getTimestamp(android.media.AudioTimestamp, int);
     method public int read(byte[], int, int);
     method public int read(byte[], int, int, int);
     method public int read(short[], int, int);
@@ -19571,8 +19935,11 @@
 
   public class AudioRecordConfiguration implements android.os.Parcelable {
     method public int describeContents();
-    method public int getAudioSessionId();
+    method public android.media.AudioDeviceInfo getAudioDevice();
+    method public int getClientAudioSessionId();
     method public int getClientAudioSource();
+    method public android.media.AudioFormat getClientFormat();
+    method public android.media.AudioFormat getFormat();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.media.AudioRecordConfiguration> CREATOR;
   }
@@ -19590,6 +19957,8 @@
 
   public final class AudioTimestamp {
     ctor public AudioTimestamp();
+    field public static final int TIMEBASE_BOOTTIME = 1; // 0x1
+    field public static final int TIMEBASE_MONOTONIC = 0; // 0x0
     field public long framePosition;
     field public long nanoTime;
   }
@@ -19604,6 +19973,7 @@
     method public void flush();
     method public int getAudioFormat();
     method public int getAudioSessionId();
+    method public int getBufferCapacityInFrames();
     method public int getBufferSizeInFrames();
     method public int getChannelConfiguration();
     method public int getChannelCount();
@@ -19625,6 +19995,7 @@
     method public int getState();
     method public int getStreamType();
     method public boolean getTimestamp(android.media.AudioTimestamp);
+    method public int getUnderrunCount();
     method public void pause() throws java.lang.IllegalStateException;
     method public void play() throws java.lang.IllegalStateException;
     method public void release();
@@ -19632,6 +20003,7 @@
     method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
     method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
     method public int setAuxEffectSendLevel(float);
+    method public int setBufferSizeInFrames(int);
     method public int setLoopPoints(int, int, int);
     method public int setNotificationMarkerPosition(int);
     method public int setPlaybackHeadPosition(int);
@@ -19743,6 +20115,16 @@
     ctor public DeniedByServerException(java.lang.String);
   }
 
+  public abstract class DrmInitData {
+    ctor public DrmInitData();
+    method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
+  }
+
+  public static final class DrmInitData.SchemeInitData {
+    field public final byte[] data;
+    field public final java.lang.String mimeType;
+  }
+
   public class ExifInterface {
     ctor public ExifInterface(java.lang.String) throws java.io.IOException;
     method public double getAltitude(double);
@@ -20090,6 +20472,7 @@
     field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
     field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+    field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
     field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
     field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
     field public int[] colorFormats;
@@ -20132,6 +20515,21 @@
     field public static final int AVCProfileHigh422 = 32; // 0x20
     field public static final int AVCProfileHigh444 = 64; // 0x40
     field public static final int AVCProfileMain = 2; // 0x2
+    field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
+    field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
+    field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
+    field public static final int DolbyVisionLevelHd24 = 1; // 0x1
+    field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+    field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
+    field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
+    field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
+    field public static final int DolbyVisionLevelUhd60 = 256; // 0x100
+    field public static final int DolbyVisionProfileDvavDen = 2; // 0x2
+    field public static final int DolbyVisionProfileDvavDer = 1; // 0x1
+    field public static final int DolbyVisionProfileDvheDen = 4; // 0x4
+    field public static final int DolbyVisionProfileDvheDer = 3; // 0x3
+    field public static final int DolbyVisionProfileDvheDtr = 5; // 0x5
+    field public static final int DolbyVisionProfileDvheStn = 6; // 0x6
     field public static final int H263Level10 = 1; // 0x1
     field public static final int H263Level20 = 2; // 0x2
     field public static final int H263Level30 = 4; // 0x4
@@ -20216,6 +20614,24 @@
     field public static final int VP8Level_Version2 = 4; // 0x4
     field public static final int VP8Level_Version3 = 8; // 0x8
     field public static final int VP8ProfileMain = 1; // 0x1
+    field public static final int VP9Level1 = 0; // 0x0
+    field public static final int VP9Level11 = 1; // 0x1
+    field public static final int VP9Level2 = 2; // 0x2
+    field public static final int VP9Level21 = 4; // 0x4
+    field public static final int VP9Level3 = 8; // 0x8
+    field public static final int VP9Level31 = 16; // 0x10
+    field public static final int VP9Level4 = 32; // 0x20
+    field public static final int VP9Level41 = 64; // 0x40
+    field public static final int VP9Level5 = 128; // 0x80
+    field public static final int VP9Level51 = 256; // 0x100
+    field public static final int VP9Level52 = 512; // 0x200
+    field public static final int VP9Level6 = 1024; // 0x400
+    field public static final int VP9Level61 = 2048; // 0x800
+    field public static final int VP9Level62 = 4096; // 0x1000
+    field public static final int VP9Profile0 = 0; // 0x0
+    field public static final int VP9Profile1 = 1; // 0x1
+    field public static final int VP9Profile2 = 2; // 0x2
+    field public static final int VP9Profile3 = 3; // 0x3
     field public int level;
     field public int profile;
   }
@@ -20399,6 +20815,7 @@
     ctor public MediaExtractor();
     method public boolean advance();
     method public long getCachedDuration();
+    method public android.media.DrmInitData getDrmInitData();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -20443,6 +20860,16 @@
     method public final void setInteger(java.lang.String, int);
     method public final void setLong(java.lang.String, long);
     method public final void setString(java.lang.String, java.lang.String);
+    field public static final int COLOR_RANGE_FULL = 1; // 0x1
+    field public static final int COLOR_RANGE_LIMITED = 2; // 0x2
+    field public static final int COLOR_STANDARD_BT2020 = 6; // 0x6
+    field public static final int COLOR_STANDARD_BT601_NTSC = 4; // 0x4
+    field public static final int COLOR_STANDARD_BT601_PAL = 2; // 0x2
+    field public static final int COLOR_STANDARD_BT709 = 1; // 0x1
+    field public static final int COLOR_TRANSFER_HLG = 7; // 0x7
+    field public static final int COLOR_TRANSFER_LINEAR = 1; // 0x1
+    field public static final int COLOR_TRANSFER_SDR_VIDEO = 3; // 0x3
+    field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6
     field public static final java.lang.String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level";
     field public static final java.lang.String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level";
     field public static final java.lang.String KEY_AAC_DRC_HEAVY_COMPRESSION = "aac-drc-heavy-compression";
@@ -20458,11 +20885,15 @@
     field public static final java.lang.String KEY_CHANNEL_COUNT = "channel-count";
     field public static final java.lang.String KEY_CHANNEL_MASK = "channel-mask";
     field public static final java.lang.String KEY_COLOR_FORMAT = "color-format";
+    field public static final java.lang.String KEY_COLOR_RANGE = "color-range";
+    field public static final java.lang.String KEY_COLOR_STANDARD = "color-standard";
+    field public static final java.lang.String KEY_COLOR_TRANSFER = "color-transfer";
     field public static final java.lang.String KEY_COMPLEXITY = "complexity";
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
     field public static final java.lang.String KEY_HEIGHT = "height";
+    field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
     field public static final java.lang.String KEY_IS_AUTOSELECT = "is-autoselect";
     field public static final java.lang.String KEY_IS_DEFAULT = "is-default";
@@ -20784,9 +21215,11 @@
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
     method public android.view.Surface getSurface();
+    method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void release();
     method public void reset();
+    method public void resume() throws java.lang.IllegalStateException;
     method public void setAudioChannels(int);
     method public void setAudioEncoder(int) throws java.lang.IllegalStateException;
     method public void setAudioEncodingBitRate(int);
@@ -22080,6 +22513,7 @@
     method public void setRatingType(int);
     method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
@@ -22158,6 +22592,7 @@
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
+    field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
@@ -22474,7 +22909,7 @@
     method public void onInputAdded(java.lang.String);
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
-    method public void onTvInputInfoChanged(java.lang.String, android.media.tv.TvInputInfo);
+    method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
   public abstract class TvInputService extends android.app.Service {
@@ -22482,7 +22917,7 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public android.media.tv.TvInputService.RecordingSession onCreateRecordingSession(java.lang.String);
     method public abstract android.media.tv.TvInputService.Session onCreateSession(java.lang.String);
-    method public final void setTvInputInfo(java.lang.String, android.media.tv.TvInputInfo);
+    method public static final void setTvInputInfo(android.content.Context, android.media.tv.TvInputInfo);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
     field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
   }
@@ -22745,6 +23180,7 @@
     field public static final int OPERATION_GET_OBJECT_PROP_VALUE = 38915; // 0x9803
     field public static final int OPERATION_GET_OBJECT_REFERENCES = 38928; // 0x9810
     field public static final int OPERATION_GET_PARTIAL_OBJECT = 4123; // 0x101b
+    field public static final int OPERATION_GET_PARTIAL_OBJECT_64 = 38337; // 0x95c1
     field public static final int OPERATION_GET_STORAGE_INFO = 4101; // 0x1005
     field public static final int OPERATION_GET_STORAGE_I_DS = 4100; // 0x1004
     field public static final int OPERATION_GET_THUMB = 4106; // 0x100a
@@ -22782,6 +23218,7 @@
     method public android.mtp.MtpObjectInfo getObjectInfo(int);
     method public long getParent(int);
     method public long getPartialObject(int, long, long, byte[]) throws java.io.IOException;
+    method public long getPartialObject64(int, long, long, byte[]) throws java.io.IOException;
     method public long getStorageId(int);
     method public int[] getStorageIds();
     method public android.mtp.MtpStorageInfo getStorageInfo(int);
@@ -22790,7 +23227,7 @@
     method public boolean importFile(int, android.os.ParcelFileDescriptor);
     method public boolean open(android.hardware.usb.UsbDeviceConnection);
     method public android.mtp.MtpEvent readEvent(android.os.CancellationSignal);
-    method public boolean sendObject(int, int, android.os.ParcelFileDescriptor);
+    method public boolean sendObject(int, long, android.os.ParcelFileDescriptor);
     method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
   }
 
@@ -22821,23 +23258,31 @@
     method public final int getAssociationDesc();
     method public final int getAssociationType();
     method public final int getCompressedSize();
+    method public final long getCompressedSizeLong();
     method public final long getDateCreated();
     method public final long getDateModified();
     method public final int getFormat();
     method public final int getImagePixDepth();
+    method public final long getImagePixDepthLong();
     method public final int getImagePixHeight();
+    method public final long getImagePixHeightLong();
     method public final int getImagePixWidth();
+    method public final long getImagePixWidthLong();
     method public final java.lang.String getKeywords();
     method public final java.lang.String getName();
     method public final int getObjectHandle();
     method public final int getParent();
     method public final int getProtectionStatus();
     method public final int getSequenceNumber();
+    method public final long getSequenceNumberLong();
     method public final int getStorageId();
     method public final int getThumbCompressedSize();
+    method public final long getThumbCompressedSizeLong();
     method public final int getThumbFormat();
     method public final int getThumbPixHeight();
+    method public final long getThumbPixHeightLong();
     method public final int getThumbPixWidth();
+    method public final long getThumbPixWidthLong();
   }
 
   public static class MtpObjectInfo.Builder {
@@ -22846,24 +23291,24 @@
     method public android.mtp.MtpObjectInfo build();
     method public android.mtp.MtpObjectInfo.Builder setAssociationDesc(int);
     method public android.mtp.MtpObjectInfo.Builder setAssociationType(int);
-    method public android.mtp.MtpObjectInfo.Builder setCompressedSize(int);
+    method public android.mtp.MtpObjectInfo.Builder setCompressedSize(long);
     method public android.mtp.MtpObjectInfo.Builder setDateCreated(long);
     method public android.mtp.MtpObjectInfo.Builder setDateModified(long);
     method public android.mtp.MtpObjectInfo.Builder setFormat(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(int);
-    method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(int);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(long);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(long);
+    method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(long);
     method public android.mtp.MtpObjectInfo.Builder setKeywords(java.lang.String);
     method public android.mtp.MtpObjectInfo.Builder setName(java.lang.String);
     method public android.mtp.MtpObjectInfo.Builder setObjectHandle(int);
     method public android.mtp.MtpObjectInfo.Builder setParent(int);
     method public android.mtp.MtpObjectInfo.Builder setProtectionStatus(int);
-    method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(int);
+    method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(long);
     method public android.mtp.MtpObjectInfo.Builder setStorageId(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(int);
+    method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(long);
     method public android.mtp.MtpObjectInfo.Builder setThumbFormat(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(int);
-    method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(int);
+    method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(long);
+    method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(long);
   }
 
   public final class MtpStorageInfo {
@@ -27900,6 +28345,14 @@
     method public final synchronized android.os.CountDownTimer start();
   }
 
+  public final class CpuUsageInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getActive();
+    method public long getTotal();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.CpuUsageInfo> CREATOR;
+  }
+
   public class DeadObjectException extends android.os.RemoteException {
     ctor public DeadObjectException();
     ctor public DeadObjectException(java.lang.String);
@@ -28102,6 +28555,10 @@
     field public static final int OPEN = 32; // 0x20
   }
 
+  public class FileUriExposedException extends java.lang.RuntimeException {
+    ctor public FileUriExposedException(java.lang.String);
+  }
+
   public class Handler {
     ctor public Handler();
     ctor public Handler(android.os.Handler.Callback);
@@ -28152,6 +28609,18 @@
     method public boolean quitSafely();
   }
 
+  public class HardwarePropertiesManager {
+    method public android.os.CpuUsageInfo[] getCpuUsages();
+    method public float[] getDeviceTemperatures(int);
+    method public float[] getFanSpeeds();
+    field public static final int DEVICE_TEMPERATURE_BATTERY = 2; // 0x2
+    field public static final int DEVICE_TEMPERATURE_CPU = 0; // 0x0
+    field public static final int DEVICE_TEMPERATURE_GPU = 1; // 0x1
+  }
+
+  public static abstract class HardwarePropertiesManager.DeviceTemperatureType implements java.lang.annotation.Annotation {
+  }
+
   public abstract interface IBinder {
     method public abstract void dump(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
     method public abstract void dumpAsync(java.io.FileDescriptor, java.lang.String[]) throws android.os.RemoteException;
@@ -28521,6 +28990,7 @@
     field public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1; // 0x1
     field public static final deprecated int SCREEN_BRIGHT_WAKE_LOCK = 10; // 0xa
     field public static final deprecated int SCREEN_DIM_WAKE_LOCK = 6; // 0x6
+    field public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 256; // 0x100
   }
 
   public final class PowerManager.WakeLock {
@@ -28680,6 +29150,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
+    method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox();
     method public android.os.StrictMode.VmPolicy.Builder penaltyLog();
     method public android.os.StrictMode.VmPolicy.Builder setClassInstanceLimit(java.lang.Class, int);
@@ -28787,6 +29258,8 @@
     field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
     field public static final java.lang.String ENSURE_VERIFY_APPS = "ensure_verify_apps";
     field public static final java.lang.String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
+    field public static final int USER_CREATION_FAILED_NOT_PERMITTED = 1; // 0x1
+    field public static final int USER_CREATION_FAILED_NO_MORE_USERS = 2; // 0x2
   }
 
   public abstract class Vibrator {
@@ -29144,6 +29617,8 @@
     method public static void setDefaultValues(android.content.Context, java.lang.String, int, int, boolean);
     method public void setSharedPreferencesMode(int);
     method public void setSharedPreferencesName(java.lang.String);
+    method public void setStorageDefault();
+    method public void setStorageDeviceEncrypted();
     field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
     field public static final java.lang.String METADATA_KEY_PREFERENCES = "android.preference";
   }
@@ -31141,7 +31616,9 @@
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
     method public static java.lang.String getTreeDocumentId(android.net.Uri);
     method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
+    method public static boolean isTreeUri(android.net.Uri);
     method public static android.net.Uri moveDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri, android.net.Uri);
+    method public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri);
     method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String);
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
@@ -31167,6 +31644,7 @@
     field public static final int FLAG_SUPPORTS_COPY = 128; // 0x80
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
     field public static final int FLAG_SUPPORTS_MOVE = 256; // 0x100
+    field public static final int FLAG_SUPPORTS_REMOVE = 2048; // 0x800
     field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -31214,6 +31692,7 @@
     method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+    method public boolean removeDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public java.lang.String renameDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final void revokeDocumentPermission(java.lang.String);
     method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
@@ -31593,6 +32072,7 @@
     field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
     field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
     field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
+    field public static final java.lang.String ACTION_KEYBOARD_LAYOUT_SETTINGS = "android.settings.KEYBOARD_LAYOUT_SETTINGS";
     field public static final java.lang.String ACTION_LOCALE_SETTINGS = "android.settings.LOCALE_SETTINGS";
     field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
@@ -32256,6 +32736,7 @@
   public class VoicemailContract {
     field public static final java.lang.String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
     field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+    field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
     field public static final java.lang.String AUTHORITY = "com.android.voicemail";
     field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
     field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
@@ -32270,8 +32751,13 @@
     field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+    field public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3; // 0x3
+    field public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4; // 0x4
     field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+    field public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2; // 0x2
     field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6; // 0x6
+    field public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5; // 0x5
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
     field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
@@ -32369,6 +32855,7 @@
     method public void copyTo(short[]);
     method public void copyTo(int[]);
     method public void copyTo(float[]);
+    method public static android.renderscript.Allocation[] createAllocations(android.renderscript.RenderScript, android.renderscript.Type, int, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
     method public static android.renderscript.Allocation createCubemapFromBitmap(android.renderscript.RenderScript, android.graphics.Bitmap);
     method public static android.renderscript.Allocation createCubemapFromCubeFaces(android.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.renderscript.Allocation.MipmapControl, int);
@@ -32384,9 +32871,12 @@
     method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int);
     method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type);
     method public void generateMipmaps();
+    method public java.nio.ByteBuffer getByteBuffer();
     method public int getBytesSize();
     method public android.renderscript.Element getElement();
+    method public long getStride();
     method public android.view.Surface getSurface();
+    method public long getTimeStamp();
     method public android.renderscript.Type getType();
     method public int getUsage();
     method public void ioReceive();
@@ -33911,6 +34401,7 @@
     field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
     field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+    field public static final int REASON_PACKAGE_SUSPENDED = 15; // 0xf
     field public static final int REASON_TOPIC_BANNED = 14; // 0xe
     field public static final int REASON_USER_STOPPED = 6; // 0x6
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
@@ -35326,6 +35817,30 @@
     field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
   }
 
+  public abstract class CallScreeningService extends android.app.Service {
+    ctor public CallScreeningService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onScreenCall(android.telecom.Call.Details);
+    method public final void respondToCall(android.telecom.Call.Details, android.telecom.CallScreeningService.CallResponse);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+  }
+
+  public static class CallScreeningService.CallResponse {
+    method public boolean getDisallowCall();
+    method public boolean getRejectCall();
+    method public boolean getSkipCallLog();
+    method public boolean getSkipNotification();
+  }
+
+  public static class CallScreeningService.CallResponse.Builder {
+    ctor public CallScreeningService.CallResponse.Builder();
+    method public android.telecom.CallScreeningService.CallResponse build();
+    method public android.telecom.CallScreeningService.CallResponse.Builder setDisallowCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setRejectCall(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipCallLog(boolean);
+    method public android.telecom.CallScreeningService.CallResponse.Builder setSkipNotification(boolean);
+  }
+
   public abstract class Conference extends android.telecom.Conferenceable {
     ctor public Conference(android.telecom.PhoneAccountHandle);
     method public final boolean addConnection(android.telecom.Connection);
@@ -35565,6 +36080,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.InCallService";
@@ -35825,6 +36341,7 @@
     field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
+    field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
     field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
@@ -35976,6 +36493,7 @@
     field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
     field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
     field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+    field public static final java.lang.String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
     field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
@@ -35993,6 +36511,8 @@
 
   public final class CellIdentityGsm implements android.os.Parcelable {
     method public int describeContents();
+    method public int getArfcn();
+    method public int getBsic();
     method public int getCid();
     method public int getLac();
     method public int getMcc();
@@ -36005,6 +36525,7 @@
   public final class CellIdentityLte implements android.os.Parcelable {
     method public int describeContents();
     method public int getCi();
+    method public int getEarfcn();
     method public int getMcc();
     method public int getMnc();
     method public int getPci();
@@ -36020,6 +36541,7 @@
     method public int getMcc();
     method public int getMnc();
     method public int getPsc();
+    method public int getUarfcn();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityWcdma> CREATOR;
   }
@@ -36697,7 +37219,7 @@
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityInstrumentationTestCase2 extends android.test.ActivityTestCase {
     ctor public deprecated ActivityInstrumentationTestCase2(java.lang.String, java.lang.Class<T>);
     ctor public ActivityInstrumentationTestCase2(java.lang.Class<T>);
     method public T getActivity();
@@ -36705,14 +37227,14 @@
     method public void setActivityIntent(android.content.Intent);
   }
 
-  public abstract class ActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class ActivityTestCase extends android.test.InstrumentationTestCase {
     ctor public ActivityTestCase();
     method protected android.app.Activity getActivity();
     method protected void scrubClass(java.lang.Class<?>) throws java.lang.IllegalAccessException;
     method protected void setActivity(android.app.Activity);
   }
 
-  public abstract class ActivityUnitTestCase extends android.test.ActivityTestCase {
+  public abstract deprecated class ActivityUnitTestCase extends android.test.ActivityTestCase {
     ctor public ActivityUnitTestCase(java.lang.Class<T>);
     method public T getActivity();
     method public int getFinishedActivityRequest();
@@ -36725,7 +37247,7 @@
     method protected T startActivity(android.content.Intent, android.os.Bundle, java.lang.Object);
   }
 
-  public class AndroidTestCase extends junit.framework.TestCase {
+  public deprecated class AndroidTestCase extends junit.framework.TestCase {
     ctor public AndroidTestCase();
     method public void assertActivityRequiresPermission(java.lang.String, java.lang.String, java.lang.String);
     method public void assertReadingContentUriRequiresPermission(android.net.Uri, java.lang.String);
@@ -36737,7 +37259,7 @@
     field protected android.content.Context mContext;
   }
 
-  public class AndroidTestRunner extends junit.runner.BaseTestRunner {
+  public deprecated class AndroidTestRunner extends junit.runner.BaseTestRunner {
     ctor public AndroidTestRunner();
     method public void addTestListener(junit.framework.TestListener);
     method public void clearTestListeners();
@@ -36758,7 +37280,7 @@
     method public void testStarted(java.lang.String);
   }
 
-  public abstract class ApplicationTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ApplicationTestCase extends android.test.AndroidTestCase {
     ctor public ApplicationTestCase(java.lang.Class<T>);
     method protected final void createApplication();
     method public T getApplication();
@@ -36776,10 +37298,10 @@
     ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String);
   }
 
-  public abstract class FlakyTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class FlakyTest implements java.lang.annotation.Annotation {
   }
 
-  public class InstrumentationTestCase extends junit.framework.TestCase {
+  public deprecated class InstrumentationTestCase extends junit.framework.TestCase {
     ctor public InstrumentationTestCase();
     method public android.app.Instrumentation getInstrumentation();
     method public deprecated void injectInsrumentation(android.app.Instrumentation);
@@ -36792,7 +37314,7 @@
     method public void sendRepeatedKeys(int...);
   }
 
-  public class InstrumentationTestRunner extends android.app.Instrumentation implements android.test.TestSuiteProvider {
+  public deprecated class InstrumentationTestRunner extends android.app.Instrumentation implements android.test.TestSuiteProvider {
     ctor public InstrumentationTestRunner();
     method public junit.framework.TestSuite getAllTests();
     method protected android.test.AndroidTestRunner getAndroidTestRunner();
@@ -36811,14 +37333,14 @@
     field public static final int REPORT_VALUE_RESULT_START = 1; // 0x1
   }
 
-  public class InstrumentationTestSuite extends junit.framework.TestSuite {
+  public deprecated class InstrumentationTestSuite extends junit.framework.TestSuite {
     ctor public InstrumentationTestSuite(android.app.Instrumentation);
     ctor public InstrumentationTestSuite(java.lang.String, android.app.Instrumentation);
     ctor public InstrumentationTestSuite(java.lang.Class, android.app.Instrumentation);
     method public void addTestSuite(java.lang.Class);
   }
 
-  public class IsolatedContext extends android.content.ContextWrapper {
+  public deprecated class IsolatedContext extends android.content.ContextWrapper {
     ctor public IsolatedContext(android.content.ContentResolver, android.content.Context);
     method public java.util.List<android.content.Intent> getAndClearBroadcastIntents();
   }
@@ -36828,7 +37350,7 @@
     method public T getLoaderResultSynchronously(android.content.Loader<T>);
   }
 
-  public final class MoreAsserts {
+  public final deprecated class MoreAsserts {
     method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Object);
     method public static void assertAssignableFrom(java.lang.Class<?>, java.lang.Class<?>);
     method public static java.util.regex.MatchResult assertContainsRegex(java.lang.String, java.lang.String, java.lang.String);
@@ -36867,7 +37389,7 @@
     method public static void checkEqualsAndHashCodeMethods(java.lang.Object, java.lang.Object, boolean);
   }
 
-  public abstract interface PerformanceTestCase {
+  public abstract deprecated interface PerformanceTestCase {
     method public abstract boolean isPerformanceOnly();
     method public abstract int startPerformance(android.test.PerformanceTestCase.Intermediates);
   }
@@ -36896,7 +37418,7 @@
     method public static android.content.ContentResolver newResolverWithContentProviderFromSql(android.content.Context, java.lang.String, java.lang.Class<T>, java.lang.String, java.lang.String, int, java.lang.String) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public class RenamingDelegatingContext extends android.content.ContextWrapper {
+  public deprecated class RenamingDelegatingContext extends android.content.ContextWrapper {
     ctor public RenamingDelegatingContext(android.content.Context, java.lang.String);
     ctor public RenamingDelegatingContext(android.content.Context, android.content.Context, java.lang.String);
     method public java.lang.String getDatabasePrefix();
@@ -36905,7 +37427,7 @@
     method public static T providerWithRenamedContext(java.lang.Class<T>, android.content.Context, java.lang.String, boolean) throws java.lang.IllegalAccessException, java.lang.InstantiationException;
   }
 
-  public abstract class ServiceTestCase extends android.test.AndroidTestCase {
+  public abstract deprecated class ServiceTestCase extends android.test.AndroidTestCase {
     ctor public ServiceTestCase(java.lang.Class<T>);
     method protected android.os.IBinder bindService(android.content.Intent);
     method public android.app.Application getApplication();
@@ -36918,23 +37440,23 @@
     method public void testServiceTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public abstract class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
+  public abstract deprecated class SingleLaunchActivityTestCase extends android.test.InstrumentationTestCase {
     ctor public SingleLaunchActivityTestCase(java.lang.String, java.lang.Class<T>);
     method public T getActivity();
     method public void testActivityTestCaseSetUpProperly() throws java.lang.Exception;
   }
 
-  public class SyncBaseInstrumentation extends android.test.InstrumentationTestCase {
+  public deprecated class SyncBaseInstrumentation extends android.test.InstrumentationTestCase {
     ctor public SyncBaseInstrumentation();
     method protected void cancelSyncsandDisableAutoSync();
     method protected void syncProvider(android.net.Uri, java.lang.String, java.lang.String) throws java.lang.Exception;
   }
 
-  public abstract interface TestSuiteProvider {
+  public abstract deprecated interface TestSuiteProvider {
     method public abstract junit.framework.TestSuite getTestSuite();
   }
 
-  public class TouchUtils {
+  public deprecated class TouchUtils {
     ctor public TouchUtils();
     method public static void clickView(android.test.InstrumentationTestCase, android.view.View);
     method public static deprecated void drag(android.test.ActivityInstrumentationTestCase, float, float, float, float, int);
@@ -36969,10 +37491,10 @@
     method public static void touchAndCancelView(android.test.InstrumentationTestCase, android.view.View);
   }
 
-  public abstract class UiThreadTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class UiThreadTest implements java.lang.annotation.Annotation {
   }
 
-  public class ViewAsserts {
+  public deprecated class ViewAsserts {
     method public static void assertBaselineAligned(android.view.View, android.view.View);
     method public static void assertBottomAligned(android.view.View, android.view.View);
     method public static void assertBottomAligned(android.view.View, android.view.View, int);
@@ -36997,11 +37519,11 @@
 
 package android.test.mock {
 
-  public class MockApplication extends android.app.Application {
+  public deprecated class MockApplication extends android.app.Application {
     ctor public MockApplication();
   }
 
-  public class MockContentProvider extends android.content.ContentProvider {
+  public deprecated class MockContentProvider extends android.content.ContentProvider {
     ctor protected MockContentProvider();
     ctor public MockContentProvider(android.content.Context);
     ctor public MockContentProvider(android.content.Context, java.lang.String, java.lang.String, android.content.pm.PathPermission[]);
@@ -37013,13 +37535,13 @@
     method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
-  public class MockContentResolver extends android.content.ContentResolver {
+  public deprecated class MockContentResolver extends android.content.ContentResolver {
     ctor public MockContentResolver();
     ctor public MockContentResolver(android.content.Context);
     method public void addProvider(java.lang.String, android.content.ContentProvider);
   }
 
-  public class MockContext extends android.content.Context {
+  public deprecated class MockContext extends android.content.Context {
     ctor public MockContext();
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(java.lang.String);
@@ -37120,7 +37642,7 @@
     method public void unregisterReceiver(android.content.BroadcastReceiver);
   }
 
-  public class MockCursor implements android.database.Cursor {
+  public deprecated class MockCursor implements android.database.Cursor {
     ctor public MockCursor();
     method public void close();
     method public void copyStringToBuffer(int, android.database.CharArrayBuffer);
@@ -37165,13 +37687,13 @@
     method public void unregisterDataSetObserver(android.database.DataSetObserver);
   }
 
-  public class MockDialogInterface implements android.content.DialogInterface {
+  public deprecated class MockDialogInterface implements android.content.DialogInterface {
     ctor public MockDialogInterface();
     method public void cancel();
     method public void dismiss();
   }
 
-  public class MockPackageManager extends android.content.pm.PackageManager {
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
     ctor public MockPackageManager();
     method public void addPackageToPreferred(java.lang.String);
     method public boolean addPermission(android.content.pm.PermissionInfo);
@@ -37259,7 +37781,7 @@
     method public void verifyPendingInstall(int, int);
   }
 
-  public class MockResources extends android.content.res.Resources {
+  public deprecated class MockResources extends android.content.res.Resources {
     ctor public MockResources();
   }
 
@@ -37300,19 +37822,19 @@
 
 package android.test.suitebuilder.annotation {
 
-  public abstract class LargeTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class LargeTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class MediumTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class MediumTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class SmallTest implements java.lang.annotation.Annotation {
+  public abstract deprecated class SmallTest implements java.lang.annotation.Annotation {
   }
 
-  public abstract class Smoke implements java.lang.annotation.Annotation {
+  public abstract deprecated class Smoke implements java.lang.annotation.Annotation {
   }
 
-  public abstract class Suppress implements java.lang.annotation.Annotation {
+  public abstract deprecated class Suppress implements java.lang.annotation.Annotation {
   }
 
 }
@@ -48325,7 +48847,6 @@
     method public boolean setReadable(boolean);
     method public boolean setWritable(boolean, boolean);
     method public boolean setWritable(boolean);
-    method public java.nio.file.Path toPath();
     method public java.net.URI toURI();
     method public deprecated java.net.URL toURL() throws java.net.MalformedURLException;
     field public static final java.lang.String pathSeparator;
@@ -49878,6 +50399,9 @@
     field public static final java.lang.Class<java.lang.Float> TYPE;
   }
 
+  public abstract class FunctionalInterface implements java.lang.annotation.Annotation {
+  }
+
   public class IllegalAccessError extends java.lang.IncompatibleClassChangeError {
     ctor public IllegalAccessError();
     ctor public IllegalAccessError(java.lang.String);
@@ -50809,6 +51333,9 @@
   public abstract class Inherited implements java.lang.annotation.Annotation {
   }
 
+  public abstract class Repeatable implements java.lang.annotation.Annotation {
+  }
+
   public abstract class Retention implements java.lang.annotation.Annotation {
   }
 
@@ -52421,25 +52948,6 @@
     ctor public AsynchronousCloseException();
   }
 
-  public abstract class AsynchronousFileChannel implements java.nio.channels.AsynchronousChannel {
-    ctor protected AsynchronousFileChannel();
-    method public abstract void force(boolean) throws java.io.IOException;
-    method public abstract void lock(long, long, boolean, A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public final void lock(A, java.nio.channels.CompletionHandler<java.nio.channels.FileLock, ? super A>);
-    method public abstract java.util.concurrent.Future<java.nio.channels.FileLock> lock(long, long, boolean);
-    method public final java.util.concurrent.Future<java.nio.channels.FileLock> lock();
-    method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousFileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract void read(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer, long);
-    method public abstract long size() throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousFileChannel truncate(long) throws java.io.IOException;
-    method public abstract java.nio.channels.FileLock tryLock(long, long, boolean) throws java.io.IOException;
-    method public final java.nio.channels.FileLock tryLock() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer, long);
-  }
-
   public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
     ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
     method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
@@ -52548,8 +53056,6 @@
     method public abstract java.nio.channels.FileLock lock(long, long, boolean) throws java.io.IOException;
     method public final java.nio.channels.FileLock lock() throws java.io.IOException;
     method public abstract java.nio.MappedByteBuffer map(java.nio.channels.FileChannel.MapMode, long, long) throws java.io.IOException;
-    method public static java.nio.channels.FileChannel open(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.FileChannel open(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
     method public abstract long position() throws java.io.IOException;
     method public abstract java.nio.channels.FileChannel position(long) throws java.io.IOException;
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
@@ -52576,7 +53082,6 @@
 
   public abstract class FileLock implements java.lang.AutoCloseable {
     ctor protected FileLock(java.nio.channels.FileChannel, long, long, boolean);
-    ctor protected FileLock(java.nio.channels.AsynchronousFileChannel, long, long, boolean);
     method public java.nio.channels.Channel acquiredBy();
     method public final java.nio.channels.FileChannel channel();
     method public final void close() throws java.io.IOException;
@@ -53026,592 +53531,6 @@
 
 }
 
-package java.nio.file {
-
-  public class AccessDeniedException extends java.nio.file.FileSystemException {
-    ctor public AccessDeniedException(java.lang.String);
-    ctor public AccessDeniedException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public final class AccessMode extends java.lang.Enum {
-    method public static java.nio.file.AccessMode valueOf(java.lang.String);
-    method public static final java.nio.file.AccessMode[] values();
-    enum_constant public static final java.nio.file.AccessMode EXECUTE;
-    enum_constant public static final java.nio.file.AccessMode READ;
-    enum_constant public static final java.nio.file.AccessMode WRITE;
-  }
-
-  public class AtomicMoveNotSupportedException extends java.nio.file.FileSystemException {
-    ctor public AtomicMoveNotSupportedException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public class ClosedDirectoryStreamException extends java.lang.IllegalStateException {
-    ctor public ClosedDirectoryStreamException();
-  }
-
-  public class ClosedFileSystemException extends java.lang.IllegalStateException {
-    ctor public ClosedFileSystemException();
-  }
-
-  public class ClosedWatchServiceException extends java.lang.IllegalStateException {
-    ctor public ClosedWatchServiceException();
-  }
-
-  public abstract interface CopyOption {
-  }
-
-  public final class DirectoryIteratorException extends java.util.ConcurrentModificationException {
-    ctor public DirectoryIteratorException(java.io.IOException);
-  }
-
-  public class DirectoryNotEmptyException extends java.nio.file.FileSystemException {
-    ctor public DirectoryNotEmptyException(java.lang.String);
-  }
-
-  public abstract interface DirectoryStream implements java.io.Closeable java.lang.Iterable {
-    method public abstract java.util.Iterator<T> iterator();
-  }
-
-  public static abstract interface DirectoryStream.Filter {
-    method public abstract boolean accept(T) throws java.io.IOException;
-  }
-
-  public class FileAlreadyExistsException extends java.nio.file.FileSystemException {
-    ctor public FileAlreadyExistsException(java.lang.String);
-    ctor public FileAlreadyExistsException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public abstract class FileStore {
-    ctor protected FileStore();
-    method public abstract java.lang.Object getAttribute(java.lang.String) throws java.io.IOException;
-    method public abstract V getFileStoreAttributeView(java.lang.Class<V>);
-    method public abstract long getTotalSpace() throws java.io.IOException;
-    method public abstract long getUnallocatedSpace() throws java.io.IOException;
-    method public abstract long getUsableSpace() throws java.io.IOException;
-    method public abstract boolean isReadOnly();
-    method public abstract java.lang.String name();
-    method public abstract boolean supportsFileAttributeView(java.lang.Class<? extends java.nio.file.attribute.FileAttributeView>);
-    method public abstract boolean supportsFileAttributeView(java.lang.String);
-    method public abstract java.lang.String type();
-  }
-
-  public abstract class FileSystem implements java.io.Closeable {
-    ctor protected FileSystem();
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.lang.Iterable<java.nio.file.FileStore> getFileStores();
-    method public abstract java.nio.file.Path getPath(java.lang.String, java.lang.String...);
-    method public abstract java.nio.file.PathMatcher getPathMatcher(java.lang.String);
-    method public abstract java.lang.Iterable<java.nio.file.Path> getRootDirectories();
-    method public abstract java.lang.String getSeparator();
-    method public abstract java.nio.file.attribute.UserPrincipalLookupService getUserPrincipalLookupService();
-    method public abstract boolean isOpen();
-    method public abstract boolean isReadOnly();
-    method public abstract java.nio.file.WatchService newWatchService() throws java.io.IOException;
-    method public abstract java.nio.file.spi.FileSystemProvider provider();
-    method public abstract java.util.Set<java.lang.String> supportedFileAttributeViews();
-  }
-
-  public class FileSystemAlreadyExistsException extends java.lang.RuntimeException {
-    ctor public FileSystemAlreadyExistsException();
-    ctor public FileSystemAlreadyExistsException(java.lang.String);
-  }
-
-  public class FileSystemException extends java.io.IOException {
-    ctor public FileSystemException(java.lang.String);
-    ctor public FileSystemException(java.lang.String, java.lang.String, java.lang.String);
-    method public java.lang.String getFile();
-    method public java.lang.String getOtherFile();
-    method public java.lang.String getReason();
-  }
-
-  public class FileSystemLoopException extends java.nio.file.FileSystemException {
-    ctor public FileSystemLoopException(java.lang.String);
-  }
-
-  public class FileSystemNotFoundException extends java.lang.RuntimeException {
-    ctor public FileSystemNotFoundException();
-    ctor public FileSystemNotFoundException(java.lang.String);
-  }
-
-  public final class FileSystems {
-    method public static java.nio.file.FileSystem getDefault();
-    method public static java.nio.file.FileSystem getFileSystem(java.net.URI);
-    method public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public static java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>, java.lang.ClassLoader) throws java.io.IOException;
-    method public static java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.lang.ClassLoader) throws java.io.IOException;
-  }
-
-  public final class FileVisitOption extends java.lang.Enum {
-    method public static java.nio.file.FileVisitOption valueOf(java.lang.String);
-    method public static final java.nio.file.FileVisitOption[] values();
-    enum_constant public static final java.nio.file.FileVisitOption FOLLOW_LINKS;
-  }
-
-  public final class FileVisitResult extends java.lang.Enum {
-    method public static java.nio.file.FileVisitResult valueOf(java.lang.String);
-    method public static final java.nio.file.FileVisitResult[] values();
-    enum_constant public static final java.nio.file.FileVisitResult CONTINUE;
-    enum_constant public static final java.nio.file.FileVisitResult SKIP_SIBLINGS;
-    enum_constant public static final java.nio.file.FileVisitResult SKIP_SUBTREE;
-    enum_constant public static final java.nio.file.FileVisitResult TERMINATE;
-  }
-
-  public abstract interface FileVisitor {
-    method public abstract java.nio.file.FileVisitResult postVisitDirectory(T, java.io.IOException) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult preVisitDirectory(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult visitFile(T, java.nio.file.attribute.BasicFileAttributes) throws java.io.IOException;
-    method public abstract java.nio.file.FileVisitResult visitFileFailed(T, java.io.IOException) throws java.io.IOException;
-  }
-
-  public final class Files {
-    method public static java.nio.file.Path copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static long copy(java.io.InputStream, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static long copy(java.nio.file.Path, java.io.OutputStream) throws java.io.IOException;
-    method public static java.nio.file.Path createDirectories(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createFile(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createLink(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempDirectory(java.nio.file.Path, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempDirectory(java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempFile(java.nio.file.Path, java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.file.Path createTempFile(java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static void delete(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean exists(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public static java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.attribute.FileTime getLastModifiedTime(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.attribute.UserPrincipal getOwner(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.util.Set<java.nio.file.attribute.PosixFilePermission> getPosixFilePermissions(java.nio.file.Path, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static boolean isDirectory(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static boolean isExecutable(java.nio.file.Path);
-    method public static boolean isHidden(java.nio.file.Path) throws java.io.IOException;
-    method public static boolean isReadable(java.nio.file.Path);
-    method public static boolean isRegularFile(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static boolean isSameFile(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public static boolean isSymbolicLink(java.nio.file.Path);
-    method public static boolean isWritable(java.nio.file.Path);
-    method public static java.nio.file.Path move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public static java.io.BufferedReader newBufferedReader(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
-    method public static java.io.BufferedWriter newBufferedWriter(java.nio.file.Path, java.nio.charset.Charset, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public static java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.lang.String) throws java.io.IOException;
-    method public static java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static boolean notExists(java.nio.file.Path, java.nio.file.LinkOption...);
-    method public static java.lang.String probeContentType(java.nio.file.Path) throws java.io.IOException;
-    method public static byte[] readAllBytes(java.nio.file.Path) throws java.io.IOException;
-    method public static java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) throws java.io.IOException;
-    method public static A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public static java.nio.file.Path setLastModifiedTime(java.nio.file.Path, java.nio.file.attribute.FileTime) throws java.io.IOException;
-    method public static java.nio.file.Path setOwner(java.nio.file.Path, java.nio.file.attribute.UserPrincipal) throws java.io.IOException;
-    method public static java.nio.file.Path setPosixFilePermissions(java.nio.file.Path, java.util.Set<java.nio.file.attribute.PosixFilePermission>) throws java.io.IOException;
-    method public static long size(java.nio.file.Path) throws java.io.IOException;
-    method public static java.nio.file.Path walkFileTree(java.nio.file.Path, java.util.Set<java.nio.file.FileVisitOption>, int, java.nio.file.FileVisitor<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.nio.file.Path walkFileTree(java.nio.file.Path, java.nio.file.FileVisitor<? super java.nio.file.Path>) throws java.io.IOException;
-    method public static java.nio.file.Path write(java.nio.file.Path, byte[], java.nio.file.OpenOption...) throws java.io.IOException;
-    method public static java.nio.file.Path write(java.nio.file.Path, java.lang.Iterable<? extends java.lang.CharSequence>, java.nio.charset.Charset, java.nio.file.OpenOption...) throws java.io.IOException;
-  }
-
-  public class InvalidPathException extends java.lang.IllegalArgumentException {
-    ctor public InvalidPathException(java.lang.String, java.lang.String, int);
-    ctor public InvalidPathException(java.lang.String, java.lang.String);
-    method public int getIndex();
-    method public java.lang.String getInput();
-    method public java.lang.String getReason();
-  }
-
-  public final class LinkOption extends java.lang.Enum implements java.nio.file.CopyOption java.nio.file.OpenOption {
-    method public static java.nio.file.LinkOption valueOf(java.lang.String);
-    method public static final java.nio.file.LinkOption[] values();
-    enum_constant public static final java.nio.file.LinkOption NOFOLLOW_LINKS;
-  }
-
-  public final class LinkPermission extends java.security.BasicPermission {
-    ctor public LinkPermission(java.lang.String);
-    ctor public LinkPermission(java.lang.String, java.lang.String);
-  }
-
-  public class NoSuchFileException extends java.nio.file.FileSystemException {
-    ctor public NoSuchFileException(java.lang.String);
-    ctor public NoSuchFileException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public class NotDirectoryException extends java.nio.file.FileSystemException {
-    ctor public NotDirectoryException(java.lang.String);
-  }
-
-  public class NotLinkException extends java.nio.file.FileSystemException {
-    ctor public NotLinkException(java.lang.String);
-    ctor public NotLinkException(java.lang.String, java.lang.String, java.lang.String);
-  }
-
-  public abstract interface OpenOption {
-  }
-
-  public abstract interface Path implements java.lang.Comparable java.lang.Iterable java.nio.file.Watchable {
-    method public abstract int compareTo(java.nio.file.Path);
-    method public abstract boolean endsWith(java.nio.file.Path);
-    method public abstract boolean endsWith(java.lang.String);
-    method public abstract boolean equals(java.lang.Object);
-    method public abstract java.nio.file.Path getFileName();
-    method public abstract java.nio.file.FileSystem getFileSystem();
-    method public abstract java.nio.file.Path getName(int);
-    method public abstract int getNameCount();
-    method public abstract java.nio.file.Path getParent();
-    method public abstract java.nio.file.Path getRoot();
-    method public abstract int hashCode();
-    method public abstract boolean isAbsolute();
-    method public abstract java.util.Iterator<java.nio.file.Path> iterator();
-    method public abstract java.nio.file.Path normalize();
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>[], java.nio.file.WatchEvent.Modifier...) throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.Path relativize(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolve(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolve(java.lang.String);
-    method public abstract java.nio.file.Path resolveSibling(java.nio.file.Path);
-    method public abstract java.nio.file.Path resolveSibling(java.lang.String);
-    method public abstract boolean startsWith(java.nio.file.Path);
-    method public abstract boolean startsWith(java.lang.String);
-    method public abstract java.nio.file.Path subpath(int, int);
-    method public abstract java.nio.file.Path toAbsolutePath();
-    method public abstract java.io.File toFile();
-    method public abstract java.nio.file.Path toRealPath(java.nio.file.LinkOption...) throws java.io.IOException;
-    method public abstract java.lang.String toString();
-    method public abstract java.net.URI toUri();
-  }
-
-  public abstract interface PathMatcher {
-    method public abstract boolean matches(java.nio.file.Path);
-  }
-
-  public final class Paths {
-    method public static java.nio.file.Path get(java.lang.String, java.lang.String...);
-    method public static java.nio.file.Path get(java.net.URI);
-  }
-
-  public class ProviderMismatchException extends java.lang.IllegalArgumentException {
-    ctor public ProviderMismatchException();
-    ctor public ProviderMismatchException(java.lang.String);
-  }
-
-  public class ProviderNotFoundException extends java.lang.RuntimeException {
-    ctor public ProviderNotFoundException();
-    ctor public ProviderNotFoundException(java.lang.String);
-  }
-
-  public class ReadOnlyFileSystemException extends java.lang.UnsupportedOperationException {
-    ctor public ReadOnlyFileSystemException();
-  }
-
-  public abstract interface SecureDirectoryStream implements java.nio.file.DirectoryStream {
-    method public abstract void deleteDirectory(T) throws java.io.IOException;
-    method public abstract void deleteFile(T) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.lang.Class<V>);
-    method public abstract V getFileAttributeView(T, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public abstract void move(T, java.nio.file.SecureDirectoryStream<T>, T) throws java.io.IOException;
-    method public abstract java.nio.channels.SeekableByteChannel newByteChannel(T, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.SecureDirectoryStream<T> newDirectoryStream(T, java.nio.file.LinkOption...) throws java.io.IOException;
-  }
-
-  public final class StandardCopyOption extends java.lang.Enum implements java.nio.file.CopyOption {
-    method public static java.nio.file.StandardCopyOption valueOf(java.lang.String);
-    method public static final java.nio.file.StandardCopyOption[] values();
-    enum_constant public static final java.nio.file.StandardCopyOption ATOMIC_MOVE;
-    enum_constant public static final java.nio.file.StandardCopyOption COPY_ATTRIBUTES;
-    enum_constant public static final java.nio.file.StandardCopyOption REPLACE_EXISTING;
-  }
-
-  public final class StandardOpenOption extends java.lang.Enum implements java.nio.file.OpenOption {
-    method public static java.nio.file.StandardOpenOption valueOf(java.lang.String);
-    method public static final java.nio.file.StandardOpenOption[] values();
-    enum_constant public static final java.nio.file.StandardOpenOption APPEND;
-    enum_constant public static final java.nio.file.StandardOpenOption CREATE;
-    enum_constant public static final java.nio.file.StandardOpenOption CREATE_NEW;
-    enum_constant public static final java.nio.file.StandardOpenOption DELETE_ON_CLOSE;
-    enum_constant public static final java.nio.file.StandardOpenOption DSYNC;
-    enum_constant public static final java.nio.file.StandardOpenOption READ;
-    enum_constant public static final java.nio.file.StandardOpenOption SPARSE;
-    enum_constant public static final java.nio.file.StandardOpenOption SYNC;
-    enum_constant public static final java.nio.file.StandardOpenOption TRUNCATE_EXISTING;
-    enum_constant public static final java.nio.file.StandardOpenOption WRITE;
-  }
-
-  public final class StandardWatchEventKinds {
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_CREATE;
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_DELETE;
-    field public static final java.nio.file.WatchEvent.Kind<java.nio.file.Path> ENTRY_MODIFY;
-    field public static final java.nio.file.WatchEvent.Kind<java.lang.Object> OVERFLOW;
-  }
-
-  public abstract interface WatchEvent {
-    method public abstract T context();
-    method public abstract int count();
-    method public abstract java.nio.file.WatchEvent.Kind<T> kind();
-  }
-
-  public static abstract interface WatchEvent.Kind {
-    method public abstract java.lang.String name();
-    method public abstract java.lang.Class<T> type();
-  }
-
-  public static abstract interface WatchEvent.Modifier {
-    method public abstract java.lang.String name();
-  }
-
-  public abstract interface WatchKey {
-    method public abstract void cancel();
-    method public abstract boolean isValid();
-    method public abstract java.util.List<java.nio.file.WatchEvent<?>> pollEvents();
-    method public abstract boolean reset();
-    method public abstract java.nio.file.Watchable watchable();
-  }
-
-  public abstract interface WatchService implements java.io.Closeable {
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey poll();
-    method public abstract java.nio.file.WatchKey poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract java.nio.file.WatchKey take() throws java.lang.InterruptedException;
-  }
-
-  public abstract interface Watchable {
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>[], java.nio.file.WatchEvent.Modifier...) throws java.io.IOException;
-    method public abstract java.nio.file.WatchKey register(java.nio.file.WatchService, java.nio.file.WatchEvent.Kind<?>...) throws java.io.IOException;
-  }
-
-}
-
-package java.nio.file.attribute {
-
-  public final class AclEntry {
-    method public java.util.Set<java.nio.file.attribute.AclEntryFlag> flags();
-    method public static java.nio.file.attribute.AclEntry.Builder newBuilder();
-    method public static java.nio.file.attribute.AclEntry.Builder newBuilder(java.nio.file.attribute.AclEntry);
-    method public java.util.Set<java.nio.file.attribute.AclEntryPermission> permissions();
-    method public java.nio.file.attribute.UserPrincipal principal();
-    method public java.nio.file.attribute.AclEntryType type();
-  }
-
-  public static final class AclEntry.Builder {
-    method public java.nio.file.attribute.AclEntry build();
-    method public java.nio.file.attribute.AclEntry.Builder setFlags(java.util.Set<java.nio.file.attribute.AclEntryFlag>);
-    method public java.nio.file.attribute.AclEntry.Builder setFlags(java.nio.file.attribute.AclEntryFlag...);
-    method public java.nio.file.attribute.AclEntry.Builder setPermissions(java.util.Set<java.nio.file.attribute.AclEntryPermission>);
-    method public java.nio.file.attribute.AclEntry.Builder setPermissions(java.nio.file.attribute.AclEntryPermission...);
-    method public java.nio.file.attribute.AclEntry.Builder setPrincipal(java.nio.file.attribute.UserPrincipal);
-    method public java.nio.file.attribute.AclEntry.Builder setType(java.nio.file.attribute.AclEntryType);
-  }
-
-  public final class AclEntryFlag extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryFlag valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryFlag[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag DIRECTORY_INHERIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag FILE_INHERIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag INHERIT_ONLY;
-    enum_constant public static final java.nio.file.attribute.AclEntryFlag NO_PROPAGATE_INHERIT;
-  }
-
-  public final class AclEntryPermission extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryPermission valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryPermission[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission APPEND_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE_CHILD;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission EXECUTE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ACL;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ATTRIBUTES;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_NAMED_ATTRS;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission SYNCHRONIZE;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ACL;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ATTRIBUTES;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_DATA;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_NAMED_ATTRS;
-    enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_OWNER;
-    field public static final java.nio.file.attribute.AclEntryPermission ADD_FILE;
-    field public static final java.nio.file.attribute.AclEntryPermission ADD_SUBDIRECTORY;
-    field public static final java.nio.file.attribute.AclEntryPermission LIST_DIRECTORY;
-  }
-
-  public final class AclEntryType extends java.lang.Enum {
-    method public static java.nio.file.attribute.AclEntryType valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.AclEntryType[] values();
-    enum_constant public static final java.nio.file.attribute.AclEntryType ALARM;
-    enum_constant public static final java.nio.file.attribute.AclEntryType ALLOW;
-    enum_constant public static final java.nio.file.attribute.AclEntryType AUDIT;
-    enum_constant public static final java.nio.file.attribute.AclEntryType DENY;
-  }
-
-  public abstract interface AclFileAttributeView implements java.nio.file.attribute.FileOwnerAttributeView {
-    method public abstract java.util.List<java.nio.file.attribute.AclEntry> getAcl() throws java.io.IOException;
-    method public abstract java.lang.String name();
-    method public abstract void setAcl(java.util.List<java.nio.file.attribute.AclEntry>) throws java.io.IOException;
-  }
-
-  public abstract interface AttributeView {
-    method public abstract java.lang.String name();
-  }
-
-  public abstract interface BasicFileAttributeView implements java.nio.file.attribute.FileAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.BasicFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setTimes(java.nio.file.attribute.FileTime, java.nio.file.attribute.FileTime, java.nio.file.attribute.FileTime) throws java.io.IOException;
-  }
-
-  public abstract interface BasicFileAttributes {
-    method public abstract java.nio.file.attribute.FileTime creationTime();
-    method public abstract java.lang.Object fileKey();
-    method public abstract boolean isDirectory();
-    method public abstract boolean isOther();
-    method public abstract boolean isRegularFile();
-    method public abstract boolean isSymbolicLink();
-    method public abstract java.nio.file.attribute.FileTime lastAccessTime();
-    method public abstract java.nio.file.attribute.FileTime lastModifiedTime();
-    method public abstract long size();
-  }
-
-  public abstract interface DosFileAttributeView implements java.nio.file.attribute.BasicFileAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.DosFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setArchive(boolean) throws java.io.IOException;
-    method public abstract void setHidden(boolean) throws java.io.IOException;
-    method public abstract void setReadOnly(boolean) throws java.io.IOException;
-    method public abstract void setSystem(boolean) throws java.io.IOException;
-  }
-
-  public abstract interface DosFileAttributes implements java.nio.file.attribute.BasicFileAttributes {
-    method public abstract boolean isArchive();
-    method public abstract boolean isHidden();
-    method public abstract boolean isReadOnly();
-    method public abstract boolean isSystem();
-  }
-
-  public abstract interface FileAttribute {
-    method public abstract java.lang.String name();
-    method public abstract T value();
-  }
-
-  public abstract interface FileAttributeView implements java.nio.file.attribute.AttributeView {
-  }
-
-  public abstract interface FileOwnerAttributeView implements java.nio.file.attribute.FileAttributeView {
-    method public abstract java.nio.file.attribute.UserPrincipal getOwner() throws java.io.IOException;
-    method public abstract java.lang.String name();
-    method public abstract void setOwner(java.nio.file.attribute.UserPrincipal) throws java.io.IOException;
-  }
-
-  public abstract interface FileStoreAttributeView implements java.nio.file.attribute.AttributeView {
-  }
-
-  public final class FileTime implements java.lang.Comparable {
-    method public int compareTo(java.nio.file.attribute.FileTime);
-    method public static java.nio.file.attribute.FileTime from(long, java.util.concurrent.TimeUnit);
-    method public static java.nio.file.attribute.FileTime fromMillis(long);
-    method public long to(java.util.concurrent.TimeUnit);
-    method public long toMillis();
-  }
-
-  public abstract interface GroupPrincipal implements java.nio.file.attribute.UserPrincipal {
-  }
-
-  public abstract interface PosixFileAttributeView implements java.nio.file.attribute.BasicFileAttributeView java.nio.file.attribute.FileOwnerAttributeView {
-    method public abstract java.lang.String name();
-    method public abstract java.nio.file.attribute.PosixFileAttributes readAttributes() throws java.io.IOException;
-    method public abstract void setGroup(java.nio.file.attribute.GroupPrincipal) throws java.io.IOException;
-    method public abstract void setPermissions(java.util.Set<java.nio.file.attribute.PosixFilePermission>) throws java.io.IOException;
-  }
-
-  public abstract interface PosixFileAttributes implements java.nio.file.attribute.BasicFileAttributes {
-    method public abstract java.nio.file.attribute.GroupPrincipal group();
-    method public abstract java.nio.file.attribute.UserPrincipal owner();
-    method public abstract java.util.Set<java.nio.file.attribute.PosixFilePermission> permissions();
-  }
-
-  public final class PosixFilePermission extends java.lang.Enum {
-    method public static java.nio.file.attribute.PosixFilePermission valueOf(java.lang.String);
-    method public static final java.nio.file.attribute.PosixFilePermission[] values();
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission GROUP_WRITE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OTHERS_WRITE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_EXECUTE;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_READ;
-    enum_constant public static final java.nio.file.attribute.PosixFilePermission OWNER_WRITE;
-  }
-
-  public final class PosixFilePermissions {
-    method public static java.nio.file.attribute.FileAttribute<java.util.Set<java.nio.file.attribute.PosixFilePermission>> asFileAttribute(java.util.Set<java.nio.file.attribute.PosixFilePermission>);
-    method public static java.util.Set<java.nio.file.attribute.PosixFilePermission> fromString(java.lang.String);
-    method public static java.lang.String toString(java.util.Set<java.nio.file.attribute.PosixFilePermission>);
-  }
-
-  public abstract interface UserPrincipal implements java.security.Principal {
-  }
-
-  public abstract class UserPrincipalLookupService {
-    ctor protected UserPrincipalLookupService();
-    method public abstract java.nio.file.attribute.GroupPrincipal lookupPrincipalByGroupName(java.lang.String) throws java.io.IOException;
-    method public abstract java.nio.file.attribute.UserPrincipal lookupPrincipalByName(java.lang.String) throws java.io.IOException;
-  }
-
-  public class UserPrincipalNotFoundException extends java.io.IOException {
-    ctor public UserPrincipalNotFoundException(java.lang.String);
-    method public java.lang.String getName();
-  }
-
-}
-
-package java.nio.file.spi {
-
-  public abstract class FileSystemProvider {
-    ctor protected FileSystemProvider();
-    method public abstract void checkAccess(java.nio.file.Path, java.nio.file.AccessMode...) throws java.io.IOException;
-    method public abstract void copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public abstract void createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public void createLink(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public void createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract void delete(java.nio.file.Path) throws java.io.IOException;
-    method public boolean deleteIfExists(java.nio.file.Path) throws java.io.IOException;
-    method public abstract V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...);
-    method public abstract java.nio.file.FileStore getFileStore(java.nio.file.Path) throws java.io.IOException;
-    method public abstract java.nio.file.FileSystem getFileSystem(java.net.URI);
-    method public abstract java.nio.file.Path getPath(java.net.URI);
-    method public abstract java.lang.String getScheme();
-    method public static java.util.List<java.nio.file.spi.FileSystemProvider> installedProviders();
-    method public abstract boolean isHidden(java.nio.file.Path) throws java.io.IOException;
-    method public abstract boolean isSameFile(java.nio.file.Path, java.nio.file.Path) throws java.io.IOException;
-    method public abstract void move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) throws java.io.IOException;
-    method public java.nio.channels.AsynchronousFileChannel newAsynchronousFileChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.util.concurrent.ExecutorService, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) throws java.io.IOException;
-    method public java.nio.channels.FileChannel newFileChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) throws java.io.IOException;
-    method public abstract java.nio.file.FileSystem newFileSystem(java.net.URI, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public java.nio.file.FileSystem newFileSystem(java.nio.file.Path, java.util.Map<java.lang.String, ?>) throws java.io.IOException;
-    method public java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) throws java.io.IOException;
-    method public abstract A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public abstract java.util.Map<java.lang.String, java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) throws java.io.IOException;
-    method public java.nio.file.Path readSymbolicLink(java.nio.file.Path) throws java.io.IOException;
-    method public abstract void setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) throws java.io.IOException;
-  }
-
-  public abstract class FileTypeDetector {
-    ctor protected FileTypeDetector();
-    method public abstract java.lang.String probeContentType(java.nio.file.Path) throws java.io.IOException;
-  }
-
-}
-
 package java.security {
 
   public final class AccessControlContext {
@@ -58208,8 +58127,6 @@
     ctor public Scanner(java.io.InputStream, java.lang.String);
     ctor public Scanner(java.io.File) throws java.io.FileNotFoundException;
     ctor public Scanner(java.io.File, java.lang.String) throws java.io.FileNotFoundException;
-    ctor public Scanner(java.nio.file.Path) throws java.io.IOException;
-    ctor public Scanner(java.nio.file.Path, java.lang.String) throws java.io.IOException;
     ctor public Scanner(java.lang.String);
     ctor public Scanner(java.nio.channels.ReadableByteChannel);
     ctor public Scanner(java.nio.channels.ReadableByteChannel, java.lang.String);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 6b7961e..2c6729d 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -201,7 +201,7 @@
 
 package android.test.mock {
 
-  public class MockPackageManager extends android.content.pm.PackageManager {
+  public deprecated class MockPackageManager extends android.content.pm.PackageManager {
     method public deprecated java.lang.String getDefaultBrowserPackageName(int);
     method public deprecated boolean setDefaultBrowserPackageName(java.lang.String, int);
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 72e8c3b..d45bc5d 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -47,7 +47,6 @@
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -79,7 +78,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
 
 public class Am extends BaseCommand {
@@ -159,6 +157,7 @@
                 "       am stack start <DISPLAY_ID> <INTENT>\n" +
                 "       am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
                 "       am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
+                "       am stack resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
                 "       am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]\n" +
                 "       am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]\n" +
                 "       am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
@@ -1688,6 +1687,9 @@
             case "resize":
                 runStackResize();
                 break;
+            case "resize-animated":
+                runStackResizeAnimated();
+                break;
             case "resize-docked-stack":
                 runStackResizeDocked();
                 break;
@@ -1756,7 +1758,18 @@
             System.err.println("Error: invalid input bounds");
             return;
         }
-        resizeStack(stackId, bounds, 0);
+        resizeStack(stackId, bounds, 0, false);
+    }
+
+    private void runStackResizeAnimated() throws Exception {
+        String stackIdStr = nextArgRequired();
+        int stackId = Integer.valueOf(stackIdStr);
+        final Rect bounds = getBounds();
+        if (bounds == null) {
+            System.err.println("Error: invalid input bounds");
+            return;
+        }
+        resizeStack(stackId, bounds, 0, true);
     }
 
     private void runStackResizeDocked() throws Exception {
@@ -1773,14 +1786,15 @@
         }
     }
 
-    private void resizeStack(int stackId, Rect bounds, int delayMs) throws Exception {
+    private void resizeStack(int stackId, Rect bounds, int delayMs, boolean animate)
+            throws Exception {
         if (bounds == null) {
             showError("Error: invalid input bounds");
             return;
         }
 
         try {
-            mAm.resizeStack(stackId, bounds, false);
+            mAm.resizeStack(stackId, bounds, false, false, animate);
             Thread.sleep(delayMs);
         } catch (RemoteException e) {
             showError("Error: resizing stack " + e);
@@ -1894,7 +1908,7 @@
             maxChange = Math.min(stepSize, currentPoint - minPoint);
             currentPoint -= maxChange;
             setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+            resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
         }
 
         System.out.println("Growing docked stack side=" + side);
@@ -1902,7 +1916,7 @@
             maxChange = Math.min(stepSize, maxPoint - currentPoint);
             currentPoint += maxChange;
             setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+            resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
         }
 
         System.out.println("Back to Original size side=" + side);
@@ -1910,7 +1924,7 @@
             maxChange = Math.min(stepSize, currentPoint - startPoint);
             currentPoint -= maxChange;
             setBoundsSide(bounds, side, currentPoint);
-            resizeStack(DOCKED_STACK_ID, bounds, delayMs);
+            resizeStack(DOCKED_STACK_ID, bounds, delayMs, false);
         }
     }
 
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 8bc17f8..be93926 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -49,7 +49,8 @@
 import java.util.List;
 
 /**
- * An accessibility service runs in the background and receives callbacks by the system
+ * Accessibility services are intended to assist users with disabilities in using
+ * Android devices and apps. They run in the background and receive callbacks by the system
  * when {@link AccessibilityEvent}s are fired. Such events denote some state transition
  * in the user interface, for example, the focus has changed, a button has been clicked,
  * etc. Such a service can optionally request the capability for querying the content
@@ -66,22 +67,31 @@
  * <h3>Lifecycle</h3>
  * <p>
  * The lifecycle of an accessibility service is managed exclusively by the system and
- * follows the established service life cycle. Additionally, starting or stopping an
- * accessibility service is triggered exclusively by an explicit user action through
- * enabling or disabling it in the device settings. After the system binds to a service it
- * calls {@link AccessibilityService#onServiceConnected()}. This method can be
- * overriden by clients that want to perform post binding setup.
+ * follows the established service life cycle. Starting an accessibility service is triggered
+ * exclusively by the user explicitly turning the service on in device settings. After the system
+ * binds to a service, it calls {@link AccessibilityService#onServiceConnected()}. This method can
+ * be overriden by clients that want to perform post binding setup.
+ * </p>
+ * <p>
+ * An accessibility service stops either when the user turns it off in device settings or when
+ * it calls {@link AccessibilityService#disableSelf()}.
  * </p>
  * <h3>Declaration</h3>
  * <p>
- * An accessibility is declared as any other service in an AndroidManifest.xml but it
- * must also specify that it handles the "android.accessibilityservice.AccessibilityService"
- * {@link android.content.Intent}. Failure to declare this intent will cause the system to
- * ignore the accessibility service. Additionally an accessibility service must request the
- * {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission to ensure
- * that only the system
- * can bind to it. Failure to declare this intent will cause the system to ignore the
- * accessibility service. Following is an example declaration:
+ * An accessibility is declared as any other service in an AndroidManifest.xml, but it
+ * must do two things:
+ * <ul>
+ *     <ol>
+ *         Specify that it handles the "android.accessibilityservice.AccessibilityService"
+ *         {@link android.content.Intent}.
+ *     </ol>
+ *     <ol>
+ *         Request the {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission to
+ *         ensure that only the system can bind to it.
+ *     </ol>
+ * </ul>
+ * If either of these items is missing, the system will ignore the accessibility service.
+ * Following is an example declaration:
  * </p>
  * <pre> &lt;service android:name=".MyAccessibilityService"
  *         android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"&gt;
@@ -135,48 +145,24 @@
  * </ul>
  * <h3>Retrieving window content</h3>
  * <p>
- * A service can specify in its declaration that it can retrieve the active window
- * content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that
+ * A service can specify in its declaration that it can retrieve window
+ * content which is represented as a tree of {@link AccessibilityWindowInfo} and
+ * {@link AccessibilityNodeInfo} objects. Note that
  * declaring this capability requires that the service declares its configuration via
  * an XML resource referenced by {@link #SERVICE_META_DATA}.
  * </p>
  * <p>
- * For security purposes an accessibility service can retrieve only the content of the
- * currently active window. The currently active window is defined as the window from
- * which was fired the last event of the following types:
- * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED},
- * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
- * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
- * In other words, the last window that was shown or the last window that the user has touched
- * during touch exploration.
- * </p>
- * <p>
- * The entry point for retrieving window content is through calling
- * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()} of the last received
- * event of the above types or a previous event from the same window
- * (see {@link AccessibilityEvent#getWindowId() AccessibilityEvent.getWindowId()}). Invoking
- * this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the
- * window content which represented as a tree of such objects.
+ * Window content may be retrieved with
+ * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()},
+ * {@link AccessibilityService#findFocus(int)},
+ * {@link AccessibilityService#getWindows()}, or
+ * {@link AccessibilityService#getRootInActiveWindow()}.
  * </p>
  * <p class="note">
  * <strong>Note</strong> An accessibility service may have requested to be notified for
- * a subset of the event types, thus be unaware that the active window has changed. Therefore
- * accessibility service that would like to retrieve window content should:
- * <ul>
- * <li>
- * Register for all event types with no notification timeout and keep track for the active
- * window by calling {@link AccessibilityEvent#getWindowId()} of the last received event and
- * compare this with the {@link AccessibilityNodeInfo#getWindowId()} before calling retrieval
- * methods on the latter.
- * </li>
- * <li>
- * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the
- * active window has changed and the service did not get the accessibility event yet. Note
- * that it is possible to have a retrieval method failing even adopting the strategy
- * specified in the previous bullet because the accessibility event dispatch is asynchronous
- * and crosses process boundaries.
- * </li>
- * </ul>
+ * a subset of the event types, and thus be unaware when the node hierarchy has changed. It is also
+ * possible for a node to contain outdated information because the window content may change at any
+ * time.
  * </p>
  * <h3>Notification strategy</h3>
  * <p>
@@ -328,7 +314,6 @@
      *     android:settingsActivity="foo.bar.TestBackActivity"
      *     android:canRetrieveWindowContent="true"
      *     android:canRequestTouchExplorationMode="true"
-     *     android:canRequestEnhancedWebAccessibility="true"
      *     . . .
      * /&gt;</pre>
      */
@@ -528,6 +513,14 @@
      * is currently touching or the window with input focus, if the user is not
      * touching any window.
      * <p>
+     * The currently active window is defined as the window that most recently fired one
+     * of the following events:
+     * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED},
+     * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
+     * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}.
+     * In other words, the last window shown that also has input focus.
+     * </p>
+     * <p>
      * <strong>Note:</strong> In order to access the root node your service has
      * to declare the capability to retrieve window content by setting the
      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
@@ -541,8 +534,8 @@
     }
 
     /**
-     * This method allows accessibility service turn itself off
-     * and the service will become disabled from the Settings.
+     * Disables the service. After calling this method, the service will be disabled and settings
+     * will show that it is turned off.
      */
     public final void disableSelf() {
         final IAccessibilityServiceConnection connection =
@@ -1054,7 +1047,7 @@
      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
      * Also the service has to opt-in to retrieve the interactive windows by
      * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
-     * flag.Otherwise, the search will be performed only in the active window.
+     * flag. Otherwise, the search will be performed only in the active window.
      * </p>
      *
      * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e36a427..dc3f64a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2313,7 +2313,7 @@
      * <p>In order to use a Toolbar within the Activity's window content the application
      * must not request the window feature {@link Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p>
      *
-     * @param toolbar Toolbar to set as the Activity's action bar
+     * @param toolbar Toolbar to set as the Activity's action bar, or {@code null} to clear it
      */
     public void setActionBar(@Nullable Toolbar toolbar) {
         final ActionBar ab = getActionBar();
@@ -2332,10 +2332,17 @@
             ab.onDestroy();
         }
 
-        ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this);
-        mActionBar = tbab;
-        mWindow.setCallback(tbab.getWrappedWindowCallback());
-        mActionBar.invalidateOptionsMenu();
+        if (toolbar != null) {
+            final ToolbarActionBar tbab = new ToolbarActionBar(toolbar, getTitle(), this);
+            mActionBar = tbab;
+            mWindow.setCallback(tbab.getWrappedWindowCallback());
+        } else {
+            mActionBar = null;
+            // Re-set the original window callback since we may have already set a Toolbar wrapper
+            mWindow.setCallback(this);
+        }
+
+        invalidateOptionsMenu();
     }
 
     /**
@@ -4390,7 +4397,7 @@
             String resolvedType = null;
             if (fillInIntent != null) {
                 fillInIntent.migrateExtraStreamToClipData();
-                fillInIntent.prepareToLeaveProcess();
+                fillInIntent.prepareToLeaveProcess(this);
                 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
             }
             int result = ActivityManagerNative.getDefault()
@@ -4622,7 +4629,7 @@
                     intent.putExtra(Intent.EXTRA_REFERRER, referrer);
                 }
                 intent.migrateExtraStreamToClipData();
-                intent.prepareToLeaveProcess();
+                intent.prepareToLeaveProcess(this);
                 result = ActivityManagerNative.getDefault()
                     .startActivity(mMainThread.getApplicationThread(), getBasePackageName(),
                             intent, intent.resolveTypeIfNeeded(getContentResolver()), mToken,
@@ -4693,7 +4700,7 @@
         if (mParent == null) {
             try {
                 intent.migrateExtraStreamToClipData();
-                intent.prepareToLeaveProcess();
+                intent.prepareToLeaveProcess(this);
                 return ActivityManagerNative.getDefault()
                     .startNextMatchingActivity(mToken, intent, options);
             } catch (RemoteException e) {
@@ -5121,7 +5128,7 @@
             if (false) Log.v(TAG, "Finishing self: token=" + mToken);
             try {
                 if (resultData != null) {
-                    resultData.prepareToLeaveProcess();
+                    resultData.prepareToLeaveProcess(this);
                 }
                 if (ActivityManagerNative.getDefault()
                         .finishActivity(mToken, resultCode, resultData, finishTask)) {
@@ -5348,7 +5355,7 @@
             @PendingIntent.Flags int flags) {
         String packageName = getPackageName();
         try {
-            data.prepareToLeaveProcess();
+            data.prepareToLeaveProcess(this);
             IIntentSender target =
                 ActivityManagerNative.getDefault().getIntentSender(
                         ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName,
@@ -6328,10 +6335,10 @@
                 resultData = mResultData;
             }
             if (resultData != null) {
-                resultData.prepareToLeaveProcess();
+                resultData.prepareToLeaveProcess(this);
             }
             try {
-                upIntent.prepareToLeaveProcess();
+                upIntent.prepareToLeaveProcess(this);
                 return ActivityManagerNative.getDefault().navigateUpTo(mToken, upIntent,
                         resultCode, resultData);
             } catch (RemoteException e) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 420bf31..90feab4 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -564,8 +564,7 @@
          * there isn't a display gap.
          */
         public static boolean preserveWindowOnTaskMove(int stackId) {
-            return stackId == FULLSCREEN_WORKSPACE_STACK_ID
-                    || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
+            return stackId == FULLSCREEN_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
         }
 
         /**
@@ -616,6 +615,14 @@
         public static boolean keepVisibleDeadAppWindowOnScreen(int stackId) {
             return stackId != PINNED_STACK_ID;
         }
+
+        /**
+         * Returns true if the backdrop on the client side should match the frame of the window.
+         * Returns false, if the backdrop should be fullscreen.
+         */
+        public static boolean useWindowFrameForBackdrop(int stackId) {
+            return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == PINNED_STACK_ID;
+        }
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 42ff8e8..cd5797e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -816,7 +816,9 @@
                 r = Rect.CREATOR.createFromParcel(data);
             }
             final boolean allowResizeInDockedMode = data.readInt() == 1;
-            resizeStack(stackId, r, allowResizeInDockedMode);
+            final boolean preserveWindows = data.readInt() == 1;
+            final boolean animate = data.readInt() == 1;
+            resizeStack(stackId, r, allowResizeInDockedMode, preserveWindows, animate);
             reply.writeNoException();
             return true;
         }
@@ -3815,9 +3817,8 @@
         return res;
     }
     @Override
-    public void resizeStack(int stackId, Rect r, boolean allowResizeInDockedMode)
-            throws RemoteException
-    {
+    public void resizeStack(int stackId, Rect r, boolean allowResizeInDockedMode,
+            boolean preserveWindows, boolean animate) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -3829,6 +3830,8 @@
             data.writeInt(0);
         }
         data.writeInt(allowResizeInDockedMode ? 1 : 0);
+        data.writeInt(preserveWindows ? 1 : 0);
+        data.writeInt(animate ? 1 : 0);
         mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1e7457c..100e67b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -56,6 +56,7 @@
 import android.opengl.GLUtils;
 import android.os.AsyncTask;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.DropBoxManager;
@@ -4959,16 +4960,22 @@
         }
 
         /**
-         * For apps targetting SDK Honeycomb or later, we don't allow
-         * network usage on the main event loop / UI thread.
-         *
-         * Note to those grepping:  this is what ultimately throws
-         * NetworkOnMainThreadException ...
+         * For apps targetting Honeycomb or later, we don't allow network usage
+         * on the main event loop / UI thread. This is what ultimately throws
+         * {@link NetworkOnMainThreadException}.
          */
-        if (data.appInfo.targetSdkVersion > 9) {
+        if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
             StrictMode.enableDeathOnNetwork();
         }
 
+        /**
+         * For apps targetting N or later, we don't allow file:// Uri exposure.
+         * This is what ultimately throws {@link FileUriExposedException}.
+         */
+        if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
+            StrictMode.enableDeathOnFileUriExposure();
+        }
+
         NetworkSecurityPolicy.getInstance().setCleartextTrafficPermitted(
                 (data.appInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0);
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index fab3740..0d6e93d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -752,7 +752,7 @@
             String resolvedType = null;
             if (fillInIntent != null) {
                 fillInIntent.migrateExtraStreamToClipData();
-                fillInIntent.prepareToLeaveProcess();
+                fillInIntent.prepareToLeaveProcess(this);
                 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
             }
             int result = ActivityManagerNative.getDefault()
@@ -773,7 +773,7 @@
         warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                     mMainThread.getApplicationThread(), intent, resolvedType, null,
                     Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
@@ -790,7 +790,7 @@
         String[] receiverPermissions = receiverPermission == null ? null
                 : new String[] {receiverPermission};
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                     mMainThread.getApplicationThread(), intent, resolvedType, null,
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
@@ -805,7 +805,7 @@
         warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                     mMainThread.getApplicationThread(), intent, resolvedType, null,
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
@@ -822,7 +822,7 @@
         String[] receiverPermissions = receiverPermission == null ? null
                 : new String[] {receiverPermission};
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                     mMainThread.getApplicationThread(), intent, resolvedType, null,
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
@@ -839,7 +839,7 @@
         String[] receiverPermissions = receiverPermission == null ? null
                 : new String[] {receiverPermission};
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                     mMainThread.getApplicationThread(), intent, resolvedType, null,
                     Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
@@ -856,7 +856,7 @@
         String[] receiverPermissions = receiverPermission == null ? null
                 : new String[] {receiverPermission};
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                     mMainThread.getApplicationThread(), intent, resolvedType, null,
                     Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
@@ -919,7 +919,7 @@
         String[] receiverPermissions = receiverPermission == null ? null
                 : new String[] {receiverPermission};
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, receiverPermissions, appOp,
@@ -933,7 +933,7 @@
     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(),
                     intent, resolvedType, null, Activity.RESULT_OK, null, null, null,
                     AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
@@ -955,7 +955,7 @@
         String[] receiverPermissions = receiverPermission == null ? null
                 : new String[] {receiverPermission};
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                     mMainThread.getApplicationThread(), intent, resolvedType, null,
                     Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
@@ -1006,7 +1006,7 @@
         String[] receiverPermissions = receiverPermission == null ? null
                 : new String[] {receiverPermission};
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, receiverPermissions,
@@ -1022,7 +1022,7 @@
         warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
@@ -1058,7 +1058,7 @@
         }
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, null,
@@ -1077,7 +1077,7 @@
             intent.setDataAndType(intent.getData(), resolvedType);
         }
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().unbroadcastIntent(
                     mMainThread.getApplicationThread(), intent, getUserId());
         } catch (RemoteException e) {
@@ -1090,7 +1090,7 @@
     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
@@ -1105,7 +1105,7 @@
     public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, null,
                 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, options, false, true,
@@ -1140,7 +1140,7 @@
         }
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().broadcastIntent(
                 mMainThread.getApplicationThread(), intent, resolvedType, rd,
                 initialCode, initialData, initialExtras, null,
@@ -1159,7 +1159,7 @@
             intent.setDataAndType(intent.getData(), resolvedType);
         }
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(this);
             ActivityManagerNative.getDefault().unbroadcastIntent(
                     mMainThread.getApplicationThread(), intent, user.getIdentifier());
         } catch (RemoteException e) {
@@ -1262,7 +1262,7 @@
     private ComponentName startServiceCommon(Intent service, UserHandle user) {
         try {
             validateServiceIntent(service);
-            service.prepareToLeaveProcess();
+            service.prepareToLeaveProcess(this);
             ComponentName cn = ActivityManagerNative.getDefault().startService(
                 mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                             getContentResolver()), getOpPackageName(), user.getIdentifier());
@@ -1291,7 +1291,7 @@
     private boolean stopServiceCommon(Intent service, UserHandle user) {
         try {
             validateServiceIntent(service);
-            service.prepareToLeaveProcess();
+            service.prepareToLeaveProcess(this);
             int res = ActivityManagerNative.getDefault().stopService(
                 mMainThread.getApplicationThread(), service,
                 service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
@@ -1339,7 +1339,7 @@
                     < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                 flags |= BIND_WAIVE_PRIORITY;
             }
-            service.prepareToLeaveProcess();
+            service.prepareToLeaveProcess(this);
             int res = ActivityManagerNative.getDefault().bindService(
                 mMainThread.getApplicationThread(), getActivityToken(), service,
                 service.resolveTypeIfNeeded(getContentResolver()),
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 22de2ff..5b3ffe0 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -146,8 +146,8 @@
     public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
             Rect initialBounds) throws RemoteException;
     public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) throws RemoteException;
-    public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode)
-            throws RemoteException;
+    public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
+            boolean preserveWindows, boolean animate) throws RemoteException;
 
     /**
      * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 2caec369..7640e75 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -33,7 +33,7 @@
  * {@hide}
  */
 interface IUiAutomationConnection {
-    void connect(IAccessibilityServiceClient client);
+    void connect(IAccessibilityServiceClient client, int flags);
     void disconnect();
     boolean injectInputEvent(in InputEvent event, boolean sync);
     boolean setRotation(int rotation);
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 7a0e7f6..fa0fbd1 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -35,10 +35,16 @@
      * 'which' is some combination of:
      *   FLAG_SET_SYSTEM
      *   FLAG_SET_LOCK
+     *
+     * A 'null' cropHint rectangle is explicitly permitted as a sentinel for "whatever
+     * the source image's bounding rect is."
+     *
+     * The completion callback's "onWallpaperChanged()" method is invoked when the
+     * new wallpaper content is ready to display.
      */
     ParcelFileDescriptor setWallpaper(String name, in String callingPackage,
-            out Bundle extras, int which);
-    
+            in Rect cropHint, out Bundle extras, int which, IWallpaperManagerCallback completion);
+
     /**
      * Set the live wallpaper. This only affects the system wallpaper.
      */
@@ -54,14 +60,14 @@
      */
     ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
             out Bundle outParams);
-    
+
     /**
      * If the current system wallpaper is a live wallpaper component, return the
      * information about that wallpaper.  Otherwise, if it is a static image,
      * simply return null.
      */
     WallpaperInfo getWallpaperInfo();
-    
+
     /**
      * Clear the system wallpaper.
      */
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 24a3470..9a88f2c 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1503,7 +1503,7 @@
         }
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(who);
             int result = ActivityManagerNative.getDefault()
                 .startActivity(whoThread, who.getBasePackageName(), intent,
                         intent.resolveTypeIfNeeded(who.getContentResolver()),
@@ -1561,7 +1561,7 @@
             String[] resolvedTypes = new String[intents.length];
             for (int i=0; i<intents.length; i++) {
                 intents[i].migrateExtraStreamToClipData();
-                intents[i].prepareToLeaveProcess();
+                intents[i].prepareToLeaveProcess(who);
                 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
             }
             int result = ActivityManagerNative.getDefault()
@@ -1622,7 +1622,7 @@
         }
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(who);
             int result = ActivityManagerNative.getDefault()
                 .startActivity(whoThread, who.getBasePackageName(), intent,
                         intent.resolveTypeIfNeeded(who.getContentResolver()),
@@ -1682,7 +1682,7 @@
         }
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(who);
             int result = ActivityManagerNative.getDefault()
                 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
                         intent.resolveTypeIfNeeded(who.getContentResolver()),
@@ -1721,7 +1721,7 @@
         }
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(who);
             int result = ActivityManagerNative.getDefault()
                 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
                         intent.resolveTypeIfNeeded(who.getContentResolver()),
@@ -1759,7 +1759,7 @@
         }
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(who);
             int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
                     intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
             checkStartActivityResult(result, intent);
@@ -1837,16 +1837,59 @@
      * {@link Instrumentation} APIs. Using both APIs at the same time is not
      * a mistake by itself but a client has to be aware of the APIs limitations.
      * </p>
-     * @return The UI automation instance.
+     * @return The UI automation instance. If none exists, a new one is created with no flags set.
      *
      * @see UiAutomation
      */
     public UiAutomation getUiAutomation() {
         if (mUiAutomationConnection != null) {
             if (mUiAutomation == null) {
+                return getUiAutomation(0);
+            }
+            return mUiAutomation;
+        }
+        return null;
+    }
+
+    /**
+     * Gets the {@link UiAutomation} instance with flags set.
+     * <p>
+     * <strong>Note:</strong> Only one UiAutomation can be obtained. Calling this method
+     * twice with different flags will fail unless the UiAutomation obtained in the first call
+     * is released with {@link UiAutomation#destroy()}.
+     * </p>
+     * <p>
+     * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
+     * work across application boundaries while the APIs exposed by the instrumentation
+     * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
+     * not allow you to inject the event in an app different from the instrumentation
+     * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
+     * will work regardless of the current application.
+     * </p>
+     * <p>
+     * A typical test case should be using either the {@link UiAutomation} or
+     * {@link Instrumentation} APIs. Using both APIs at the same time is not
+     * a mistake by itself but a client has to be aware of the APIs limitations.
+     * </p>
+     *
+     * @param flags The flags to be passed to the UiAutomation, for example
+     *        {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
+     *
+     * @return The UI automation instance.
+     *
+     * @see UiAutomation
+     */
+    public UiAutomation getUiAutomation(int flags) {
+        if (mUiAutomationConnection != null) {
+            if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
                 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
                         mUiAutomationConnection);
-                mUiAutomation.connect();
+                mUiAutomation.connect(flags);
+            } else {
+                if (mUiAutomation.getFlags() != flags) {
+                    throw new RuntimeException(
+                            "Cannot get a UiAutomation with different flags from the existing one");
+                }
             }
             return mUiAutomation;
         }
@@ -1861,8 +1904,8 @@
             try {
                 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
             } catch (RuntimeException e) {
-                Log.w(TAG, "Exception setting priority of instrumentation thread "                                            
-                        + Process.myTid(), e);                                                                             
+                Log.w(TAG, "Exception setting priority of instrumentation thread "
+                        + Process.myTid(), e);
             }
             if (mAutomaticPerformanceSnapshots) {
                 startPerformanceSnapshot();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0f3aad9..7f037f2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4384,7 +4384,17 @@
                     view.addView(com.android.internal.R.id.media_actions, button);
                 }
             }
-            handleImage(view  /* addPaddingToMainColumn */);
+            handleImage(view);
+            // handle the content margin
+            int endMargin;
+            if (mBuilder.mN.mLargeIcon != null) {
+                endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
+                        R.dimen.notification_content_picture_margin_media);
+            } else {
+                endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
+                        R.dimen.notification_content_margin_end);
+            }
+            view.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
             return view;
         }
 
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index edafe59..412b098 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -307,7 +307,7 @@
                 context.getContentResolver()) : null;
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(context);
             IIntentSender target =
                 ActivityManagerNative.getDefault().getIntentSender(
                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
@@ -332,7 +332,7 @@
                 context.getContentResolver()) : null;
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(context);
             IIntentSender target =
                 ActivityManagerNative.getDefault().getIntentSender(
                     ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
@@ -446,7 +446,7 @@
         String[] resolvedTypes = new String[intents.length];
         for (int i=0; i<intents.length; i++) {
             intents[i].migrateExtraStreamToClipData();
-            intents[i].prepareToLeaveProcess();
+            intents[i].prepareToLeaveProcess(context);
             resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
         }
         try {
@@ -472,7 +472,7 @@
         String[] resolvedTypes = new String[intents.length];
         for (int i=0; i<intents.length; i++) {
             intents[i].migrateExtraStreamToClipData();
-            intents[i].prepareToLeaveProcess();
+            intents[i].prepareToLeaveProcess(context);
             resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
         }
         try {
@@ -527,7 +527,7 @@
         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
                 context.getContentResolver()) : null;
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(context);
             IIntentSender target =
                 ActivityManagerNative.getDefault().getIntentSender(
                     ActivityManager.INTENT_SENDER_BROADCAST, packageName,
@@ -570,7 +570,7 @@
         String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
                 context.getContentResolver()) : null;
         try {
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(context);
             IIntentSender target =
                 ActivityManagerNative.getDefault().getIntentSender(
                     ActivityManager.INTENT_SENDER_SERVICE, packageName,
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 8035c56..5eed781 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.ISoundTriggerService;
 import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.os.IDropBoxManagerService;
 
@@ -61,6 +62,7 @@
 import android.media.midi.MidiManager;
 import android.media.projection.MediaProjectionManager;
 import android.media.session.MediaSessionManager;
+import android.media.soundtrigger.SoundTriggerManager;
 import android.media.tv.ITvInputManager;
 import android.media.tv.TvInputManager;
 import android.net.ConnectivityManager;
@@ -85,6 +87,7 @@
 import android.nfc.NfcManager;
 import android.os.BatteryManager;
 import android.os.DropBoxManager;
+import android.os.HardwarePropertiesManager;
 import android.os.IBinder;
 import android.os.IPowerManager;
 import android.os.IUserManager;
@@ -707,6 +710,22 @@
             public RadioManager createService(ContextImpl ctx) {
                 return new RadioManager(ctx);
             }});
+
+        registerService(Context.HARDWARE_PROPERTIES_SERVICE, HardwarePropertiesManager.class,
+                new CachedServiceFetcher<HardwarePropertiesManager>() {
+            @Override
+            public HardwarePropertiesManager createService(ContextImpl ctx) {
+                return new HardwarePropertiesManager();
+            }});
+
+        registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class,
+                new CachedServiceFetcher<SoundTriggerManager>() {
+            @Override
+            public SoundTriggerManager createService(ContextImpl ctx) {
+                IBinder b = ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE);
+                Log.i(TAG, "Creating new instance of SoundTriggerManager object.");
+                return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b));
+            }});
     }
 
     /**
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index dce2e51..79d383c 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -105,6 +105,14 @@
     /** Rotation constant: Freeze rotation to 270 degrees . */
     public static final int ROTATION_FREEZE_270 = Surface.ROTATION_270;
 
+    /**
+     * UiAutomation supresses accessibility services by default. This flag specifies that
+     * existing accessibility services should continue to run, and that new ones may start.
+     * This flag is set when obtaining the UiAutomation from
+     * {@link Instrumentation#getUiAutomation(int)}.
+     */
+    public static final int FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES = 0x00000001;
+
     private final Object mLock = new Object();
 
     private final ArrayList<AccessibilityEvent> mEventQueue = new ArrayList<AccessibilityEvent>();
@@ -123,6 +131,10 @@
 
     private boolean mIsConnecting;
 
+    private boolean mIsDestroyed;
+
+    private int mFlags;
+
     /**
      * Listener for observing the {@link AccessibilityEvent} stream.
      */
@@ -182,11 +194,22 @@
     }
 
     /**
-     * Connects this UiAutomation to the accessibility introspection APIs.
+     * Connects this UiAutomation to the accessibility introspection APIs with default flags.
      *
      * @hide
      */
     public void connect() {
+        connect(0);
+    }
+
+    /**
+     * Connects this UiAutomation to the accessibility introspection APIs.
+     *
+     * @param flags Any flags to apply to the automation as it gets connected
+     *
+     * @hide
+     */
+    public void connect(int flags) {
         synchronized (mLock) {
             throwIfConnectedLocked();
             if (mIsConnecting) {
@@ -197,7 +220,8 @@
 
         try {
             // Calling out without a lock held.
-            mUiAutomationConnection.connect(mClient);
+            mUiAutomationConnection.connect(mClient, flags);
+            mFlags = flags;
         } catch (RemoteException re) {
             throw new RuntimeException("Error while connecting UiAutomation", re);
         }
@@ -227,6 +251,17 @@
     }
 
     /**
+     * Get the flags used to connect the service.
+     *
+     * @return The flags used to connect
+     *
+     * @hide
+     */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /**
      * Disconnects this UiAutomation from the accessibility introspection APIs.
      *
      * @hide
@@ -263,6 +298,17 @@
     }
 
     /**
+     * Reports if the object has been destroyed
+     *
+     * @return {code true} if the object has been destroyed.
+     *
+     * @hide
+     */
+    public boolean isDestroyed() {
+        return mIsDestroyed;
+    }
+
+    /**
      * Sets a callback for observing the stream of {@link AccessibilityEvent}s.
      *
      * @param listener The callback.
@@ -274,6 +320,15 @@
     }
 
     /**
+     * Destroy this UiAutomation. After calling this method, attempting to use the object will
+     * result in errors.
+     */
+    public void destroy() {
+        disconnect();
+        mIsDestroyed = true;
+    }
+
+    /**
      * Performs a global action. Such an action can be performed at any moment
      * regardless of the current application or user location in that application.
      * For example going back, going home, opening recents, etc.
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index bd10267..276f774 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -77,7 +77,7 @@
 
     private int mOwningUid;
 
-    public void connect(IAccessibilityServiceClient client) {
+    public void connect(IAccessibilityServiceClient client, int flags) {
         if (client == null) {
             throw new IllegalArgumentException("Client cannot be null!");
         }
@@ -87,7 +87,7 @@
                 throw new IllegalStateException("Already connected.");
             }
             mOwningUid = Binder.getCallingUid();
-            registerUiTestAutomationServiceLocked(client);
+            registerUiTestAutomationServiceLocked(client, flags);
             storeRotationStateLocked();
         }
     }
@@ -322,7 +322,8 @@
         }
     }
 
-    private void registerUiTestAutomationServiceLocked(IAccessibilityServiceClient client) {
+    private void registerUiTestAutomationServiceLocked(IAccessibilityServiceClient client,
+            int flags) {
         IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
                 ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
         AccessibilityServiceInfo info = new AccessibilityServiceInfo();
@@ -337,7 +338,7 @@
         try {
             // Calling out with a lock held is fine since if the system
             // process is gone the client calling in will be killed.
-            manager.registerUiTestAutomationService(mToken, client, info);
+            manager.registerUiTestAutomationService(mToken, client, info, flags);
             mClient = client;
         } catch (RemoteException re) {
             throw new IllegalStateException("Error while registering UiTestAutomationService.", re);
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index f103576..b0ffd21 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -64,6 +64,8 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Provides access to the system wallpaper. With WallpaperManager, you can
@@ -770,18 +772,26 @@
             return 0;
         }
         final Bundle result = new Bundle();
+        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
         try {
             Resources resources = mContext.getResources();
             /* Set the wallpaper to the default values */
             ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(
                     "res:" + resources.getResourceName(resid),
-                    mContext.getOpPackageName(), result, which);
+                    mContext.getOpPackageName(), null, result, which, completion);
             if (fd != null) {
                 FileOutputStream fos = null;
+                boolean ok = false;
                 try {
                     fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                     copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
+                    // The 'close()' is the trigger for any server-side image manipulation,
+                    // so we must do that before waiting for completion.
+                    fos.close();
+                    completion.waitForCompletion();
                 } finally {
+                    // Might be redundant but completion shouldn't wait unless the write
+                    // succeeded; this is a fallback if it threw past the close+wait.
                     IoUtils.closeQuietly(fos);
                 }
             }
@@ -876,14 +886,17 @@
             return 0;
         }
         final Bundle result = new Bundle();
+        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
         try {
             ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
-                    mContext.getOpPackageName(), result, which);
+                    mContext.getOpPackageName(), visibleCropHint, result, which, completion);
             if (fd != null) {
                 FileOutputStream fos = null;
                 try {
                     fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                     fullImage.compress(Bitmap.CompressFormat.PNG, 90, fos);
+                    fos.close();
+                    completion.waitForCompletion();
                 } finally {
                     IoUtils.closeQuietly(fos);
                 }
@@ -990,14 +1003,17 @@
             return 0;
         }
         final Bundle result = new Bundle();
+        final WallpaperSetCompletion completion = new WallpaperSetCompletion();
         try {
             ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
-                    mContext.getOpPackageName(), result, which);
+                    mContext.getOpPackageName(), visibleCropHint, result, which, completion);
             if (fd != null) {
                 FileOutputStream fos = null;
                 try {
                     fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                     copyStreamToWallpaperFile(bitmapData, fos);
+                    fos.close();
+                    completion.waitForCompletion();
                 } finally {
                     IoUtils.closeQuietly(fos);
                 }
@@ -1385,4 +1401,28 @@
 
         return null;
     }
+
+    // Private completion callback for setWallpaper() synchronization
+    private class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub {
+        final CountDownLatch mLatch;
+
+        public WallpaperSetCompletion() {
+            mLatch = new CountDownLatch(1);
+        }
+
+        public void waitForCompletion() {
+            try {
+                mLatch.await(30, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                // This might be legit: the crop may take a very long time. Don't sweat
+                // it in that case; we are okay with display lagging behind in order to
+                // keep the caller from locking up indeterminately.
+            }
+        }
+
+        @Override
+        public void onWallpaperChanged() throws RemoteException {
+            mLatch.countDown();
+        }
+    }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index dc49c7c..c79c407 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -30,6 +30,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
 import android.net.ProxyInfo;
 import android.net.Uri;
@@ -2770,6 +2771,45 @@
     }
 
     /**
+     * Called by a device owner to set whether all users created on the device should be ephemeral.
+     *
+     * <p>The system user is exempt from this policy - it is never ephemeral.
+     *
+     * <p>The calling device admin must be the device owner. If it is not, a security exception will
+     * be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param forceEphemeralUsers If true, all the existing users will be deleted and all
+     *         subsequently created users will be ephemeral.
+     * @hide
+     */
+    public void setForceEphemeralUsers(
+            @NonNull ComponentName admin, boolean forceEphemeralUsers) {
+        if (mService != null) {
+            try {
+                mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+    }
+
+    /**
+     * @return true if all users are created ephemeral.
+     * @hide
+     */
+    public boolean getForceEphemeralUsers(@NonNull ComponentName admin) {
+        if (mService != null) {
+            try {
+                return mService.getForceEphemeralUsers(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by an application that is administering the device to disable keyguard customizations,
      * such as widgets. After setting this, keyguard features will be disabled according to the
      * provided feature list.
@@ -2934,6 +2974,34 @@
     }
 
     /**
+     * Should be called when keyguard has been dismissed.
+     * @hide
+     */
+    public void reportKeyguardDismissed() {
+        if (mService != null) {
+            try {
+                mService.reportKeyguardDismissed();
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+    }
+
+    /**
+     * Should be called when keyguard view has been shown to the user.
+     * @hide
+     */
+    public void reportKeyguardSecured() {
+        if (mService != null) {
+            try {
+                mService.reportKeyguardSecured();
+            } catch (RemoteException e) {
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+            }
+        }
+    }
+
+    /**
      * @hide
      * Sets the given package as the device owner.
      * Same as {@link #setDeviceOwner(ComponentName, String)} but without setting a device owner name.
@@ -3205,15 +3273,14 @@
     }
 
     /**
-     * @hide
      * Clears the active profile owner and removes all user restrictions. The caller must
      * be from the same package as the active profile owner for this user, otherwise a
      * SecurityException will be thrown.
      *
+     * <p>This doesn't work for managed profile owners.
+     *
      * @param admin The component to remove as the profile owner.
-     * @return
      */
-    @SystemApi
     public void clearProfileOwner(@NonNull ComponentName admin) {
         if (mService != null) {
             try {
@@ -3279,6 +3346,10 @@
      * <p>If the device owner information contains only whitespaces then the message on the lock
      * screen will be blank and the user will not be allowed to change it.
      *
+     * <p>If the device owner information needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
      * @param admin The name of the admin component to check.
      * @param info Device owner information which will be displayed instead of the user
      * owner info.
@@ -4207,6 +4278,13 @@
     public static final int SKIP_SETUP_WIZARD = 0x0001;
 
     /**
+     * Flag used by {@link #createAndManageUser} to specify that the user should be created
+     * ephemeral.
+     * @hide
+     */
+    public static final int MAKE_USER_EPHEMERAL = 0x0002;
+
+    /**
      * Called by a device owner to create a user with the specified name and a given component of
      * the calling package as profile owner. The UserHandle returned by this method should not be
      * persisted as user handles are recycled as users are removed and created. If you need to
@@ -5137,6 +5215,10 @@
      *  for support."
      * If the message is longer than 200 characters it may be truncated.
      *
+     * <p>If the short support message needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
      * @see #setLongSupportMessage
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -5176,6 +5258,10 @@
      * Called by a device admin to set the long support message. This will
      * be displayed to the user in the device administators settings screen.
      *
+     * <p>If the long support message needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
      * @see #setShortSupportMessage
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -5273,6 +5359,22 @@
     }
 
     /**
+     * Called by the system to obtain a {@link DevicePolicyManager} whose calls act on the parent
+     * profile.
+     *
+     * @hide
+     */
+    public DevicePolicyManager getParentProfileInstance(UserInfo uInfo) {
+        mContext.checkSelfPermission(
+                android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+        if (!uInfo.isManagedProfile()) {
+            throw new SecurityException("The user " + uInfo.id
+                    + " does not have a parent profile.");
+        }
+        return new DevicePolicyManager(mContext, true);
+    }
+
+    /**
      * Called by a profile owner of a managed profile to set the color used for customization.
      * This color is used as background color of the confirm credentials screen for that user.
      * The default color is {@link android.graphics.Color#GRAY}.
@@ -5324,6 +5426,58 @@
     }
 
     /**
+     * Called by a profile owner of a managed profile to set the name of the organization under
+     * management.
+     *
+     * <p>If the organization name needs to be localized, it is the responsibility of the
+     * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
+     * and set a new version of this string accordingly.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param title The organization name or {@code null} to clear a previously set name.
+     */
+    public void setOrganizationName(@NonNull ComponentName admin, @Nullable String title) {
+        try {
+            mService.setOrganizationName(admin, title);
+        } catch (RemoteException re) {
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+        }
+    }
+
+    /**
+     * Called by a profile owner of a managed profile to retrieve the name of the organization
+     * under management.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @return The organization name or {@code null} if none is set.
+     */
+    public String getOrganizationName(@NonNull ComponentName admin) {
+        try {
+            return mService.getOrganizationName(admin);
+        } catch (RemoteException re) {
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+            return null;
+        }
+    }
+
+    /**
+     * Retrieve the default title message used in the confirm credentials screen for a given user.
+     *
+     * @param userHandle The user id of the user we're interested in.
+     * @return The organization name or {@code null} if none is set.
+     *
+     * @hide
+     */
+    public String getOrganizationNameForUser(int userHandle) {
+        try {
+            return mService.getOrganizationNameForUser(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+            return null;
+        }
+    }
+
+    /**
      * @return the {@link UserProvisioningState} for the current user - for unmanaged users will
      *         return {@link #STATE_USER_UNMANAGED}
      * @hide
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a80ed9b..37d13e5 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -116,6 +116,9 @@
     void reportFailedPasswordAttempt(int userHandle);
     void reportSuccessfulPasswordAttempt(int userHandle);
 
+    void reportKeyguardDismissed();
+    void reportKeyguardSecured();
+
     boolean setDeviceOwner(in ComponentName who, String ownerName, int userId);
     ComponentName getDeviceOwnerComponent(boolean callingUserOnly);
     String getDeviceOwnerName();
@@ -230,6 +233,9 @@
     void setAutoTimeRequired(in ComponentName who, boolean required);
     boolean getAutoTimeRequired();
 
+    void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers);
+    boolean getForceEphemeralUsers(in ComponentName who);
+
     boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle);
 
     void setUserIcon(in ComponentName admin, in Bitmap icon);
@@ -270,6 +276,10 @@
     int getOrganizationColor(in ComponentName admin);
     int getOrganizationColorForUser(int userHandle);
 
+    void setOrganizationName(in ComponentName admin, in String title);
+    String getOrganizationName(in ComponentName admin);
+    String getOrganizationNameForUser(int userHandle);
+
     int getUserProvisioningState();
     void setUserProvisioningState(int state, int userHandle);
 
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index e8373a1..1a9bf4e 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -52,10 +52,12 @@
  * {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be
  * {@link NetworkStats.Bucket#ROAMING_ALL}.
  * <p />
- * <b>NOTE:</b> Accessing stats for apps other than the calling app requires the permission
- * {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, which is a system-level permission and
- * will not be granted to third-party apps. However, declaring the permission implies intention to
- * use the API and the user of the device can grant permission through the Settings application.
+ * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
+ * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
+ * which is a system-level permission and will not be granted to third-party apps. However,
+ * declaring the permission implies intention to use the API and the user of the device can grant
+ * permission through the Settings application.
+ * <p />
  * Profile owner apps are automatically granted permission to query data on the profile they manage
  * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
  * privileged apps likewise get access to usage data for all users on the device.
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0fce4e2..a88aa3125 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -165,14 +165,18 @@
                     mPackageName + "' with UsageStats for package '" + right.mPackageName + "'.");
         }
 
-        if (right.mEndTimeStamp > mEndTimeStamp) {
+        if (right.mBeginTimeStamp > mBeginTimeStamp) {
+            // The incoming UsageStat begins after this one, so use its last time used fields
+            // as the source of truth.
+            // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with
+            // regards to their mEndTimeStamp.
             mLastEvent = right.mLastEvent;
-            mEndTimeStamp = right.mEndTimeStamp;
             mLastTimeUsed = right.mLastTimeUsed;
             mBeginIdleTime = right.mBeginIdleTime;
             mLastTimeSystemUsed = right.mLastTimeSystemUsed;
         }
         mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
+        mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
         mTotalTimeInForeground += right.mTotalTimeInForeground;
         mLaunchCount += right.mLaunchCount;
     }
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 498ff81..b6f1567 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -19,6 +19,8 @@
 import android.content.ComponentName;
 import android.content.res.Configuration;
 
+import java.io.IOException;
+
 /**
  * UsageStatsManager local system service interface.
  *
@@ -109,4 +111,9 @@
         public abstract void onParoleStateChanged(boolean isParoleOn);
     }
 
+    /*  Backup/Restore API */
+    public abstract byte[] getBackupPayload(int user, String key);
+
+    public abstract void applyRestoredPayload(int user, String key, byte[] payload);
+
 }
diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/auditing/SecurityLog.java
index 87dc1d8..8d8d2f5 100644
--- a/core/java/android/auditing/SecurityLog.java
+++ b/core/java/android/auditing/SecurityLog.java
@@ -34,7 +34,8 @@
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({TAG_ADB_SHELL_INTERACTIVE, TAG_ADB_SHELL_CMD, TAG_SYNC_RECV_FILE, TAG_SYNC_SEND_FILE,
-        TAG_APP_PROCESS_START, TAG_DEVICE_UNLOCK_ATTEMPT, TAG_DEVICE_LOCKED})
+        TAG_APP_PROCESS_START, TAG_KEYGUARD_DISMISSED, TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT,
+        TAG_KEYGUARD_SECURED})
     public @interface SECURITY_LOG_TAG {}
 
     /**
@@ -68,21 +69,24 @@
      * seinfo tag (String), SHA-256 hash of the APK in hexadecimal (String)
      */
     public static final int TAG_APP_PROCESS_START = SecurityLogTags.SECURITY_APP_PROCESS_START;
-
     /**
-     * Indicate that there has been an attempt to unlock the device. The log entry contains the
-     * following information about the attempt in order, accessible via
-     * {@link SecurityEvent#getData()}}: unlock result (integer, 1 for successful unlock, 0 for
-     * unsuccessful), unlock method (String)
+     * Indicate that keyguard is being dismissed.
+     * There is no extra payload in the log event.
      */
-    public static final int TAG_DEVICE_UNLOCK_ATTEMPT =
-            SecurityLogTags.SECURITY_DEVICE_UNLOCK_ATTEMPT;
-
+    public static final int TAG_KEYGUARD_DISMISSED =
+            SecurityLogTags.SECURITY_KEYGUARD_DISMISSED;
+    /**
+     * Indicate that there has been an authentication attempt to dismiss the keyguard. The log entry
+     * contains the attempt result (integer, 1 for successful, 0 for unsuccessful), accessible via
+     * {@link SecurityEvent#getData()}}
+     */
+    public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT =
+            SecurityLogTags.SECURITY_KEYGUARD_DISMISS_AUTH_ATTEMPT;
     /**
      * Indicate that the device has been locked, either by user or by timeout.
+     * There is no extra payload in the log event.
      */
-    public static final int TAG_DEVICE_LOCKED = SecurityLogTags.SECURITY_DEVICE_LOCKED;
-
+    public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
 
     /**
      * Returns if device logging is enabled. Log producers should only write new logs if this is
@@ -128,7 +132,9 @@
          * Returns the tag of this log entry, which specifies entry's semantics.
          * Could be one of {@link SecurityLog#TAG_SYNC_RECV_FILE},
          * {@link SecurityLog#TAG_SYNC_SEND_FILE}, {@link SecurityLog#TAG_ADB_SHELL_CMD},
-         * {@link SecurityLog#TAG_ADB_SHELL_INTERACTIVE}, {@link SecurityLog#TAG_APP_PROCESS_START}.
+         * {@link SecurityLog#TAG_ADB_SHELL_INTERACTIVE}, {@link SecurityLog#TAG_APP_PROCESS_START},
+         * {@link SecurityLog#TAG_KEYGUARD_DISMISSED}, {@link SecurityLog#TAG_KEYGUARD_SECURED},
+         * {@link SecurityLog#TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT}.
          */
         public @SECURITY_LOG_TAG int getTag() {
             return mEvent.getTag();
diff --git a/core/java/android/auditing/SecurityLogTags.logtags b/core/java/android/auditing/SecurityLogTags.logtags
index 455acff..cf85894 100644
--- a/core/java/android/auditing/SecurityLogTags.logtags
+++ b/core/java/android/auditing/SecurityLogTags.logtags
@@ -3,9 +3,10 @@
 option java_package android.auditing
 
 210001 security_adb_shell_interactive
-210002 security_adb_shell_command        (command|3)
-210003 security_adb_sync_recv            (path|3)
-210004 security_adb_sync_send            (path|3)
-210005 security_app_process_start        (process|3),(start_time|2|3),(uid|1),(pid|1),(seinfo|3),(sha256|3)
-210006 security_device_unlock_attempt    (success|1),(method|3)
-210007 security_device_locked
\ No newline at end of file
+210002 security_adb_shell_command               (command|3)
+210003 security_adb_sync_recv                   (path|3)
+210004 security_adb_sync_send                   (path|3)
+210005 security_app_process_start               (process|3),(start_time|2|3),(uid|1),(pid|1),(seinfo|3),(sha256|3)
+210006 security_keyguard_dismissed
+210007 security_keyguard_dismiss_auth_attempt   (success|1)
+210008 security_keyguard_secured
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 3660be7..6b5f77f 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -23,6 +23,7 @@
 import android.bluetooth.le.ScanSettings;
 import android.bluetooth.le.ResultStorageDescriptor;
 import android.os.ParcelUuid;
+import android.os.WorkSource;
 
 import android.bluetooth.IBluetoothGattCallback;
 import android.bluetooth.IBluetoothGattServerCallback;
@@ -35,8 +36,8 @@
     List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
 
     void startScan(in int appIf, in boolean isServer, in ScanSettings settings,
-                   in List<ScanFilter> filters,
-                   in List scanStorages, in String callingPackage);
+                   in List<ScanFilter> filters, in WorkSource workSource, in List scanStorages,
+                   in String callingPackage);
     void stopScan(in int appIf, in boolean isServer);
     void flushPendingBatchResults(in int appIf, in boolean isServer);
     void startMultiAdvertising(in int appIf,
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 2ba87744..03449cc 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -29,6 +29,7 @@
 import android.os.Looper;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
+import android.os.WorkSource;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -89,9 +90,6 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public void startScan(final ScanCallback callback) {
-        if (callback == null) {
-            throw new IllegalArgumentException("callback is null");
-        }
         startScan(null, new ScanSettings.Builder().build(), callback);
     }
 
@@ -112,14 +110,53 @@
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public void startScan(List<ScanFilter> filters, ScanSettings settings,
             final ScanCallback callback) {
-        startScan(filters, settings, callback, null);
+        startScan(filters, settings, null, callback, null);
+    }
+
+    /**
+     * Start Bluetooth LE scan. Same as {@link #startScan(ScanCallback)} but allows the caller to
+     * specify on behalf of which application(s) the work is being done.
+     *
+     * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
+     *                   the scan.
+     * @param callback Callback used to deliver scan results.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(allOf = {
+            Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
+    public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) {
+        startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback);
+    }
+
+    /**
+     * Start Bluetooth LE scan. Same as {@link #startScan(List, ScanSettings, ScanCallback)} but
+     * allows the caller to specify on behalf of which application(s) the work is being done.
+     *
+     * @param filters {@link ScanFilter}s for finding exact BLE devices.
+     * @param settings Settings for the scan.
+     * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
+     *                   the scan.
+     * @param callback Callback used to deliver scan results.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(allOf = {
+            Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
+    public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
+                                    final WorkSource workSource, final ScanCallback callback) {
+        startScan(filters, settings, workSource, callback, null);
     }
 
     private void startScan(List<ScanFilter> filters, ScanSettings settings,
-            final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) {
+                           final WorkSource workSource, final ScanCallback callback,
+                           List<List<ResultStorageDescriptor>> resultStorages) {
         BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        if (settings == null || callback == null) {
-            throw new IllegalArgumentException("settings or callback is null");
+        if (callback == null) {
+            throw new IllegalArgumentException("callback is null");
+        }
+        if (settings == null) {
+            throw new IllegalArgumentException("settings is null");
         }
         synchronized (mLeScanClients) {
             if (mLeScanClients.containsKey(callback)) {
@@ -152,7 +189,7 @@
                 return;
             }
             BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
-                    settings, callback, resultStorages);
+                    settings, workSource, callback, resultStorages);
             wrapper.startRegisteration();
         }
     }
@@ -215,7 +252,7 @@
             scanFilters.add(filter.getFilter());
             scanStorages.add(filter.getStorageDescriptors());
         }
-        startScan(scanFilters, settings, callback, scanStorages);
+        startScan(scanFilters, settings, null, callback, scanStorages);
     }
 
     /**
@@ -235,6 +272,7 @@
 
         private final ScanCallback mScanCallback;
         private final List<ScanFilter> mFilters;
+        private final WorkSource mWorkSource;
         private ScanSettings mSettings;
         private IBluetoothGatt mBluetoothGatt;
         private List<List<ResultStorageDescriptor>> mResultStorages;
@@ -246,10 +284,12 @@
 
         public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt,
                 List<ScanFilter> filters, ScanSettings settings,
-                ScanCallback scanCallback, List<List<ResultStorageDescriptor>> resultStorages) {
+                WorkSource workSource, ScanCallback scanCallback,
+                List<List<ResultStorageDescriptor>> resultStorages) {
             mBluetoothGatt = bluetoothGatt;
             mFilters = filters;
             mSettings = settings;
+            mWorkSource = workSource;
             mScanCallback = scanCallback;
             mClientIf = 0;
             mResultStorages = resultStorages;
@@ -322,7 +362,9 @@
                     mClientIf = clientIf;
                     try {
                         mBluetoothGatt.startScan(mClientIf, false, mSettings, mFilters,
-                                mResultStorages, ActivityThread.currentOpPackageName());
+                                mWorkSource, mResultStorages,
+                                ActivityThread.currentOpPackageName());
+
                     } catch (RemoteException e) {
                         Log.e(TAG, "fail to start le scan: " + e);
                         mClientIf = -1;
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 2260d7e..10e6fb2 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -522,7 +522,7 @@
         IActivityManager am = ActivityManagerNative.getDefault();
         IBinder binder = null;
         try {
-            service.prepareToLeaveProcess();
+            service.prepareToLeaveProcess(myContext);
             binder = am.peekService(service, service.resolveTypeIfNeeded(
                     myContext.getContentResolver()), myContext.getOpPackageName());
         } catch (RemoteException e) {
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 6dfefac..0ec58ea 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -823,14 +823,14 @@
      *
      * @hide
      */
-    public void prepareToLeaveProcess() {
+    public void prepareToLeaveProcess(boolean leavingPackage) {
         final int size = mItems.size();
         for (int i = 0; i < size; i++) {
             final Item item = mItems.get(i);
             if (item.mIntent != null) {
-                item.mIntent.prepareToLeaveProcess();
+                item.mIntent.prepareToLeaveProcess(leavingPackage);
             }
-            if (item.mUri != null && StrictMode.vmFileUriExposureEnabled()) {
+            if (item.mUri != null && StrictMode.vmFileUriExposureEnabled() && leavingPackage) {
                 item.mUri.checkFileUriExposed("ClipData.Item.getUri()");
             }
         }
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 5653cad..e67da2b 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -118,7 +118,7 @@
     public void setPrimaryClip(ClipData clip) {
         try {
             if (clip != null) {
-                clip.prepareToLeaveProcess();
+                clip.prepareToLeaveProcess(true);
             }
             getService().setPrimaryClip(clip, mContext.getOpPackageName());
         } catch (RemoteException e) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9df7a28..3142b40 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -48,6 +48,7 @@
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.HardwarePropertiesManager;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.StatFs;
@@ -2611,6 +2612,8 @@
             MEDIA_PROJECTION_SERVICE,
             MIDI_SERVICE,
             RADIO_SERVICE,
+            HARDWARE_PROPERTIES_SERVICE,
+            //@hide: SOUND_TRIGGER_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -2672,6 +2675,8 @@
      * <dt> {@link #NETWORK_STATS_SERVICE} ("netstats")
      * <dd> A {@link android.app.usage.NetworkStatsManager NetworkStatsManager} for querying network
      * usage statistics.
+     * <dt> {@link #HARDWARE_PROPERTIES_SERVICE} ("hardwareproperties")
+     * <dd> A {@link android.os.HardwarePropertiesManager} for accessing hardware properties.
      * </dl>
      *
      * <p>Note:  System services obtained via this API may be closely associated with
@@ -2733,6 +2738,8 @@
      * @see android.app.job.JobScheduler
      * @see #NETWORK_STATS_SERVICE
      * @see android.app.usage.NetworkStatsManager
+     * @see android.os.HardwarePropertiesManager
+     * @see #HARDWARE_PROPERTIES_SERVICE
      */
     public abstract Object getSystemService(@ServiceName @NonNull String name);
 
@@ -3189,6 +3196,16 @@
     public static final String VOICE_INTERACTION_MANAGER_SERVICE = "voiceinteraction";
 
     /**
+     * Use with {@link #getSystemService} to access the
+     * {@link com.android.server.voiceinteraction.SoundTriggerService}.
+     *
+     * @hide
+     * @see #getSystemService
+     */
+    public static final String SOUND_TRIGGER_SERVICE = "soundtrigger";
+
+
+    /**
      * Use with {@link #getSystemService} to retrieve an
      * {@link android.app.backup.IBackupManager IBackupManager} for communicating
      * with the backup mechanism.
@@ -3475,6 +3492,14 @@
     public static final String RADIO_SERVICE = "radio";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.os.HardwarePropertiesManager} for accessing the hardware properties service.
+     *
+     * @see #getSystemService
+     */
+    public static final String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 06da4955..ee469da 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1575,6 +1575,14 @@
             = "android.intent.extra.UNINSTALL_ALL_USERS";
 
     /**
+     * Specified when the uninstall confirmation dialog is not required to be shown.
+     * Use with {@link #ACTION_UNINSTALL_PACKAGE}
+     * @hide
+     */
+    public static final String EXTRA_SKIP_UNINSTALL_CONFIRMATION =
+            "android.intent.extra.SKIP_UNINSTALL_CONFIRMATION";
+
+    /**
      * A string associated with a {@link #ACTION_UPGRADE_SETUP} activity
      * describing the last run version of the platform that was setup.
      * @hide
@@ -2618,8 +2626,7 @@
      *   turned off</li>
      * </ul>
      *
-     * <p class="note">This is a protected intent that can only be sent
-     * by the system.
+     * <p class="note">This is a protected intent that can only be sent by the system.</p>
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
@@ -3210,6 +3217,18 @@
     public static final String
             ACTION_OPEN_EXTERNAL_DIRECTORY = "android.intent.action.OPEN_EXTERNAL_DIRECTORY";
 
+    /**
+     * Broadcast Action: List of dynamic sensor is changed due to new sensor being connected or
+     * exisiting sensor being disconnected.
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.</p>
+     *
+     * {@hide}
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String
+            ACTION_DYNAMIC_SENSOR_CHANGED = "android.intent.action.DYNAMIC_SENSOR_CHANGED";
+
     /** {@hide} */
     public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
 
@@ -5698,6 +5717,9 @@
                 case "--receiver-replace-pending":
                     intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
                     break;
+                case "--receiver-foreground":
+                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                    break;
                 case "--selector":
                     intent.setDataAndType(data, type);
                     intent = new Intent();
@@ -5807,6 +5829,7 @@
                 "    [--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]",
                 "        (mutiple extras passed as List<String>; to embed a comma into a string,",
                 "         escape it using \"\\,\")",
+                "    [--f <FLAG>]",
                 "    [--grant-read-uri-permission] [--grant-write-uri-permission]",
                 "    [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]",
                 "    [--debug-log-resolution] [--exclude-stopped-packages]",
@@ -5820,6 +5843,7 @@
                 "    [--activity-single-top] [--activity-clear-task]",
                 "    [--activity-task-on-home]",
                 "    [--receiver-registered-only] [--receiver-replace-pending]",
+                "    [--receiver-foreground]",
                 "    [--selector]",
                 "    [<URI> | <PACKAGE> | <COMPONENT>]"
         };
@@ -8888,23 +8912,46 @@
      *
      * @hide
      */
-    public void prepareToLeaveProcess() {
+    public void prepareToLeaveProcess(Context context) {
+        final boolean leavingPackage = (mComponent == null)
+                || !Objects.equals(mComponent.getPackageName(), context.getPackageName());
+        prepareToLeaveProcess(leavingPackage);
+    }
+
+    /**
+     * Prepare this {@link Intent} to leave an app process.
+     *
+     * @hide
+     */
+    public void prepareToLeaveProcess(boolean leavingPackage) {
         setAllowFds(false);
 
         if (mSelector != null) {
-            mSelector.prepareToLeaveProcess();
+            mSelector.prepareToLeaveProcess(leavingPackage);
         }
         if (mClipData != null) {
-            mClipData.prepareToLeaveProcess();
+            mClipData.prepareToLeaveProcess(leavingPackage);
         }
 
-        if (mData != null && StrictMode.vmFileUriExposureEnabled()) {
-            // There are several ACTION_MEDIA_* broadcasts that send file://
-            // Uris, so only check common actions.
-            if (ACTION_VIEW.equals(mAction) ||
-                    ACTION_EDIT.equals(mAction) ||
-                    ACTION_ATTACH_DATA.equals(mAction)) {
-                mData.checkFileUriExposed("Intent.getData()");
+        if (mData != null && StrictMode.vmFileUriExposureEnabled() && leavingPackage) {
+            switch (mAction) {
+                case ACTION_MEDIA_REMOVED:
+                case ACTION_MEDIA_UNMOUNTED:
+                case ACTION_MEDIA_CHECKING:
+                case ACTION_MEDIA_NOFS:
+                case ACTION_MEDIA_MOUNTED:
+                case ACTION_MEDIA_SHARED:
+                case ACTION_MEDIA_UNSHARED:
+                case ACTION_MEDIA_BAD_REMOVAL:
+                case ACTION_MEDIA_UNMOUNTABLE:
+                case ACTION_MEDIA_EJECT:
+                case ACTION_MEDIA_SCANNER_STARTED:
+                case ACTION_MEDIA_SCANNER_FINISHED:
+                case ACTION_MEDIA_SCANNER_SCAN_FILE:
+                    // Ignore legacy actions
+                    break;
+                default:
+                    mData.checkFileUriExposed("Intent.getData()");
             }
         }
     }
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index 1d16516..7f9e176 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -30,8 +30,7 @@
  * when they are committed to storage.  Objects that are returned from the
  * various <code>get</code> methods must be treated as immutable by the application.
  *
- * <p><em>Note: currently this class does not support use across multiple
- * processes.  This will be added later.</em>
+ * <p><em>Note: This class does not support use across multiple processes.</em>
  *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index dedf07f5..91a8e0a 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -156,6 +156,35 @@
     public String targetActivity;
 
     /**
+     * Activity can not be resized and always occupies the fullscreen area with all windows fully
+     * visible.
+     * @hide
+     */
+    public static final int RESIZE_MODE_UNRESIZEABLE = 0;
+    /**
+     * Activity can not be resized and always occupies the fullscreen area with all windows cropped
+     * to either the task or stack bounds.
+     * @hide
+     */
+    public static final int RESIZE_MODE_CROP_WINDOWS = 1;
+    /**
+     * Activity is resizeable.
+     * @hide
+     */
+    public static final int RESIZE_MODE_RESIZEABLE = 2;
+    /**
+     * Activity is resizeable and supported picture-in-picture mode.
+     * @hide
+     */
+    public static final int RESIZE_MODE_RESIZEABLE_AND_PIPABLE = 3;
+    /**
+     * Value indicating if the resizing mode the activity supports.
+     * See {@link android.R.attr#resizeableActivity}.
+     * @hide
+     */
+    public int resizeMode;
+
+    /**
      * Bit in {@link #flags} indicating whether this activity is able to
      * run in multiple processes.  If
      * true, the system may instantiate it in the some process as the
@@ -283,20 +312,6 @@
     public static final int FLAG_ENABLE_VR_MODE = 0x8000;
 
     /**
-     * Bit in {@link #flags} indicating if the activity is resizeable to any dimension.
-     * See {@link android.R.attr#resizeableActivity}.
-     * @hide
-     */
-    public static final int FLAG_RESIZEABLE = 0x10000;
-
-    /**
-     * Bit in {@link #flags} indicating if the activity is supports picture-in-picture form of
-     * multi-window mode. See {@link android.R.attr#supportsPictureInPicture}.
-     * @hide
-     */
-    public static final int FLAG_SUPPORTS_PICTURE_IN_PICTURE = 0x20000;
-
-    /**
      * Bit in {@link #flags} indicating if the activity is always focusable regardless of if it is
      * in a task/stack whose activities are normally not focusable.
      * See android.R.attr#alwaysFocusable.
@@ -746,6 +761,7 @@
         maxRecents = orig.maxRecents;
         lockTaskLaunchMode = orig.lockTaskLaunchMode;
         layout = orig.layout;
+        resizeMode = orig.resizeMode;
     }
 
     /**
@@ -768,6 +784,22 @@
         }
     }
 
+    /** @hide */
+    public static final String resizeModeToString(int mode) {
+        switch (mode) {
+            case RESIZE_MODE_UNRESIZEABLE:
+                return "RESIZE_MODE_UNRESIZEABLE";
+            case RESIZE_MODE_CROP_WINDOWS:
+                return "RESIZE_MODE_CROP_WINDOWS";
+            case RESIZE_MODE_RESIZEABLE:
+                return "RESIZE_MODE_RESIZEABLE";
+            case RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
+                return "RESIZE_MODE_RESIZEABLE_AND_PIPABLE";
+            default:
+                return "unknown=" + mode;
+        }
+    }
+
     public void dump(Printer pw, String prefix) {
         dump(pw, prefix, DUMP_FLAG_ALL);
     }
@@ -806,6 +838,7 @@
                     + layout.widthFraction + ", " + layout.height + "|"
                     + layout.heightFraction + ", " + layout.gravity);
         }
+        pw.println(prefix + "resizeMode=" + resizeModeToString(resizeMode));
         super.dumpBack(pw, prefix, flags);
     }
 
@@ -847,6 +880,7 @@
         } else {
             dest.writeInt(0);
         }
+        dest.writeInt(resizeMode);
     }
 
     public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -879,6 +913,7 @@
         if (source.readInt() == 1) {
             layout = new Layout(source);
         }
+        resizeMode = source.readInt();
     }
 
     public static final class Layout {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 476dc46..3a94bf7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2017,6 +2017,11 @@
     public static final String FEATURE_SECURELY_REMOVES_USERS
             = "android.software.securely_removes_users";
 
+    /** {@hide} */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_FILE_BASED_ENCRYPTION
+            = "android.software.file_based_encryption";
+
     /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
      * The device has a full implementation of the android.webkit.* APIs. Devices
@@ -3627,7 +3632,7 @@
      *         {@link #MATCH_ENCRYPTION_AWARE_AND_UNAWARE}, {@link #MATCH_ENCRYPTION_UNAWARE},
      *         {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES}
      *         to modify the data returned.
-     * @param userId The userId of the user being queried.
+     * @param userHandle UserHandle of the user being queried.
      *
      * @return Returns a List of ResolveInfo objects containing one entry for each
      *         matching receiver, ordered from best to worst. If there are no matching
@@ -3648,9 +3653,19 @@
      *
      * @hide
      */
+    @SystemApi
+    public List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent,
+            @ResolveInfoFlags int flags, UserHandle userHandle) {
+        return queryBroadcastReceiversAsUser(intent, flags, userHandle.getIdentifier());
+    }
+
+    /**
+     * @hide
+     */
     public abstract List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent,
             @ResolveInfoFlags int flags, @UserIdInt int userId);
 
+
     /** {@hide} */
     @Deprecated
     public List<ResolveInfo> queryBroadcastReceivers(Intent intent,
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a6fec9f..44cd003 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -16,15 +16,12 @@
 
 package android.content.pm;
 
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
-import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
@@ -55,15 +52,6 @@
 import android.util.jar.StrictJarFile;
 import android.view.Gravity;
 
-import com.android.internal.R;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.XmlUtils;
-
-import libcore.io.IoUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -87,6 +75,25 @@
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.ZipEntry;
 
+import libcore.io.IoUtils;
+
+import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
+import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+
 /**
  * Parser for package files (APKs) on disk. This supports apps packaged either
  * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
@@ -3219,24 +3226,29 @@
                 a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
             }
 
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
-                    owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N)) {
-                a.info.flags |= ActivityInfo.FLAG_RESIZEABLE;
+            a.info.screenOrientation = sa.getInt(
+                    R.styleable.AndroidManifestActivity_screenOrientation,
+                    SCREEN_ORIENTATION_UNSPECIFIED);
 
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
-                        false)) {
-                    a.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
+            a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+            if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
+                if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity, true)) {
+                    if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
+                            false)) {
+                        a.info.resizeMode = RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+                    } else {
+                        a.info.resizeMode = RESIZE_MODE_RESIZEABLE;
+                    }
                 }
+            } else if (a.info.screenOrientation == SCREEN_ORIENTATION_UNSPECIFIED
+                    && (a.info.flags & FLAG_IMMERSIVE) == 0) {
+                a.info.resizeMode = RESIZE_MODE_CROP_WINDOWS;
             }
 
             if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
-                a.info.flags |= ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+                a.info.flags |= FLAG_ALWAYS_FOCUSABLE;
             }
 
-            a.info.screenOrientation = sa.getInt(
-                    R.styleable.AndroidManifestActivity_screenOrientation,
-                    ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
-
             a.info.lockTaskLaunchMode =
                     sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
 
@@ -3478,6 +3490,8 @@
         info.parentActivityName = target.info.parentActivityName;
         info.maxRecents = target.info.maxRecents;
         info.layout = target.info.layout;
+        info.resizeMode = target.info.resizeMode;
+        info.encryptionAware = target.info.encryptionAware;
 
         Activity a = new Activity(mParseActivityAliasArgs, info);
         if (outError[0] != null) {
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 19921b5..9e1b312 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -69,7 +69,7 @@
  * href="{@docRoot}guide/topics/resources/color-list-resource.html">Color State
  * List Resource</a>.</p>
  */
-public class ColorStateList implements Parcelable {
+public class ColorStateList extends ComplexColor implements Parcelable {
     private static final String TAG = "ColorStateList";
 
     private static final int DEFAULT_COLOR = Color.RED;
@@ -209,7 +209,7 @@
      * @return A new color state list for the current tag.
      */
     @NonNull
-    private static ColorStateList createFromXmlInner(@NonNull Resources r,
+    static ColorStateList createFromXmlInner(@NonNull Resources r,
             @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
             throws XmlPullParserException, IOException {
         final String name = parser.getName();
@@ -340,6 +340,7 @@
      * @return whether a theme can be applied to this color state list
      * @hide only for resource preloading
      */
+    @Override
     public boolean canApplyTheme() {
         return mThemeAttrs != null;
     }
@@ -419,6 +420,7 @@
      *         attributes
      * @hide only for resource preloading
      */
+    @Override
     public ColorStateList obtainForTheme(Theme t) {
         if (t == null || !canApplyTheme()) {
             return this;
@@ -460,6 +462,7 @@
      *         otherwise.
      * @see #getColorForState(int[], int)
      */
+    @Override
     public boolean isStateful() {
         return mStateSpecs.length > 1;
     }
@@ -602,14 +605,14 @@
      * @return a factory that can create new instances of this ColorStateList
      * @hide only for resource preloading
      */
-    public ConstantState<ColorStateList> getConstantState() {
+    public ConstantState<ComplexColor> getConstantState() {
         if (mFactory == null) {
             mFactory = new ColorStateListFactory(this);
         }
         return mFactory;
     }
 
-    private static class ColorStateListFactory extends ConstantState<ColorStateList> {
+    private static class ColorStateListFactory extends ConstantState<ComplexColor> {
         private final ColorStateList mSrc;
 
         public ColorStateListFactory(ColorStateList src) {
@@ -628,7 +631,7 @@
 
         @Override
         public ColorStateList newInstance(Resources res, Theme theme) {
-            return mSrc.obtainForTheme(theme);
+            return (ColorStateList) mSrc.obtainForTheme(theme);
         }
     }
 
diff --git a/core/java/android/content/res/ComplexColor.java b/core/java/android/content/res/ComplexColor.java
new file mode 100644
index 0000000..d96ec62
--- /dev/null
+++ b/core/java/android/content/res/ComplexColor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import android.annotation.ColorInt;
+import android.content.res.Resources.Theme;
+import android.graphics.Color;
+
+/**
+ * Defines an abstract class for the complex color information, like
+ * {@link android.content.res.ColorStateList} or {@link android.content.res.GradientColor}
+ */
+public abstract class ComplexColor {
+    /**
+     * @return {@code true}  if this ComplexColor changes color based on state, {@code false}
+     * otherwise.
+     */
+    public boolean isStateful() { return false; }
+
+    /**
+     * @return the default color.
+     */
+    @ColorInt
+    public abstract int getDefaultColor();
+
+    /**
+     * @hide only for resource preloading
+     *
+     */
+    public abstract ConstantState<ComplexColor> getConstantState();
+
+    /**
+     * @hide only for resource preloading
+     */
+    public abstract boolean canApplyTheme();
+
+    /**
+     * @hide only for resource preloading
+     */
+    public abstract ComplexColor obtainForTheme(Theme t);
+}
diff --git a/core/java/android/content/res/GradientColor.java b/core/java/android/content/res/GradientColor.java
new file mode 100644
index 0000000..98ef2ea
--- /dev/null
+++ b/core/java/android/content/res/GradientColor.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Resources.Theme;
+
+import com.android.internal.R;
+import com.android.internal.util.GrowingArrayUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.graphics.LinearGradient;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.graphics.SweepGradient;
+import android.graphics.drawable.GradientDrawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import java.io.IOException;
+
+
+public class GradientColor extends ComplexColor {
+    private static final String TAG = "GradientColor";
+
+    private static final boolean DBG_GRADIENT = false;
+
+    /** Lazily-created factory for this GradientColor. */
+    private GradientColorFactory mFactory;
+
+    private int mChangingConfigurations;
+    private int mDefaultColor;
+
+    // After parsing all the attributes from XML, this shader is the ultimate result containing
+    // all the XML information.
+    private Shader mShader = null;
+
+    // Below are the attributes at the root element <gradient>
+    private int mGradientType = GradientDrawable.LINEAR_GRADIENT;
+
+    private float mCenterX = 0f;
+    private float mCenterY = 0f;
+
+    private float mStartX = 0f;
+    private float mStartY = 0f;
+    private float mEndX = 0f;
+    private float mEndY = 0f;
+
+    private int mStartColor = 0;
+    private int mCenterColor = 0;
+    private int mEndColor = 0;
+    private boolean mHasCenterColor = false;
+
+    private float mGradientRadius = 0f;
+
+    // Below are the attributes for the <item> element.
+    private int[] mItemColors;
+    private float[] mItemOffsets;
+
+    // Theme attributes for the root and item elements.
+    private int[] mThemeAttrs;
+    private int[][] mItemsThemeAttrs;
+
+    private GradientColor() {
+    }
+
+    private GradientColor(GradientColor copy) {
+        if (copy != null) {
+            mChangingConfigurations = copy.mChangingConfigurations;
+            mDefaultColor = copy.mDefaultColor;
+            mShader = copy.mShader;
+            mGradientType = copy.mGradientType;
+            mCenterX = copy.mCenterX;
+            mCenterY = copy.mCenterY;
+            mStartX = copy.mStartX;
+            mStartY = copy.mStartY;
+            mEndX = copy.mEndX;
+            mEndY = copy.mEndY;
+            mStartColor = copy.mStartColor;
+            mCenterColor = copy.mCenterColor;
+            mEndColor = copy.mEndColor;
+            mHasCenterColor = copy.mHasCenterColor;
+            mGradientRadius = copy.mGradientRadius;
+
+            if (copy.mItemColors != null) {
+                mItemColors = copy.mItemColors.clone();
+            }
+            if (copy.mItemOffsets != null) {
+                mItemOffsets = copy.mItemOffsets.clone();
+            }
+
+            if (copy.mThemeAttrs != null) {
+                mThemeAttrs = copy.mThemeAttrs.clone();
+            }
+            if (copy.mItemsThemeAttrs != null) {
+                mItemsThemeAttrs = copy.mItemsThemeAttrs.clone();
+            }
+        }
+    }
+
+    /**
+     * Update the root level's attributes, either for inflate or applyTheme.
+     */
+    private void updateRootElementState(TypedArray a) {
+        // Extract the theme attributes, if any.
+        mThemeAttrs = a.extractThemeAttrs();
+
+        mStartX = a.getFloat(
+                R.styleable.GradientColor_startX, mStartX);
+        mStartY = a.getFloat(
+                R.styleable.GradientColor_startY, mStartY);
+        mEndX = a.getFloat(
+                R.styleable.GradientColor_endX, mEndX);
+        mEndY = a.getFloat(
+                R.styleable.GradientColor_endY, mEndY);
+
+        mCenterX = a.getFloat(
+                R.styleable.GradientColor_centerX, mCenterX);
+        mCenterY = a.getFloat(
+                R.styleable.GradientColor_centerY, mCenterY);
+
+        mGradientType = a.getInt(
+                R.styleable.GradientColor_type, mGradientType);
+
+        mStartColor = a.getColor(
+                R.styleable.GradientColor_startColor, mStartColor);
+        mHasCenterColor |= a.hasValue(
+                R.styleable.GradientColor_centerColor);
+        mCenterColor = a.getColor(
+                R.styleable.GradientColor_centerColor, mCenterColor);
+        mEndColor = a.getColor(
+                R.styleable.GradientColor_endColor, mEndColor);
+
+        if (DBG_GRADIENT) {
+            Log.v(TAG, "hasCenterColor is " + mHasCenterColor);
+            if (mHasCenterColor) {
+                Log.v(TAG, "centerColor:" + mCenterColor);
+            }
+            Log.v(TAG, "startColor: " + mStartColor);
+            Log.v(TAG, "endColor: " + mEndColor);
+        }
+
+        mGradientRadius = a.getFloat(R.styleable.GradientColor_gradientRadius,
+                mGradientRadius);
+    }
+
+    /**
+     * Check if the XML content is valid.
+     *
+     * @throws XmlPullParserException if errors were found.
+     */
+    private void validateXmlContent() throws XmlPullParserException {
+        if (mGradientRadius <= 0
+                && mGradientType == GradientDrawable.RADIAL_GRADIENT) {
+            throw new XmlPullParserException(
+                    "<gradient> tag requires 'gradientRadius' "
+                            + "attribute with radial type");
+        }
+    }
+
+    /**
+     * The shader information will be applied to the native VectorDrawable's path.
+     * @hide
+     */
+    public Shader getShader() {
+        return mShader;
+    }
+
+    /**
+     * A public method to create GradientColor from a XML resource.
+     */
+    public static GradientColor createFromXml(Resources r, XmlResourceParser parser, Theme theme)
+            throws XmlPullParserException, IOException {
+        final AttributeSet attrs = Xml.asAttributeSet(parser);
+
+        int type;
+        while ((type = parser.next()) != XmlPullParser.START_TAG
+                && type != XmlPullParser.END_DOCUMENT) {
+            // Seek parser to start tag.
+        }
+
+        if (type != XmlPullParser.START_TAG) {
+            throw new XmlPullParserException("No start tag found");
+        }
+
+        return createFromXmlInner(r, parser, attrs, theme);
+    }
+
+    /**
+     * Create from inside an XML document. Called on a parser positioned at a
+     * tag in an XML document, tries to create a GradientColor from that tag.
+     *
+     * @return A new GradientColor for the current tag.
+     * @throws XmlPullParserException if the current tag is not &lt;gradient>
+     */
+    @NonNull
+    static GradientColor createFromXmlInner(@NonNull Resources r,
+            @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
+            throws XmlPullParserException, IOException {
+        final String name = parser.getName();
+        if (!name.equals("gradient")) {
+            throw new XmlPullParserException(
+                    parser.getPositionDescription() + ": invalid gradient color tag " + name);
+        }
+
+        final GradientColor gradientColor = new GradientColor();
+        gradientColor.inflate(r, parser, attrs, theme);
+        return gradientColor;
+    }
+
+    /**
+     * Fill in this object based on the contents of an XML "gradient" element.
+     */
+    private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
+            @NonNull AttributeSet attrs, @Nullable Theme theme)
+            throws XmlPullParserException, IOException {
+        final TypedArray a = Resources.obtainAttributes(r, theme, attrs, R.styleable.GradientColor);
+        updateRootElementState(a);
+        mChangingConfigurations |= a.getChangingConfigurations();
+        a.recycle();
+
+        // Check correctness and throw exception if errors found.
+        validateXmlContent();
+
+        inflateChildElements(r, parser, attrs, theme);
+
+        onColorsChange();
+    }
+
+    /**
+     * Inflates child elements "item"s for each color stop.
+     *
+     * Note that at root level, we need to save ThemeAttrs for theme applied later.
+     * Here similarly, at each child item, we need to save the theme's attributes, and apply theme
+     * later as applyItemsAttrsTheme().
+     */
+    private void inflateChildElements(@NonNull Resources r, @NonNull XmlPullParser parser,
+            @NonNull AttributeSet attrs, @NonNull Theme theme)
+            throws XmlPullParserException, IOException {
+        final int innerDepth = parser.getDepth() + 1;
+        int type;
+        int depth;
+
+        // Pre-allocate the array with some size, for better performance.
+        float[] offsetList = new float[20];
+        int[] colorList = new int[offsetList.length];
+        int[][] themeAttrsList = new int[offsetList.length][];
+
+        int listSize = 0;
+        boolean hasUnresolvedAttrs = false;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && ((depth = parser.getDepth()) >= innerDepth
+                || type != XmlPullParser.END_TAG)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            if (depth > innerDepth || !parser.getName().equals("item")) {
+                continue;
+            }
+
+            final TypedArray a = Resources.obtainAttributes(r, theme, attrs,
+                    R.styleable.GradientColorItem);
+            boolean hasColor = a.hasValue(R.styleable.GradientColorItem_color);
+            boolean hasOffset = a.hasValue(R.styleable.GradientColorItem_offset);
+            if (!hasColor || !hasOffset) {
+                throw new XmlPullParserException(
+                        parser.getPositionDescription()
+                                + ": <item> tag requires a 'color' attribute and a 'offset' "
+                                + "attribute!");
+            }
+
+            final int[] themeAttrs = a.extractThemeAttrs();
+            int color = a.getColor(R.styleable.GradientColorItem_color, 0);
+            float offset = a.getFloat(R.styleable.GradientColorItem_offset, 0);
+
+            if (DBG_GRADIENT) {
+                Log.v(TAG, "new item color " + color + " " + Integer.toHexString(color));
+                Log.v(TAG, "offset" + offset);
+            }
+            mChangingConfigurations |= a.getChangingConfigurations();
+            a.recycle();
+
+            if (themeAttrs != null) {
+                hasUnresolvedAttrs = true;
+            }
+
+            colorList = GrowingArrayUtils.append(colorList, listSize, color);
+            offsetList = GrowingArrayUtils.append(offsetList, listSize, offset);
+            themeAttrsList = GrowingArrayUtils.append(themeAttrsList, listSize, themeAttrs);
+            listSize++;
+        }
+        if (listSize > 0) {
+            if (hasUnresolvedAttrs) {
+                mItemsThemeAttrs = new int[listSize][];
+                System.arraycopy(themeAttrsList, 0, mItemsThemeAttrs, 0, listSize);
+            } else {
+                mItemsThemeAttrs = null;
+            }
+
+            mItemColors = new int[listSize];
+            mItemOffsets = new float[listSize];
+            System.arraycopy(colorList, 0, mItemColors, 0, listSize);
+            System.arraycopy(offsetList, 0, mItemOffsets, 0, listSize);
+        }
+    }
+
+    /**
+     * Apply theme to all the items.
+     */
+    private void applyItemsAttrsTheme(Theme t) {
+        if (mItemsThemeAttrs == null) {
+            return;
+        }
+
+        boolean hasUnresolvedAttrs = false;
+
+        final int[][] themeAttrsList = mItemsThemeAttrs;
+        final int N = themeAttrsList.length;
+        for (int i = 0; i < N; i++) {
+            if (themeAttrsList[i] != null) {
+                final TypedArray a = t.resolveAttributes(themeAttrsList[i],
+                        R.styleable.GradientColorItem);
+
+                // Extract the theme attributes, if any, before attempting to
+                // read from the typed array. This prevents a crash if we have
+                // unresolved attrs.
+                themeAttrsList[i] = a.extractThemeAttrs(themeAttrsList[i]);
+                if (themeAttrsList[i] != null) {
+                    hasUnresolvedAttrs = true;
+                }
+
+                mItemColors[i] = a.getColor(R.styleable.GradientColorItem_color, mItemColors[i]);
+                mItemOffsets[i] = a.getFloat(R.styleable.GradientColorItem_offset, mItemOffsets[i]);
+                if (DBG_GRADIENT) {
+                    Log.v(TAG, "applyItemsAttrsTheme Colors[i] " + i + " " +
+                            Integer.toHexString(mItemColors[i]));
+                    Log.v(TAG, "Offsets[i] " + i + " " + mItemOffsets[i]);
+                }
+
+                // Account for any configuration changes.
+                mChangingConfigurations |= a.getChangingConfigurations();
+
+                a.recycle();
+            }
+        }
+
+        if (!hasUnresolvedAttrs) {
+            mItemsThemeAttrs = null;
+        }
+    }
+
+    private void onColorsChange() {
+        int[] tempColors = null;
+        float[] tempOffsets = null;
+
+        if (mItemColors != null) {
+            int length = mItemColors.length;
+            tempColors = new int[length];
+            tempOffsets = new float[length];
+
+            for (int i = 0; i < length; i++) {
+                tempColors[i] = mItemColors[i];
+                tempOffsets[i] = mItemOffsets[i];
+            }
+        } else {
+            if (mHasCenterColor) {
+                tempColors = new int[3];
+                tempColors[0] = mStartColor;
+                tempColors[1] = mCenterColor;
+                tempColors[2] = mEndColor;
+
+                tempOffsets = new float[3];
+                tempOffsets[0] = 0.0f;
+                // Since 0.5f is default value, try to take the one that isn't 0.5f
+                tempOffsets[1] = 0.5f;
+                tempOffsets[2] = 1f;
+            } else {
+                tempColors = new int[2];
+                tempColors[0] = mStartColor;
+                tempColors[1] = mEndColor;
+            }
+        }
+        if (tempColors.length < 2) {
+            Log.w(TAG, "<gradient> tag requires 2 color values specified!" + tempColors.length
+                    + " " + tempColors);
+        }
+
+        if (mGradientType == GradientDrawable.LINEAR_GRADIENT) {
+            mShader = new LinearGradient(mStartX, mStartY, mEndX, mEndY, tempColors, tempOffsets,
+                    Shader.TileMode.CLAMP);
+        } else {
+            if (mGradientType == GradientDrawable.RADIAL_GRADIENT) {
+                mShader = new RadialGradient(mCenterX, mCenterY, mGradientRadius, tempColors,
+                        tempOffsets, Shader.TileMode.CLAMP);
+            } else {
+                mShader = new SweepGradient(mCenterX, mCenterY, tempColors, tempOffsets);
+            }
+        }
+        mDefaultColor = tempColors[0];
+    }
+
+    /**
+     * For Gradient color, the default color is not very useful, since the gradient will override
+     * the color information anyway.
+     */
+    @Override
+    @ColorInt
+    public int getDefaultColor() {
+        return mDefaultColor;
+    }
+
+    /**
+     * Similar to ColorStateList, setup constant state and its factory.
+     * @hide only for resource preloading
+     */
+    @Override
+    public ConstantState<ComplexColor> getConstantState() {
+        if (mFactory == null) {
+            mFactory = new GradientColorFactory(this);
+        }
+        return mFactory;
+    }
+
+    private static class GradientColorFactory extends ConstantState<ComplexColor> {
+        private final GradientColor mSrc;
+
+        public GradientColorFactory(GradientColor src) {
+            mSrc = src;
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mSrc.mChangingConfigurations;
+        }
+
+        @Override
+        public GradientColor newInstance() {
+            return mSrc;
+        }
+
+        @Override
+        public GradientColor newInstance(Resources res, Theme theme) {
+            return mSrc.obtainForTheme(theme);
+        }
+    }
+
+    /**
+     * Returns an appropriately themed gradient color.
+     *
+     * @param t the theme to apply
+     * @return a copy of the gradient color the theme applied, or the
+     * gradient itself if there were no unresolved theme
+     * attributes
+     * @hide only for resource preloading
+     */
+    @Override
+    public GradientColor obtainForTheme(Theme t) {
+        if (t == null || !canApplyTheme()) {
+            return this;
+        }
+
+        final GradientColor clone = new GradientColor(this);
+        clone.applyTheme(t);
+        return clone;
+    }
+
+    private void applyTheme(Theme t) {
+        if (mThemeAttrs != null) {
+            applyRootAttrsTheme(t);
+        }
+        if (mItemsThemeAttrs != null) {
+            applyItemsAttrsTheme(t);
+        }
+        onColorsChange();
+    }
+
+    private void applyRootAttrsTheme(Theme t) {
+        final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.GradientColor);
+        // mThemeAttrs will be set to null if if there are no theme attributes in the
+        // typed array.
+        mThemeAttrs = a.extractThemeAttrs(mThemeAttrs);
+        // merging the attributes update inside the updateRootElementState().
+        updateRootElementState(a);
+
+        // Account for any configuration changes.
+        mChangingConfigurations |= a.getChangingConfigurations();
+        a.recycle();
+    }
+
+
+    /**
+     * Returns whether a theme can be applied to this gradient color, which
+     * usually indicates that the gradient color has unresolved theme
+     * attributes.
+     *
+     * @return whether a theme can be applied to this gradient color.
+     * @hide only for resource preloading
+     */
+    @Override
+    public boolean canApplyTheme() {
+        return mThemeAttrs != null || mItemsThemeAttrs != null;
+    }
+
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e404429..4967d05 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -56,6 +56,7 @@
 import android.util.Pools.SynchronizedPool;
 import android.util.Slog;
 import android.util.TypedValue;
+import android.util.Xml;
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
 
@@ -115,8 +116,8 @@
     private static final LongSparseArray<ConstantState>[] sPreloadedDrawables;
     private static final LongSparseArray<ConstantState> sPreloadedColorDrawables
             = new LongSparseArray<>();
-    private static final LongSparseArray<android.content.res.ConstantState<ColorStateList>>
-            sPreloadedColorStateLists = new LongSparseArray<>();
+    private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
+            sPreloadedComplexColors = new LongSparseArray<>();
 
     // Pool of TypedArrays targeted to this Resources object.
     final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
@@ -133,7 +134,7 @@
     private final Configuration mTmpConfig = new Configuration();
     private final DrawableCache mDrawableCache = new DrawableCache(this);
     private final DrawableCache mColorDrawableCache = new DrawableCache(this);
-    private final ConfigurationBoundResourceCache<ColorStateList> mColorStateListCache =
+    private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
             new ConfigurationBoundResourceCache<>(this);
     private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
             new ConfigurationBoundResourceCache<>(this);
@@ -1987,7 +1988,7 @@
 
             mDrawableCache.onConfigurationChange(configChanges);
             mColorDrawableCache.onConfigurationChange(configChanges);
-            mColorStateListCache.onConfigurationChange(configChanges);
+            mComplexColorCache.onConfigurationChange(configChanges);
             mAnimatorCache.onConfigurationChange(configChanges);
             mStateListAnimatorCache.onConfigurationChange(configChanges);
 
@@ -2613,6 +2614,82 @@
         return dr;
     }
 
+    /**
+     * Given the value and id, we can get the XML filename as in value.data, based on that, we
+     * first try to load CSL from the cache. If not found, try to get from the constant state.
+     * Last, parse the XML and generate the CSL.
+     */
+    private ComplexColor loadComplexColorFromName(Theme theme, TypedValue value, int id) {
+        final long key = (((long) value.assetCookie) << 32) | value.data;
+        final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
+        ComplexColor complexColor = cache.getInstance(key, theme);
+        if (complexColor != null) {
+            return complexColor;
+        }
+
+        final android.content.res.ConstantState<ComplexColor> factory =
+                sPreloadedComplexColors.get(key);
+
+        if (factory != null) {
+            complexColor = factory.newInstance(this, theme);
+        }
+        if (complexColor == null) {
+            complexColor = loadComplexColorForCookie(value, id, theme);
+        }
+
+        if (complexColor != null) {
+            if (mPreloading) {
+                if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+                        "color")) {
+                    sPreloadedComplexColors.put(key, complexColor.getConstantState());
+                }
+            } else {
+                cache.put(key, theme, complexColor.getConstantState());
+            }
+        }
+        return complexColor;
+    }
+
+    @Nullable
+    public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, Theme theme) {
+        if (TRACE_FOR_PRELOAD) {
+            // Log only framework resources
+            if ((id >>> 24) == 0x1) {
+                final String name = getResourceName(id);
+                if (name != null) android.util.Log.d("loadComplexColor", name);
+            }
+        }
+
+        final long key = (((long) value.assetCookie) << 32) | value.data;
+
+        // Handle inline color definitions.
+        if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+                && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+            return getColorStateListFromInt(value, key);
+        }
+
+        final String file = value.string.toString();
+
+        ComplexColor complexColor;
+        if (file.endsWith(".xml")) {
+            try {
+                complexColor = loadComplexColorFromName(theme, value, id);
+            } catch (Exception e) {
+                final NotFoundException rnf = new NotFoundException(
+                        "File " + file + " from complex color resource ID #0x"
+                                + Integer.toHexString(id));
+                rnf.initCause(e);
+                throw rnf;
+            }
+        } else {
+            throw new NotFoundException(
+                    "File " + file + " from drawable resource ID #0x"
+                            + Integer.toHexString(id) + ": .xml extension required");
+        }
+
+        return complexColor;
+    }
+
     @Nullable
     ColorStateList loadColorStateList(TypedValue value, int id, Theme theme)
             throws NotFoundException {
@@ -2626,63 +2703,57 @@
 
         final long key = (((long) value.assetCookie) << 32) | value.data;
 
-        ColorStateList csl;
-
         // Handle inline color definitions.
         if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
                 && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
-            final android.content.res.ConstantState<ColorStateList> factory =
-                    sPreloadedColorStateLists.get(key);
-            if (factory != null) {
-                return factory.newInstance();
-            }
-
-            csl = ColorStateList.valueOf(value.data);
-
-            if (mPreloading) {
-                if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
-                        "color")) {
-                    sPreloadedColorStateLists.put(key, csl.getConstantState());
-                }
-            }
-
-            return csl;
+            return getColorStateListFromInt(value, key);
         }
 
-        final ConfigurationBoundResourceCache<ColorStateList> cache = mColorStateListCache;
-        csl = cache.getInstance(key, theme);
-        if (csl != null) {
-            return csl;
+        ComplexColor complexColor = loadComplexColorFromName(theme, value, id);
+        if (complexColor != null && complexColor instanceof ColorStateList) {
+            return (ColorStateList) complexColor;
         }
 
-        final android.content.res.ConstantState<ColorStateList> factory =
-                sPreloadedColorStateLists.get(key);
+        throw new NotFoundException(
+                "Can't find ColorStateList from drawable resource ID #0x"
+                        + Integer.toHexString(id));
+    }
+
+    @NonNull
+    private ColorStateList getColorStateListFromInt(@NonNull  TypedValue value, long key) {
+        ColorStateList csl;
+        final android.content.res.ConstantState<ComplexColor> factory =
+                sPreloadedComplexColors.get(key);
         if (factory != null) {
-            csl = factory.newInstance(this, theme);
+            return (ColorStateList) factory.newInstance();
         }
 
-        if (csl == null) {
-            csl = loadColorStateListForCookie(value, id, theme);
-        }
+        csl = ColorStateList.valueOf(value.data);
 
-        if (csl != null) {
-            if (mPreloading) {
-                if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
-                        "color")) {
-                    sPreloadedColorStateLists.put(key, csl.getConstantState());
-                }
-            } else {
-                cache.put(key, theme, csl.getConstantState());
+        if (mPreloading) {
+            if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+                    "color")) {
+                sPreloadedComplexColors.put(key, csl.getConstantState());
             }
         }
 
         return csl;
     }
 
-    private ColorStateList loadColorStateListForCookie(TypedValue value, int id, Theme theme) {
+    /**
+     * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
+     * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
+     *
+     * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
+     * and selector tag.
+     *
+     * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
+     */
+    @Nullable
+    private ComplexColor loadComplexColorForCookie(TypedValue value, int id, Theme theme) {
         if (value.string == null) {
             throw new UnsupportedOperationException(
-                    "Can't convert to color state list: type=0x" + value.type);
+                    "Can't convert to ComplexColor: type=0x" + value.type);
         }
 
         final String file = value.string.toString();
@@ -2692,29 +2763,45 @@
             if ((id >>> 24) == 0x1) {
                 final String name = getResourceName(id);
                 if (name != null) {
-                    Log.d(TAG, "Loading framework color state list #" + Integer.toHexString(id)
+                    Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
                             + ": " + name + " at " + file);
                 }
             }
         }
 
         if (DEBUG_LOAD) {
-            Log.v(TAG, "Loading color state list for cookie " + value.assetCookie + ": " + file);
+            Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
         }
 
-        final ColorStateList csl;
+        ComplexColor complexColor = null;
 
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
         if (file.endsWith(".xml")) {
             try {
-                final XmlResourceParser rp = loadXmlResourceParser(
-                        file, id, value.assetCookie, "colorstatelist");
-                csl = ColorStateList.createFromXml(this, rp, theme);
-                rp.close();
+                final XmlResourceParser parser = loadXmlResourceParser(
+                        file, id, value.assetCookie, "ComplexColor");
+
+                final AttributeSet attrs = Xml.asAttributeSet(parser);
+                int type;
+                while ((type = parser.next()) != XmlPullParser.START_TAG
+                        && type != XmlPullParser.END_DOCUMENT) {
+                    // Seek parser to start tag.
+                }
+                if (type != XmlPullParser.START_TAG) {
+                    throw new XmlPullParserException("No start tag found");
+                }
+
+                final String name = parser.getName();
+                if (name.equals("gradient")) {
+                    complexColor = GradientColor.createFromXmlInner(this, parser, attrs, theme);
+                } else if (name.equals("selector")) {
+                    complexColor = ColorStateList.createFromXmlInner(this, parser, attrs, theme);
+                }
+                parser.close();
             } catch (Exception e) {
                 Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
                 final NotFoundException rnf = new NotFoundException(
-                        "File " + file + " from color state list resource ID #0x"
+                        "File " + file + " from ComplexColor resource ID #0x"
                                 + Integer.toHexString(id));
                 rnf.initCause(e);
                 throw rnf;
@@ -2727,7 +2814,7 @@
         }
         Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
 
-        return csl;
+        return complexColor;
     }
 
     /**
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index cc65e1e..6067577 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -454,6 +454,39 @@
     }
 
     /**
+     * Retrieve the ComplexColor for the attribute at <var>index</var>.
+     * The value may be either a {@link android.content.res.ColorStateList} which can wrap a simple
+     * color value or a {@link android.content.res.GradientColor}
+     * <p>
+     * This method will return {@code null} if the attribute is not defined or
+     * is not an integer color, color state list or GradientColor.
+     *
+     * @param index Index of attribute to retrieve.
+     *
+     * @return ComplexColor for the attribute, or {@code null} if not defined.
+     * @throws RuntimeException if the attribute if the TypedArray has already
+     *         been recycled.
+     * @throws UnsupportedOperationException if the attribute is defined but is
+     *         not an integer color, color state list or GradientColor.
+     */
+    @Nullable
+    public ComplexColor getComplexColor(@StyleableRes int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
+        final TypedValue value = mValue;
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+            if (value.type == TypedValue.TYPE_ATTRIBUTE) {
+                throw new UnsupportedOperationException(
+                        "Failed to resolve attribute at index " + index + ": " + value);
+            }
+            return mResources.loadComplexColor(value, value.resourceId, mTheme);
+        }
+        return null;
+    }
+
+    /**
      * Retrieve the ColorStateList for the attribute at <var>index</var>.
      * The value may be either a single solid color or a reference to
      * a color or complex {@link android.content.res.ColorStateList}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index e5efd56..841e5b0 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -17,8 +17,10 @@
 
 package android.hardware;
 
-import android.os.Build;
 import android.annotation.SystemApi;
+import android.os.Build;
+
+import java.util.UUID;
 
 /**
  * Class representing a sensor. Use {@link SensorManager#getSensorList} to get
@@ -557,6 +559,8 @@
      * Similar to {@link #TYPE_ROTATION_VECTOR}, with additional delta
      * translation from an arbitrary reference point.
      *
+     * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+     *
      * Can use camera, depth sensor etc to compute output value.
      *
      * This is expected to be a high power sensor and expected only to be
@@ -574,9 +578,78 @@
      */
     public static final String STRING_TYPE_POSE_6DOF = "android.sensor.pose_6dof";
 
+     /**
+     * A constant describing a stationary detect sensor.
+     *
+     * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+     *
+     */
+    public static final int TYPE_STATIONARY_DETECT = 29;
+
+    /**
+     * A constant string describing a stationary detection sensor.
+     *
+     * @see #TYPE_STATIONARY_DETECT
+     */
+    public static final String STRING_TYPE_STATIONARY_DETECT = "android.sensor.stationary_detect";
+
+     /**
+     * A constant describing a motion detect sensor.
+     *
+     * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+     *
+     */
+    public static final int TYPE_MOTION_DETECT = 30;
+
+    /**
+     * A constant string describing a motion detection sensor.
+     *
+     * @see #TYPE_MOTION_DETECT
+     */
+    public static final String STRING_TYPE_MOTION_DETECT = "android.sensor.motion_detect";
+
+     /**
+     * A constant describing a motion detect sensor.
+     *
+     * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+     *
+     */
+    public static final int TYPE_HEART_BEAT = 31;
+
+    /**
+     * A constant string describing a heart beat sensor.
+     *
+     * @see #TYPE_HEART_BEAT
+     */
+
+    public static final String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
+    /**
+     * A constant describing a dynamic sensor meta event sensor.
+     *
+     * A sensor event of this type is received when a dynamic sensor is added to or removed from
+     * the system. This sensor type should always use special trigger report mode ({@code
+     * SensorManager.REPORTING_MODE_SPECIAL_TRIGGER}).
+     *
+     * @hide This sensor is expected to be used only by system services.
+     */
+    @SystemApi
+    public static final int TYPE_DYNAMIC_SENSOR_META = 32;
+
+    /**
+     * A constant string describing a dynamic sensor meta event sensor.
+     *
+     * @see #TYPE_DYNAMIC_SENSOR_META
+     *
+     * @hide This sensor is expected to only be used by the system service
+     */
+    @SystemApi
+    public static final String STRING_TYPE_DYNAMIC_SENSOR_META =
+            "android.sensor.dynamic_sensor_meta";
+
     /**
      * A constant describing all sensor types.
      */
+
     public static final int TYPE_ALL = -1;
 
     // If this flag is set, the sensor defined as a wake up sensor. This field and REPORTING_MODE_*
@@ -660,7 +733,11 @@
             1, // SENSOR_TYPE_PICK_UP_GESTURE
             1, // SENSOR_TYPE_WRIST_TILT_GESTURE
             1, // SENSOR_TYPE_DEVICE_ORIENTATION
-            16, // SENSOR_TYPE_POSE_6DOF
+            16,// SENSOR_TYPE_POSE_6DOF
+            1, // SENSOR_TYPE_STATIONARY_DETECT
+            1, // SENSOR_TYPE_MOTION_DETECT
+            1, // SENSOR_TYPE_HEART_BEAT
+            2, // SENSOR_TYPE_DYNAMIC_SENSOR_META
     };
 
     /**
@@ -686,12 +763,10 @@
         }
         int offset = sensor.mType;
         if (offset >= sSensorReportingModes.length) {
-            // we don't know about this sensor, so this is probably a
-            // vendor-defined sensor, in that case, we don't know how many value
-            // it has
-            // so we return the maximum and assume the app will know.
-            // FIXME: sensor HAL should advertise how much data is returned per
-            // sensor
+            // we don't know about this sensor, so this is probably a vendor-defined sensor, in that
+            // case, we don't know how many value it has so we return the maximum and assume the app
+            // will know.
+            // FIXME: sensor HAL should advertise how much data is returned per sensor
             return 16;
         }
         return sSensorReportingModes[offset];
@@ -715,6 +790,7 @@
     private String  mRequiredPermission;
     private int     mMaxDelay;
     private int     mFlags;
+    private UUID    mUuid;
 
     Sensor() {
     }
@@ -803,6 +879,13 @@
     }
 
     /**
+     * @return The type of this sensor as a string.
+     */
+    public UUID getUuid() {
+        return mUuid;
+    }
+
+    /**
      * @hide
      * @return The permission required to access this sensor. If empty, no permission is required.
      */
@@ -985,6 +1068,9 @@
             case TYPE_DEVICE_ORIENTATION:
                 mStringType = STRING_TYPE_DEVICE_ORIENTATION;
                 return true;
+            case TYPE_DYNAMIC_SENSOR_META:
+                mStringType = STRING_TYPE_DYNAMIC_SENSOR_META;
+                return true;
             default:
                 return false;
         }
diff --git a/core/java/android/hardware/SensorAdditionalInfo.java b/core/java/android/hardware/SensorAdditionalInfo.java
new file mode 100644
index 0000000..8e5b8a3
--- /dev/null
+++ b/core/java/android/hardware/SensorAdditionalInfo.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class represents a {@link android.hardware.Sensor Sensor} additional information frame,
+ * which is reported through listener callback {@link
+ * android.hardware.SensorEventCallback#onSensorAdditionalInfo onSensorAdditionalInfo}.
+ *
+ * @see SensorManager
+ * @see SensorEventListener3
+ * @see Sensor
+ *
+ */
+
+public class SensorAdditionalInfo {
+
+    /**
+     * The sensor that generated this event. See
+     * {@link android.hardware.SensorManager SensorManager} for details.
+     */
+    public final Sensor sensor;
+
+    /**
+     * Type of this additional info frame.
+     */
+    public final int type;
+
+    /**
+     * Sequence number of frame for a certain type.
+     */
+    public final int serial;
+
+    /**
+     * Additional info payload data represented in float values. Depending on the type of
+     * information, this may be null.
+     */
+    public final float[] floatValues;
+
+    /**
+     * Additional info payload data represented in int values. Depending on the type of information,
+     * this may be null.
+     */
+    public final int[] intValues;
+
+    /**
+     * Typical values of additional infomation type. The set of values is subject to extension in
+     * newer versions and vendors have the freedom of define their own custom values.
+     *
+     * @hide
+     */
+    @IntDef({TYPE_FRAME_BEGIN, TYPE_FRAME_END, TYPE_UNTRACKED_DELAY, TYPE_INTERNAL_TEMPERATURE,
+             TYPE_VEC3_CALIBRATION, TYPE_SENSOR_PLACEMENT, TYPE_SAMPLING})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AdditionalInfoType {}
+
+    /**
+     * Mark the beginning of a set of additional info frames.
+     */
+    public static final int TYPE_FRAME_BEGIN = 0;
+
+    /**
+     * Mark the end of a set of additional info frames.
+     */
+    public static final int TYPE_FRAME_END = 1;
+
+    /**
+     * Untracked delay. Delays that are introduced by data processing, such as filtering, which is
+     * not taken into account by sensor timestamps.
+     *
+     * Payload:
+     *     floatValues[0]: delay estimation in seconds
+     *     floatValues[1]: delay estimation standard deviation
+     */
+    public static final int TYPE_UNTRACKED_DELAY = 0x10000;
+
+    /**
+     * Internal temperature. Sensor hardware device internal temperature.
+     *
+     * Payload:
+     *     floatValues[0]: internal temperature in Celsius.
+     */
+    public static final int TYPE_INTERNAL_TEMPERATURE = 0x10001;
+
+    /**
+     * Vector calibration parameter. Calibration applied to a sensor with 3 elements vector output,
+     * such as accelerometer, gyro, etc.
+     *
+     * Payload:
+     *     floatValues[0..11]: First 3 rows of a homogenous matrix in row major order that captures
+     *     any linear transformation, including rotation, scaling, shear, shift.
+     */
+    public static final int TYPE_VEC3_CALIBRATION = 0x10002;
+
+    /**
+     * Sensor placement. Describes location and installation angle of the sensor device.
+     *
+     * Payload:
+     *     floatValues[0..11]: First 3 rows of homogeneous matrix in row major order that describes
+     *     the location and orientation of the sensor. Origin of reference will be the mobile device
+     *     geometric sensor. Reference frame is defined as the same as Android sensor frame.
+     */
+    public static final int TYPE_SENSOR_PLACEMENT = 0x10003;
+
+    /**
+     * Sampling parameter. Describes the raw sample period and estimated jitter of sample time in
+     * terms of standard deviation.
+     *
+     * Payload:
+     *     floatValues[0]: raw sample period in seconds.
+     *     floatValues[1]: standard deviation of sampling period.
+     */
+    public static final int TYPE_SAMPLING = 0x10004;
+
+    SensorAdditionalInfo(
+            Sensor aSensor, int aType, int aSerial, int [] aIntValues, float [] aFloatValues) {
+        sensor = aSensor;
+        type = aType;
+        serial = aSerial;
+        intValues = aIntValues;
+        floatValues = aFloatValues;
+    }
+}
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 416c74c..35c96f7 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -396,7 +396,7 @@
      * dv = 216.7 *
      * (rh / 100.0 * 6.112 * Math.exp(17.62 * t / (243.12 + t)) / (273.15 + t));
      * </pre>
-     * 
+     *
      * <h4>{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE Sensor.TYPE_AMBIENT_TEMPERATURE}:
      * </h4>
      *
@@ -531,6 +531,53 @@
      *
      * </ul>
      *
+     *   <h4>{@link android.hardware.Sensor#TYPE_STATIONARY_DETECT
+     * Sensor.TYPE_STATIONARY_DETECT}:</h4>
+     *
+     * A TYPE_STATIONARY_DETECT event is produced if the device has been
+     * stationary for at least 5 seconds with a maximal latency of 5
+     * additional seconds. ie: it may take up anywhere from 5 to 10 seconds
+     * afte the device has been at rest to trigger this event.
+     *
+     * The only allowed value is 1.0.
+     *
+     * <ul>
+     *  <li> values[0]: 1.0 </li>
+     * </ul>
+     *
+     *   <h4>{@link android.hardware.Sensor#TYPE_MOTION_DETECT
+     * Sensor.TYPE_MOTION_DETECT}:</h4>
+     *
+     * A TYPE_MOTION_DETECT event is produced if the device has been in
+     * motion  for at least 5 seconds with a maximal latency of 5
+     * additional seconds. ie: it may take up anywhere from 5 to 10 seconds
+     * afte the device has been at rest to trigger this event.
+     *
+     * The only allowed value is 1.0.
+     *
+     * <ul>
+     *  <li> values[0]: 1.0 </li>
+     * </ul>
+     *
+     *   <h4>{@link android.hardware.Sensor#TYPE_HEART_BEAT
+     * Sensor.TYPE_HEART_BEAT}:</h4>
+     *
+     * A sensor of this type returns an event everytime a hear beat peak is
+     * detected.
+     *
+     * Peak here ideally corresponds to the positive peak in the QRS complex of
+     * an ECG signal.
+     *
+     * <ul>
+     *  <li> values[0]: confidence</li>
+     * </ul>
+     *
+     * <p>
+     * A confidence value of 0.0 indicates complete uncertainty - that a peak
+     * is as likely to be at the indicated timestamp as anywhere else.
+     * A confidence value of 1.0 indicates complete certainly - that a peak is
+     * completely unlikely to be anywhere else on the QRS complex.
+     * </p>
      */
     public final float[] values;
 
diff --git a/core/java/android/hardware/SensorEventCallback.java b/core/java/android/hardware/SensorEventCallback.java
new file mode 100644
index 0000000..bac212a
--- /dev/null
+++ b/core/java/android/hardware/SensorEventCallback.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+/**
+ * Used for receiving sensor additional information frames.
+ */
+public abstract class SensorEventCallback implements SensorEventListener2 {
+
+    /**
+     * Called when sensor values have changed.
+     *
+     * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
+     */
+    @Override
+    public void onSensorChanged(SensorEvent event) {}
+
+    /**
+     * Called when the accuracy of the registered sensor has changed.
+     *
+     * @see android.hardware.SensorEventListener#onAccuracyChanged(Sensor, int)
+     */
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+    /**
+     * Called after flush() is completed.
+     *
+     * @see android.hardware.SensorEventListener2#onFlushCompleted(Sensor)
+     */
+    @Override
+    public void onFlushCompleted(Sensor sensor) {}
+
+    /**
+     * Called when a sensor additional information frame is available.
+     *
+     * @param info A {@link android.hardware.SensorAdditionalInfo SensorAdditionalInfo} frame
+     * reported from sensor hardware.
+     */
+    public void onSensorAdditionalInfo(SensorAdditionalInfo info) {}
+}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 5d405f9..f0b17c30 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -377,6 +377,12 @@
     protected abstract List<Sensor> getFullSensorList();
 
     /**
+     * Gets the full list of dynamic sensors that are available.
+     * @hide
+     */
+    protected abstract List<Sensor> getFullDynamicSensorList();
+
+    /**
      * @return available sensors.
      * @deprecated This method is deprecated, use
      *             {@link SensorManager#getSensorList(int)} instead
@@ -430,6 +436,38 @@
     }
 
     /**
+     * Use this method to get a list of available dynamic sensors of a certain type.
+     * Make multiple calls to get sensors of different types or use
+     * {@link android.hardware.Sensor#TYPE_ALL Sensor.TYPE_ALL} to get all dynamic sensors.
+     *
+     * <p class="note">
+     * NOTE: Both wake-up and non wake-up sensors matching the given type are
+     * returned. Check {@link Sensor#isWakeUpSensor()} to know the wake-up properties
+     * of the returned {@link Sensor}.
+     * </p>
+     *
+     * @param type of sensors requested
+     *
+     * @return a list of dynamic sensors matching the requested type.
+     *
+     * @see Sensor
+     */
+    public List<Sensor> getDynamicSensorList(int type) {
+        // cache the returned lists the first time
+        final List<Sensor> fullList = getFullDynamicSensorList();
+        if (type == Sensor.TYPE_ALL) {
+            return Collections.unmodifiableList(fullList);
+        } else {
+            List<Sensor> list = new ArrayList();
+            for (Sensor i : fullList) {
+                if (i.getType() == type)
+                    list.add(i);
+            }
+            return Collections.unmodifiableList(list);
+        }
+    }
+
+    /**
      * Use this method to get the default sensor for a given type. Note that the
      * returned sensor could be a composite sensor, and its data could be
      * averaged or filtered. If you need to access the raw sensors use
@@ -841,6 +879,86 @@
     /** @hide */
     protected abstract boolean flushImpl(SensorEventListener listener);
 
+
+    /**
+     * Used for receiving notifications from the SensorManager when dynamic sensors are connected or
+     * disconnected.
+     */
+    public static abstract class DynamicSensorConnectionCallback {
+        /**
+         * Called when there is a dynamic sensor being connected to the system.
+         *
+         * @param sensor the newly connected sensor. See {@link android.hardware.Sensor Sensor}.
+         */
+        public void onDynamicSensorConnected(Sensor sensor) {}
+
+        /**
+         * Called when there is a dynamic sensor being disconnected from the system.
+         *
+         * @param sensor the disconnected sensor. See {@link android.hardware.Sensor Sensor}.
+         */
+        public void onDynamicSensorDisconnected(Sensor sensor) {}
+    }
+
+
+    /**
+     * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+     * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
+     * registration with the already registered callback object will have no additional effect.
+     *
+     * @param callback An object that implements the
+     *        {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+     *        DynamicSensorConnectionCallback}
+     *        interface for receiving callbacks.
+     * @see #addDynamicSensorCallback(DynamicSensorConnectionCallback, Handler)
+     *
+     * @throws IllegalArgumentException when callback is null.
+     */
+    public void registerDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
+        registerDynamicSensorCallback(callback, null);
+    }
+
+    /**
+     * Add a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+     * DynamicSensorConnectionCallback} to receive dynamic sensor connection callbacks. Repeat
+     * registration with the already registered callback object will have no additional effect.
+     *
+     * @param callback An object that implements the
+     *        {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+     *        DynamicSensorConnectionCallback} interface for receiving callbacks.
+     * @param handler The {@link android.os.Handler Handler} the {@link
+     *        android.hardware.SensorManager.DynamicSensorConnectionCallback
+     *        sensor connection events} will be delivered to.
+     *
+     * @throws IllegalArgumentException when callback is null.
+     */
+    public void registerDynamicSensorCallback(
+            DynamicSensorConnectionCallback callback, Handler handler) {
+        registerDynamicSensorCallbackImpl(callback, handler);
+    }
+
+    /**
+     * Remove a {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+     * DynamicSensorConnectionCallback} to stop sending dynamic sensor connection events to that
+     * callback.
+     *
+     * @param callback An object that implements the
+     *        {@link android.hardware.SensorManager.DynamicSensorConnectionCallback
+     *        DynamicSensorConnectionCallback}
+     *        interface for receiving callbacks.
+     */
+    public void unregisterDynamicSensorCallback(DynamicSensorConnectionCallback callback) {
+        unregisterDynamicSensorCallbackImpl(callback);
+    }
+
+    /** @hide */
+    protected abstract void registerDynamicSensorCallbackImpl(
+            DynamicSensorConnectionCallback callback, Handler handler);
+
+    /** @hide */
+    protected abstract void unregisterDynamicSensorCallbackImpl(
+            DynamicSensorConnectionCallback callback);
+
     /**
      * <p>
      * Computes the inclination matrix <b>I</b> as well as the rotation matrix
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 2fe8fb6..c4afbfb 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -17,7 +17,10 @@
 package android.hardware;
 
 import android.Manifest;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -32,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Sensor manager implementation that communicates with the built-in
@@ -40,10 +44,14 @@
  * @hide
  */
 public class SystemSensorManager extends SensorManager {
+    //TODO: disable extra logging before release
+    private static boolean DEBUG_DYNAMIC_SENSOR = true;
+
     private static native void nativeClassInit();
     private static native long nativeCreate(String opPackageName);
     private static native boolean nativeGetSensorAtIndex(long nativeInstance,
             Sensor sensor, int index);
+    private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
 
     private static boolean sSensorModuleInitialized = false;
@@ -52,7 +60,10 @@
     private final Object mLock = new Object();
 
     private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
-    private final SparseArray<Sensor> mHandleToSensor = new SparseArray<>();
+    private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
+    private boolean mDynamicSensorListDirty = true;
+
+    private final HashMap<Integer, Sensor> mHandleToSensor = new HashMap<>();
 
     // Listener list
     private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
@@ -60,6 +71,11 @@
     private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
             new HashMap<TriggerEventListener, TriggerEventQueue>();
 
+    // Dynamic Sensor callbacks
+    private HashMap<DynamicSensorConnectionCallback, Handler>
+            mDynamicSensorCallbacks = new HashMap<>();
+    private BroadcastReceiver mDynamicSensorBroadcastReceiver;
+
     // Looper associated with the context in which this instance was created.
     private final Looper mMainLooper;
     private final int mTargetSdkLevel;
@@ -84,7 +100,7 @@
                 Sensor sensor = new Sensor();
                 if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
                 mFullSensorsList.add(sensor);
-                mHandleToSensor.append(sensor.getHandle(), sensor);
+                mHandleToSensor.put(sensor.getHandle(), sensor);
             }
         }
     }
@@ -96,6 +112,15 @@
         return mFullSensorsList;
     }
 
+    /** @hide */
+    @Override
+    protected List<Sensor> getFullDynamicSensorList() {
+        // only set up broadcast receiver if the application tries to find dynamic sensors or
+        // explicitly register a DynamicSensorConnectionCallback
+        setupDynamicSensorBroadcastReceiver();
+        updateDynamicSensorList();
+        return mFullDynamicSensorsList;
+    }
 
     /** @hide */
     @Override
@@ -274,6 +299,187 @@
         }
     }
 
+    private void cleanupSensorConnection(Sensor sensor) {
+        mHandleToSensor.remove(sensor.getHandle());
+
+        if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
+            synchronized(mTriggerListeners) {
+                for (TriggerEventListener l: mTriggerListeners.keySet()) {
+                    if (DEBUG_DYNAMIC_SENSOR){
+                        Log.i(TAG, "removed trigger listener" + l.toString() +
+                                   " due to sensor disconnection");
+                    }
+                    cancelTriggerSensorImpl(l, sensor, true);
+                }
+            }
+        } else {
+            synchronized(mSensorListeners) {
+                for (SensorEventListener l: mSensorListeners.keySet()) {
+                    if (DEBUG_DYNAMIC_SENSOR){
+                        Log.i(TAG, "removed event listener" + l.toString() +
+                                   " due to sensor disconnection");
+                    }
+                    unregisterListenerImpl(l, sensor);
+                }
+            }
+        }
+    }
+
+    private void updateDynamicSensorList() {
+        synchronized(mFullDynamicSensorsList) {
+            if (mDynamicSensorListDirty) {
+                List<Sensor> list = new ArrayList<>();
+                nativeGetDynamicSensors(mNativeInstance, list);
+
+                final List<Sensor> updatedList = new ArrayList<>();
+                final List<Sensor> addedList = new ArrayList<>();
+                final List<Sensor> removedList = new ArrayList<>();
+
+                boolean changed = diffSortedSensorList(
+                        mFullDynamicSensorsList, list, updatedList, addedList, removedList);
+
+                if (changed) {
+                    if (DEBUG_DYNAMIC_SENSOR) {
+                        Log.i(TAG, "DYNS dynamic sensor list cached should be updated");
+                    }
+                    mFullDynamicSensorsList = updatedList;
+
+                    for (Sensor s: addedList) {
+                        mHandleToSensor.put(s.getHandle(), s);
+                    }
+
+                    Handler mainHandler = new Handler(mContext.getMainLooper());
+
+                    for (Map.Entry<DynamicSensorConnectionCallback, Handler> entry :
+                            mDynamicSensorCallbacks.entrySet()) {
+                        final DynamicSensorConnectionCallback callback = entry.getKey();
+                        Handler handler =
+                                entry.getValue() == null ? mainHandler : entry.getValue();
+
+                        handler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                for (Sensor s: addedList) {
+                                    callback.onDynamicSensorConnected(s);
+                                }
+                                for (Sensor s: removedList) {
+                                    callback.onDynamicSensorDisconnected(s);
+                                }
+                            }
+                        });
+                    }
+
+                    for (Sensor s: removedList) {
+                        cleanupSensorConnection(s);
+                    }
+                }
+
+                mDynamicSensorListDirty = false;
+            }
+        }
+    }
+
+    private void setupDynamicSensorBroadcastReceiver() {
+        if (mDynamicSensorBroadcastReceiver == null) {
+            mDynamicSensorBroadcastReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (intent.getAction() == Intent.ACTION_DYNAMIC_SENSOR_CHANGED) {
+                        if (DEBUG_DYNAMIC_SENSOR) {
+                            Log.i(TAG, "DYNS received DYNAMIC_SENSOR_CHANED broadcast");
+                        }
+                        // Dynamic sensors probably changed
+                        mDynamicSensorListDirty = true;
+                        updateDynamicSensorList();
+                    }
+                }
+            };
+
+            IntentFilter filter = new IntentFilter("dynamic_sensor_change");
+            filter.addAction(Intent.ACTION_DYNAMIC_SENSOR_CHANGED);
+            mContext.registerReceiver(mDynamicSensorBroadcastReceiver, filter);
+        }
+    }
+
+    private void teardownDynamicSensorBroadcastReceiver() {
+        mDynamicSensorCallbacks.clear();
+        mContext.unregisterReceiver(mDynamicSensorBroadcastReceiver);
+        mDynamicSensorBroadcastReceiver = null;
+    }
+
+    /** @hide */
+    protected void registerDynamicSensorCallbackImpl(
+            DynamicSensorConnectionCallback callback, Handler handler) {
+        if (DEBUG_DYNAMIC_SENSOR) {
+            Log.i(TAG, "DYNS Register dynamic sensor callback");
+        }
+
+        if (callback == null) {
+            throw new IllegalArgumentException("callback cannot be null");
+        }
+        if (mDynamicSensorCallbacks.containsKey(callback)) {
+            // has been already registered, ignore
+            return;
+        }
+
+        setupDynamicSensorBroadcastReceiver();
+        mDynamicSensorCallbacks.put(callback, handler);
+    }
+
+    /** @hide */
+    protected void unregisterDynamicSensorCallbackImpl(
+            DynamicSensorConnectionCallback callback) {
+        if (DEBUG_DYNAMIC_SENSOR) {
+            Log.i(TAG, "Removing dynamic sensor listerner");
+        }
+        mDynamicSensorCallbacks.remove(callback);
+    }
+
+    /*
+     * Find the difference of two List<Sensor> assuming List are sorted by handle of sensor,
+     * assuming the input list is already sorted by handle. Inputs are ol and nl; outputs are
+     * updated, added and removed. Any of the output lists can be null in case the result is not
+     * interested.
+     */
+    private static boolean diffSortedSensorList(
+            List<Sensor> oldList, List<Sensor> newList, List<Sensor> updated,
+            List<Sensor> added, List<Sensor> removed) {
+
+        boolean changed = false;
+
+        int i = 0, j = 0;
+        while (true) {
+            if (j < oldList.size() && ( i >= newList.size() ||
+                    newList.get(i).getHandle() > oldList.get(j).getHandle()) ) {
+                changed = true;
+                if (removed != null) {
+                    removed.add(oldList.get(j));
+                }
+                ++j;
+            } else if (i < newList.size() && ( j >= oldList.size() ||
+                    newList.get(i).getHandle() < oldList.get(j).getHandle())) {
+                changed = true;
+                if (added != null) {
+                    added.add(newList.get(i));
+                }
+                if (updated != null) {
+                    updated.add(newList.get(i));
+                }
+                ++i;
+            } else if (i < newList.size() && j < oldList.size() &&
+                    newList.get(i).getHandle() == oldList.get(j).getHandle()) {
+                if (updated != null) {
+                    updated.add(oldList.get(j));
+                }
+                ++i;
+                ++j;
+            } else {
+                break;
+            }
+        }
+        return changed;
+    }
+
     /*
      * BaseEventQueue is the communication channel with the sensor service,
      * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
@@ -284,7 +490,7 @@
      */
     private static abstract class BaseEventQueue {
         private static native long nativeInitBaseEventQueue(long nativeManager,
-                WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ, float[] scratch,
+                WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,
                 String packageName, int mode, String opPackageName);
         private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
                 int maxBatchReportLatencyUs);
@@ -297,9 +503,7 @@
         private long nSensorEventQueue;
         private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
         protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
-        protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
         private final CloseGuard mCloseGuard = CloseGuard.get();
-        private final float[] mScratch = new float[16];
         protected final SystemSensorManager mManager;
 
         protected static final int OPERATING_MODE_NORMAL = 0;
@@ -308,7 +512,7 @@
         BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {
             if (packageName == null) packageName = "";
             nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
-                    new WeakReference<>(this), looper.getQueue(), mScratch,
+                    new WeakReference<>(this), looper.getQueue(),
                     packageName, mode, manager.mContext.getOpPackageName());
             mCloseGuard.open("dispose");
             mManager = manager;
@@ -348,7 +552,7 @@
                         mActiveSensors.put(handle, false);
                         removeSensorEvent(sensor);
                     } else {
-                        // it should never happen -- just ignore.
+                        // sensor just disconnected -- just ignore.
                     }
                 }
             }
@@ -420,6 +624,11 @@
                 long timestamp);
         protected abstract void dispatchFlushCompleteEvent(int handle);
 
+        protected void dispatchAdditionalInfoEvent(
+                int handle, int type, int serial, float[] floatValues, int[] intValues) {
+            // default implementation is do nothing
+        }
+
         protected abstract void addSensorEvent(Sensor sensor);
         protected abstract void removeSensorEvent(Sensor sensor);
     }
@@ -456,6 +665,11 @@
         protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
                 long timestamp) {
             final Sensor sensor = mManager.mHandleToSensor.get(handle);
+            if (sensor == null) {
+                // sensor disconnected
+                return;
+            }
+
             SensorEvent t = null;
             synchronized (mSensorsEvents) {
                 t = mSensorsEvents.get(handle);
@@ -481,14 +695,37 @@
             mListener.onSensorChanged(t);
         }
 
+        // Called from native code.
         @SuppressWarnings("unused")
+        @Override
         protected void dispatchFlushCompleteEvent(int handle) {
             if (mListener instanceof SensorEventListener2) {
                 final Sensor sensor = mManager.mHandleToSensor.get(handle);
+                if (sensor == null) {
+                    // sensor disconnected
+                    return;
+                }
                 ((SensorEventListener2)mListener).onFlushCompleted(sensor);
             }
             return;
         }
+
+        // Called from native code.
+        @SuppressWarnings("unused")
+        @Override
+        protected void dispatchAdditionalInfoEvent(
+                int handle, int type, int serial, float[] floatValues, int[] intValues) {
+            if (mListener instanceof SensorEventCallback) {
+                final Sensor sensor = mManager.mHandleToSensor.get(handle);
+                if (sensor == null) {
+                    // sensor disconnected
+                    return;
+                }
+                SensorAdditionalInfo info =
+                        new SensorAdditionalInfo(sensor, type, serial, intValues, floatValues);
+                ((SensorEventCallback)mListener).onSensorAdditionalInfo(info);
+            }
+        }
     }
 
     static final class TriggerEventQueue extends BaseEventQueue {
@@ -523,6 +760,10 @@
         protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
                 long timestamp) {
             final Sensor sensor = mManager.mHandleToSensor.get(handle);
+            if (sensor == null) {
+                // sensor disconnected
+                return;
+            }
             TriggerEvent t = null;
             synchronized (mTriggerEvents) {
                 t = mTriggerEvents.get(handle);
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 28bb22a..6aacc9c 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -575,14 +575,16 @@
      * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_3 LEVEL_3}) devices
      * support at least the following stream combinations for creating a reprocessable capture
      * session in addition to those for
-     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} devices. Note that targets in the "Reprocess-only target" column may only be
-     * used as an output target for a reprocess capture request, not as an output to a regular capture request.
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} devices. Note that while
+     * the second configuration allows for configuring {@code MAXIMUM} {@code YUV} and {@code JPEG}
+     * outputs at the same time, that configuration is not listed for regular capture sessions, and
+     * therefore simultaneous output to both targets is not allowed.
      *
      * <table>
      * <tr><th colspan="13">LEVEL-3 additional guaranteed configurations for creating a reprocessable capture session<br>({@code PRIV} input is guaranteed only if PRIVATE reprocessing is supported. {@code YUV} input is always guaranteed.</th></tr>
-     * <tr><th colspan="2" id="rb">Input</th><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th colspan="2" id="rb">Reprocess-only target</th><th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th colspan="2" id="rb">Input</th><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th colspan="2" id="rb">Target 4</th><th colspan="2" id="rb">Target 5</th><th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
-     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code 640x480}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>In-app viewfinder analysis with ZSL and RAW.</td> </tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code 640x480}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>In-app viewfinder analysis with ZSL and RAW.</td> </tr>
      * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code 640x480}</td> <td>{@code RAW}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td><td>In-app viewfinder analysis with ZSL, RAW, and JPEG reprocessing output.</td> </tr>
      * </table><br>
      * </p>
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index c96c9be..9f8c28e 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -491,12 +491,13 @@
      * credentials (e.g. pin, pattern or password).
      * @param cancel an object that can be used to cancel enrollment
      * @param flags optional flags
+     * @param userId the user to whom this fingerprint will belong to
      * @param callback an object to receive enrollment events
      * @hide
      */
     @RequiresPermission(MANAGE_FINGERPRINT)
     public void enroll(byte [] token, CancellationSignal cancel, int flags,
-            EnrollmentCallback callback, int userId) {
+            int userId, EnrollmentCallback callback) {
         if (userId == UserHandle.USER_CURRENT) {
             userId = getCurrentUserId();
         }
@@ -576,17 +577,18 @@
     /**
      * Remove given fingerprint template from fingerprint hardware and/or protected storage.
      * @param fp the fingerprint item to remove
+     * @param userId the user who this fingerprint belongs to
      * @param callback an optional callback to verify that fingerprint templates have been
      * successfully removed. May be null of no callback is required.
      *
      * @hide
      */
     @RequiresPermission(MANAGE_FINGERPRINT)
-    public void remove(Fingerprint fp, RemovalCallback callback) {
+    public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
         if (mService != null) try {
             mRemovalCallback = callback;
             mRemovalFingerprint = fp;
-            mService.remove(mToken, fp.getFingerId(), getCurrentUserId(), mServiceReceiver);
+            mService.remove(mToken, fp.getFingerId(), userId, mServiceReceiver);
         } catch (RemoteException e) {
             Log.w(TAG, "Remote exception in remove: ", e);
             if (callback != null) {
@@ -599,16 +601,17 @@
     /**
      * Renames the given fingerprint template
      * @param fpId the fingerprint id
+     * @param userId the user who this fingerprint belongs to
      * @param newName the new name
      *
      * @hide
      */
     @RequiresPermission(MANAGE_FINGERPRINT)
-    public void rename(int fpId, String newName) {
+    public void rename(int fpId, int userId, String newName) {
         // Renames the given fpId
         if (mService != null) {
             try {
-                mService.rename(fpId, getCurrentUserId(), newName);
+                mService.rename(fpId, userId, newName);
             } catch (RemoteException e) {
                 Log.v(TAG, "Remote exception in rename(): ", e);
             }
diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java
index 584008c..2cafa08 100644
--- a/core/java/android/hardware/input/KeyboardLayout.java
+++ b/core/java/android/hardware/input/KeyboardLayout.java
@@ -16,8 +16,10 @@
 
 package android.hardware.input;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.LocaleList;
 
 import java.util.Locale;
 
@@ -32,7 +34,8 @@
     private final String mLabel;
     private final String mCollection;
     private final int mPriority;
-    private final Locale[] mLocales;
+    @NonNull
+    private final LocaleList mLocales;
     private final int mVendorId;
     private final int mProductId;
 
@@ -47,16 +50,12 @@
     };
 
     public KeyboardLayout(String descriptor, String label, String collection, int priority,
-            Locale[] locales, int vid, int pid) {
+            LocaleList locales, int vid, int pid) {
         mDescriptor = descriptor;
         mLabel = label;
         mCollection = collection;
         mPriority = priority;
-        if (locales != null) {
-            mLocales = locales;
-        } else {
-            mLocales = new Locale[0];
-        }
+        mLocales = locales;
         mVendorId = vid;
         mProductId = pid;
     }
@@ -66,11 +65,7 @@
         mLabel = source.readString();
         mCollection = source.readString();
         mPriority = source.readInt();
-        int N = source.readInt();
-        mLocales = new Locale[N];
-        for (int i = 0; i < N; i++) {
-            mLocales[i] = Locale.forLanguageTag(source.readString());
-        }
+        mLocales = LocaleList.CREATOR.createFromParcel(source);
         mVendorId = source.readInt();
         mProductId = source.readInt();
     }
@@ -108,7 +103,7 @@
      * This may be empty if a locale has not been assigned to this keyboard layout.
      * @return The keyboard layout's intended locale.
      */
-    public Locale[] getLocales() {
+    public LocaleList getLocales() {
         return mLocales;
     }
 
@@ -141,14 +136,7 @@
         dest.writeString(mLabel);
         dest.writeString(mCollection);
         dest.writeInt(mPriority);
-        if (mLocales != null) {
-            dest.writeInt(mLocales.length);
-            for (Locale l : mLocales) {
-                dest.writeString(l.toLanguageTag());
-            }
-        } else {
-            dest.writeInt(0);
-        }
+        mLocales.writeToParcel(dest, 0);
         dest.writeInt(mVendorId);
         dest.writeInt(mProductId);
     }
diff --git a/core/java/android/hardware/location/ContextHubInfo.aidl b/core/java/android/hardware/location/ContextHubInfo.aidl
new file mode 100644
index 0000000..1a9221a
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubInfo.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+/*
+@hide
+*/
+parcelable ContextHubInfo;
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
new file mode 100644
index 0000000..e47c541
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.location;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * @hide
+  */
+@SystemApi
+public class ContextHubInfo {
+    private int mId;
+    private String mName;
+    private String mVendor;
+    private String mToolchain;
+    private int mPlatformVersion;
+    private int mStaticSwVersion;
+    private int mToolchainVersion;
+    private float mPeakMips;
+    private float mStoppedPowerDrawMw;
+    private float mSleepPowerDrawMw;
+    private float mPeakPowerDrawMw;
+
+    private int[] mSupportedSensors;
+
+    private MemoryRegion[] mMemoryRegions;
+
+    public ContextHubInfo() {
+    }
+
+    /**
+     * get the context hub unique identifer
+     *
+     * @return int - unique system wide identifier
+     */
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * set the context hub unique identifer
+     *
+     * @param id - unique system wide identifier for the hub
+     */
+    public void setId(int id) {
+        mId = id;
+    }
+
+    /**
+     * get a string as a hub name
+     *
+     * @return String - a name for the hub
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * set a string as the hub name
+     *
+     * @param String - the name for the hub
+     */
+    public void setName(String name) {
+        mName = name;
+    }
+
+    /**
+     * get a string as the vendor name
+     *
+     * @return String - a name for the vendor
+     */
+    public String getVendor() {
+        return mVendor;
+    }
+
+    /**
+     * set a string as the vendor name
+     *
+     * @param String - a name for the vendor
+     */
+    public void setVendor(String vendor) {
+        mVendor = vendor;
+    }
+
+    /**
+     * get tool chain string
+     *
+     * @return String - description of the tool chain
+     */
+    public String getToolchain() {
+        return mToolchain;
+    }
+
+    /**
+     * set tool chain string
+     *
+     * @param String - description of the tool chain
+     */
+    public void setToolchain(String toolchain) {
+        mToolchain = toolchain;
+    }
+
+    /**
+     * get platform version
+     *
+     * @return int - platform version number
+     */
+    public int getPlatformVersion() {
+        return mPlatformVersion;
+    }
+
+    /**
+     * set platform version
+     *
+     * @param platformVersion - platform version number
+     */
+    public void setPlatformVersion(int platformVersion) {
+        mPlatformVersion = platformVersion;
+    }
+
+    /**
+     * get static platform version number
+     *
+     * @return int - platform version number
+     */
+    public int getStaticSwVersion() {
+        return mStaticSwVersion;
+    }
+
+    /**
+     * set platform software version
+     *
+     * @param staticSwVersion - platform static s/w version number
+     */
+    public void setStaticSwVersion(int staticSwVersion) {
+        mStaticSwVersion = staticSwVersion;
+    }
+
+    /**
+     * get the tool chain version
+     *
+     * @return int - the tool chain version
+     */
+    public int getToolchainVersion() {
+        return mToolchainVersion;
+    }
+
+    /**
+     * set the tool chain version number
+     *
+     * @param toolchainVersion - tool chain version number
+     */
+    public void setToolchainVersion(int toolchainVersion) {
+        mToolchainVersion = toolchainVersion;
+    }
+
+    /**
+     * get the peak processing mips the hub can support
+     *
+     * @return float - peak MIPS that this hub can deliver
+     */
+    public float getPeakMips() {
+        return mPeakMips;
+    }
+
+    /**
+     * set the peak mips that this hub can support
+     *
+     * @param peakMips - peak mips this hub can deliver
+     */
+    public void setPeakMips(float peakMips) {
+        mPeakMips = peakMips;
+    }
+
+    /**
+     * get the stopped power draw in milliwatts
+     * This assumes that the hub enter a stopped state - which is
+     * different from the sleep state. Latencies on exiting the
+     * sleep state are typically higher and expect to be in multiple
+     * milliseconds.
+     *
+     * @return float - power draw by the hub in stopped state
+     */
+    public float getStoppedPowerDrawMw() {
+        return mStoppedPowerDrawMw;
+    }
+
+    /**
+     * Set the power consumed by the hub in stopped state
+     *
+     * @param stoppedPowerDrawMw - stopped power in milli watts
+     */
+    public void setStoppedPowerDrawMw(float stoppedPowerDrawMw) {
+        mStoppedPowerDrawMw = stoppedPowerDrawMw;
+    }
+
+    /**
+     * get the power draw of the hub in sleep mode. This assumes
+     * that the hub supports a sleep mode in which the power draw is
+     * lower than the power consumed when the hub is actively
+     * processing. As a guideline, assume that the hub should be
+     * able to enter sleep mode if it knows reliably on completion
+     * of some task that the next interrupt/scheduled work item is
+     * at least 250 milliseconds later.
+     *
+     * @return float - sleep power draw in milli watts
+     */
+    public float getSleepPowerDrawMw() {
+        return mSleepPowerDrawMw;
+    }
+
+    /**
+     * Set the sleep power draw in milliwatts
+     *
+     * @param sleepPowerDrawMw - sleep power draw in milliwatts.
+     */
+    public void setSleepPowerDrawMw(float sleepPowerDrawMw) {
+        mSleepPowerDrawMw = sleepPowerDrawMw;
+    }
+
+    /**
+     * get the peak powe draw of the hub. This is the power consumed
+     * by the hub at maximum load.
+     *
+     * @return float - peak power draw
+     */
+    public float getPeakPowerDrawMw() {
+        return mPeakPowerDrawMw;
+    }
+
+    /**
+     * set the peak power draw of the hub
+     *
+     * @param peakPowerDrawMw - peak power draw of the hub in
+     *                        milliwatts.
+     */
+    public void setPeakPowerDrawMw(float peakPowerDrawMw) {
+        mPeakPowerDrawMw = peakPowerDrawMw;
+    }
+
+    /**
+     * get the sensors supported by this hub
+     *
+     * @return int[] - all the supported sensors on this hub
+     *
+     * @see ContextHubManager
+     */
+    public int[] getSupportedSensors() {
+        return Arrays.copyOf(mSupportedSensors, mSupportedSensors.length);
+    }
+
+    /**
+     * get the various memory regions on this hub
+     *
+     * @return MemoryRegion[] - all the memory regions on this hub
+     *
+     * @see MemoryRegion
+     */
+    public MemoryRegion[] getMemoryRegions() {
+        return Arrays.copyOf(mMemoryRegions, mMemoryRegions.length);
+    }
+
+    /**
+     * set the supported sensors on this hub
+     *
+     * @param supportedSensors - supported sensors on this hub
+     */
+    public void setSupportedSensors(int[] supportedSensors) {
+        mSupportedSensors = Arrays.copyOf(supportedSensors, supportedSensors.length);
+    }
+
+    /**
+     * set memory regions for this hub
+     *
+     * @param memoryRegions - memory regions information
+     *
+     * @see MemoryRegion
+     */
+    public void setMemoryRegions(MemoryRegion[] memoryRegions) {
+        mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length);
+    }
+
+    private ContextHubInfo(Parcel in) {
+        mId = in.readInt();
+        mName = in.readString();
+        mVendor = in.readString();
+        mToolchain = in.readString();
+        mPlatformVersion = in.readInt();
+        mToolchainVersion = in.readInt();
+        mStaticSwVersion = in.readInt();
+        mPeakMips = in.readFloat();
+        mStoppedPowerDrawMw = in.readFloat();
+        mSleepPowerDrawMw = in.readFloat();
+        mPeakPowerDrawMw = in.readFloat();
+
+        int numSupportedSensors = in.readInt();
+        mSupportedSensors = new int[numSupportedSensors];
+        in.readIntArray(mSupportedSensors);
+        mMemoryRegions = in.createTypedArray(MemoryRegion.CREATOR);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mId);
+        out.writeString(mName);
+        out.writeString(mVendor);
+        out.writeString(mToolchain);
+        out.writeInt(mPlatformVersion);
+        out.writeInt(mToolchainVersion);
+        out.writeInt(mStaticSwVersion);
+        out.writeFloat(mPeakMips);
+        out.writeFloat(mStoppedPowerDrawMw);
+        out.writeFloat(mSleepPowerDrawMw);
+        out.writeFloat(mPeakPowerDrawMw);
+
+        out.writeInt(mSupportedSensors.length);
+        out.writeIntArray(mSupportedSensors);
+        out.writeTypedArray(mMemoryRegions, flags);
+    }
+
+    public static final Parcelable.Creator<ContextHubInfo> CREATOR
+            = new Parcelable.Creator<ContextHubInfo>() {
+        public ContextHubInfo createFromParcel(Parcel in) {
+            return new ContextHubInfo(in);
+        }
+
+        public ContextHubInfo[] newArray(int size) {
+            return new ContextHubInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
new file mode 100644
index 0000000..301b2e4
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.location;
+
+import android.annotation.SystemApi;
+import android.hardware.location.NanoAppInstanceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.Manifest;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * A class that exposes the Context hubs on a device to
+ * applicaions.
+ *
+ * Please not that this class is not expected to be used by
+ * unbundled applications. Also, calling applications are
+ * expected to have LOCTION_HARDWARE premissions to use this
+ * class.
+ *
+ * @hide
+ */
+@SystemApi
+public final class ContextHubManager {
+
+    private static final String TAG = "ContextHubManager";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
+
+    private Context mContext;
+    private IContextHubService mContextHubService;
+    private boolean mContextHubConnected;
+
+    /**
+     * A special context hub identifer meaning any possible hub on
+     * the system.
+     */
+    public static final int ANY_HUB       = -1;
+    /**
+     * A constant denoting a message to load a a Nano App
+     */
+    public static final int MSG_LOAD_NANO_APP   = 1;
+    /**
+     * A constant denoting a message to unload a a Nano App
+     */
+    public static final int MSG_UNLOAD_NANO_APP = 2;
+    /**
+     * A constant denoting a message to send a message
+     */
+    public static final int MSG_DATA_SEND       = 3;
+
+
+    /**
+     * Get a handle to all the context hubs in the system
+     * @return array of context hub handles
+     */
+    public int[] getContexthubHandles() {
+        int[] retVal = null;
+        if(mContextHubConnected) {
+            try {
+                retVal = mContextHubService.getContextHubHandles();
+            }catch (RemoteException e) {
+                Log.e (TAG, "Could not fetch context hub handles :" + e.toString());
+            }
+        }
+        return retVal;
+    }
+
+    /**
+     * Get more information about a specific hub.
+     *
+     * @param contexthubHandle Handle of context hub
+     *
+     * @return ContextHubInfo  returned information about the hub
+     *
+     * @see ContextHubInfo
+     */
+    public ContextHubInfo getContexthubInfo(int contexthubHandle) {
+        ContextHubInfo retVal = null;
+        if(mContextHubConnected) {
+            try {
+                retVal = mContextHubService.getContextHubInfo(contexthubHandle);
+            }catch (RemoteException e) {
+                Log.e (TAG, "Could not fetch context hub info :" + e.toString());
+            }
+        }
+
+        return(retVal);
+    }
+
+    /**
+     * Load a nanoapp on a specified context hub
+     *
+     * @param hubHandle handle of context hub to load the app on.
+     * @param app the nanoApp to load on the hub
+     *
+     * @return int nanoAppInstance of the loaded nanoApp on success,
+     *         -1 otherwise
+     *
+     * @see NanoApp
+     */
+    public int loadNanoApp(int hubHandle, NanoApp app) {
+        int retVal = -1;
+
+        if(mContextHubConnected) {
+            try {
+                retVal = mContextHubService.loadNanoApp(hubHandle, app);
+            }catch (RemoteException e) {
+                Log.e (TAG, "Could not fetch load nanoApp :" + e.toString());
+            }
+        }
+
+        return retVal;
+    }
+
+    /**
+     * Unload a specified nanoApp
+     *
+     * @param nanoAppInstanceHandle handle of the nanoApp to load
+     *
+     * @return int  0 on success, -1 otherewise
+     */
+    public int unloadNanoApp(int nanoAppInstanceHandle) {
+        int retVal = -1;
+
+        if(mContextHubConnected) {
+            try {
+                retVal = mContextHubService.unloadNanoApp(nanoAppInstanceHandle);
+            }catch (RemoteException e) {
+                Log.e (TAG, "Could not fetch unload nanoApp :" + e.toString());
+            }
+        }
+
+        return retVal;
+    }
+
+    /**
+     * get information about the nano app instance
+     *
+     * @param nanoAppInstanceHandle handle of the nanoAppInstance
+     *
+     * @return NanoAppInstanceInfo Inforamtion about the nano app
+     *         instance.
+     *
+     * @see NanoAppInstanceInfo
+     */
+    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) {
+        NanoAppInstanceInfo retVal = null;
+
+        if(mContextHubConnected) {
+            try {
+                retVal = mContextHubService.getNanoAppInstanceInfo(nanoAppInstanceHandle);
+            }catch (RemoteException e) {
+                Log.e (TAG, "Could not fetch nanoApp info :" + e.toString());
+            }
+        }
+
+        return retVal;
+    }
+
+    /**
+     * Find a specified nano app on the system
+     *
+     * @param hubHandle handle of hub to search for nano app
+     * @param filter filter specifying the search criteria for app
+     *
+     * @see NanoAppFilter
+     *
+     * @return Integer[] Array of handles to any found nano apps
+     */
+    public Integer[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
+        int[] temp;
+        Integer[] retVal = null;
+
+        if(mContextHubConnected) {
+            try {
+                temp = mContextHubService.findNanoAppOnHub(hubHandle, filter);
+                retVal = new Integer[temp.length];
+                for (int i = 0; i < temp.length; i++) {
+                    retVal[i] = temp[i];
+                }
+            }catch (RemoteException e) {
+                Log.e (TAG, "Could not query nanoApp instance :" + e.toString());
+            }
+        }
+
+        return retVal;
+    }
+
+    /**
+     * Send a message to a spcific nano app instance on a context
+     * hub
+     *
+     *
+     * @param hubHandle handle of the hub to send the message to
+     * @param nanoAppHandle  handle of the nano app to send to
+     * @param msg Message to be sent
+     *
+     * @see ContextHubMessage
+     *
+     * @return int 0 on success, -1 otherwise
+     */
+    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) {
+        int retVal = -1;
+
+        if(mContextHubConnected) {
+            try {
+                retVal = mContextHubService.sendMessage(hubHandle, nanoAppHandle, msg);
+            }catch (RemoteException e) {
+                Log.e (TAG, "Could not fetch send message :" + e.toString());
+            }
+        }
+
+        return retVal;
+    }
+
+    private void checkPermissions() {
+        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+    }
+
+    private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
+        @Override
+        public void onMessageReceipt(int hubId, int nanoAppId, ContextHubMessage msg) throws RemoteException {
+
+        }
+    };
+
+    private ContextHubManager(Context context) {
+        checkPermissions();
+        mContext = context;
+        mContextHubConnected = false;
+    }
+
+    private ServiceConnection mServiceConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            mContextHubService = IContextHubService.Stub.asInterface(service);
+            mContextHubConnected = true;
+
+            // Register our Callback
+            try {
+                mContextHubService.registerCallBack(mClientCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not register callback with context hub service :" + e.toString());
+            }
+            Log.d(TAG, "contexthub manager connected to " + name.toString());
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mContextHubService = null;
+            mContextHubConnected = false;
+            Log.d(TAG, "contexthub manager disconnected from " + name.toString());
+        }
+    };
+
+}
diff --git a/core/java/android/hardware/location/ContextHubMessage.aidl b/core/java/android/hardware/location/ContextHubMessage.aidl
new file mode 100644
index 0000000..915f1ec
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubMessage.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+/*
+@hide
+*/
+parcelable ContextHubMessage;
+
diff --git a/core/java/android/hardware/location/ContextHubMessage.java b/core/java/android/hardware/location/ContextHubMessage.java
new file mode 100644
index 0000000..954e97d
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubMessage.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * @hide
+ */
+@SystemApi
+public class ContextHubMessage {
+    private int mType;
+    private int mVersion;
+    private byte[]mData;
+
+    /**
+     * Get the message type
+     *
+     * @return int - message type
+     */
+    public int getMsgType() {
+        return mType;
+    }
+
+    /**
+     * get message version
+     *
+     * @return int - message version
+     */
+    public int getVersion() {
+        return mVersion;
+    }
+
+    /**
+     * get message data
+     *
+     * @return byte[] - message data buffer
+     */
+    public byte[] getData() {
+        return Arrays.copyOf(mData, mData.length);
+    }
+
+    /**
+     * set message type
+     *
+     * @param msgType - message type
+     */
+    public void setMsgType(int msgType) {
+        mType = msgType;
+    }
+
+    /**
+     * Set message version
+     *
+     * @param version - message version
+     */
+    public void setVersion(int version) {
+        mVersion = version;
+    }
+
+    /**
+     * set message data
+     *
+     * @param data - message buffer
+     */
+    public void setMsgData(byte[] data) {
+        mData = Arrays.copyOf(data, data.length);
+    }
+
+    /**
+     * Constructor for a context hub message
+     *
+     * @param msgType - message type
+     * @param version - version
+     * @param data    - message buffer
+     */
+    public ContextHubMessage(int msgType, int version, byte[] data) {
+        mType = msgType;
+        mVersion = version;
+        mData = Arrays.copyOf(data, data.length);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    private ContextHubMessage(Parcel in) {
+        mType = in.readInt();
+        mVersion = in.readInt();
+        byte[] byteBuffer = new byte[in.readInt()];
+        in.readByteArray(byteBuffer);
+    }
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mType);
+        out.writeInt(mVersion);
+        out.writeInt(mData.length);
+        out.writeByteArray(mData);
+    }
+
+    public static final Parcelable.Creator<ContextHubMessage> CREATOR
+            = new Parcelable.Creator<ContextHubMessage>() {
+        public ContextHubMessage createFromParcel(Parcel in) {
+            return new ContextHubMessage(in);
+        }
+
+        public ContextHubMessage[] newArray(int size) {
+            return new ContextHubMessage[size];
+        }
+    };
+}
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
new file mode 100644
index 0000000..a2a13c6
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * @hide
+ */
+public class ContextHubService extends Service {
+
+    private static final String TAG = "ContextHubService";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private static ContextHubService sSingletonInstance;
+    private static final Object sSingletonInstanceLock = new Object();
+
+    private HashMap<Integer, ContextHubInfo> mHubHash;
+    private HashMap<Integer, NanoAppInstanceInfo> mNanoAppHash;
+    private ContextHubInfo[] mContexthubInfo;
+
+
+    private native int nativeSendMessage(int[] header, byte[] data);
+    private native ContextHubInfo[] nativeInitialize();
+
+    private int onMessageReceipt(int[] header, byte[] data) {
+        return 0;
+    }
+    private void initialize() {
+        mContexthubInfo = nativeInitialize();
+
+        mHubHash = new HashMap<Integer, ContextHubInfo>();
+
+        for (int i = 0; i < mContexthubInfo.length; i++) {
+            mHubHash.put(i + 1, mContexthubInfo[i]); // Avoiding zero
+        }
+    }
+
+    private ContextHubService(Context context) {
+        initialize();
+        Log.d(TAG, "Created from " + context.toString());
+    }
+
+    public static ContextHubService getInstance(Context context) {
+        synchronized (sSingletonInstanceLock) {
+            if (sSingletonInstance == null) {
+                sSingletonInstance = new ContextHubService(context);
+            }
+            return sSingletonInstance;
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    private final IContextHubService.Stub mBinder = new IContextHubService.Stub() {
+
+        private  IContextHubCallback callback;
+
+        @Override
+        public int registerCallBack(IContextHubCallback callback) throws RemoteException{
+            this.callback = callback;
+            return 0;
+        }
+
+        @Override
+        public int[] getContextHubHandles() throws RemoteException {
+            int [] returnArray = new int[mHubHash.size()];
+            int i = 0;
+            for (int key : mHubHash.keySet()) {
+                // Add any filtering here
+                returnArray[i] = key;
+                i++;
+            }
+            return returnArray;
+        }
+
+        @Override
+        public ContextHubInfo getContextHubInfo(int contexthubHandle) throws RemoteException {
+            return mHubHash.get(contexthubHandle);
+        }
+
+        @Override
+        public int loadNanoApp(int hubHandle, NanoApp app) throws RemoteException {
+            if (!mHubHash.containsKey(hubHandle)) {
+                return -1;
+            } else {
+                // Call Native interface here
+                int[] msgHeader = new int[8];
+                msgHeader[0] = ContextHubManager.MSG_LOAD_NANO_APP;
+                msgHeader[1] = app.getAppId();
+                msgHeader[2] = app.getAppVersion();
+                msgHeader[3] = 0; // LOADING_HINTS
+                msgHeader[4] = hubHandle;
+
+                int handle = nativeSendMessage(msgHeader, app.getAppBinary());
+
+                // if successful, add an entry to mNanoAppHash
+
+                if(handle > 0) {
+                    return 0;
+                } else {
+
+                    return -1;
+                }
+            }
+        }
+
+        @Override
+        public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+            if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
+                return -1;
+            } else {
+                NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
+                // Call Native interface here
+                int[] msgHeader = new int[8];
+                msgHeader[0] = ContextHubManager.MSG_UNLOAD_NANO_APP;
+                msgHeader[1] = info.getContexthubId();
+                msgHeader[2] = info.getHandle();
+
+                int result = nativeSendMessage(msgHeader, null);
+                // if successful, remove the entry in mNanoAppHash
+                if(result == 0) {
+                    mNanoAppHash.remove(nanoAppInstanceHandle);
+                }
+                return(result);
+            }
+        }
+
+        @Override
+        public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) throws RemoteException {
+            // This assumes that all the nanoAppInfo is current. This is reasonable
+            // for the use cases for tightly controlled nanoApps.
+            //
+            if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
+                return(mNanoAppHash.get(nanoAppInstanceHandle));
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
+            ArrayList<Integer> foundInstances = new ArrayList<Integer>();
+
+            for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
+                NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
+
+                if(filter.testMatch(info)){
+                    foundInstances.add(nanoAppInstance);
+                }
+            }
+
+            int[] retArray = new int[foundInstances.size()];
+            for (int i = 0; i < foundInstances.size(); i++) {
+                retArray[i] = foundInstances.get(i).intValue();
+            }
+
+            return retArray;
+        }
+
+        @Override
+        public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException {
+            int[] msgHeader = new int[8];
+            msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
+            msgHeader[1] = hubHandle;
+            msgHeader[2] = nanoAppHandle;
+            msgHeader[3] = msg.getMsgType();
+            msgHeader[4] = msg.getVersion();
+
+            return (nativeSendMessage(msgHeader, msg.getData()));
+        }
+    };
+}
diff --git a/core/java/android/hardware/location/IContextHubCallback.aidl b/core/java/android/hardware/location/IContextHubCallback.aidl
new file mode 100644
index 0000000..45b1ef4
--- /dev/null
+++ b/core/java/android/hardware/location/IContextHubCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+import android.hardware.location.ContextHubMessage;
+
+/** @hide */
+oneway interface IContextHubCallback {
+    void onMessageReceipt(int hubId, int nanoAppId, in ContextHubMessage msg);
+}
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
new file mode 100644
index 0000000..b2db0b2
--- /dev/null
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+// Declare any non-default types here with import statements
+import android.hardware.location.ContextHubMessage;
+import android.hardware.location.ContextHubInfo;
+import android.hardware.location.NanoApp;
+import android.hardware.location.NanoAppInstanceInfo;
+import android.hardware.location.NanoAppFilter;
+import android.hardware.location.IContextHubCallback;
+
+/** @hide */
+interface IContextHubService {
+
+    // register a callback to receive messages
+    int registerCallBack(in IContextHubCallback callback);
+
+    // Gets a list of available context hub handles
+    int[] getContextHubHandles();
+
+    // Get the properties of a hub
+    ContextHubInfo getContextHubInfo(int contextHubHandle);
+
+    // Load a nanoapp on a specified context hub
+    int loadNanoApp(int hubHandle, in NanoApp app);
+
+    // Unload a nanoapp instance
+    int unloadNanoApp(int nanoAppInstanceHandle);
+
+    // get information about a nanoAppInstance
+    NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle);
+
+    // find all nanoApp instances matching some filter
+    int[] findNanoAppOnHub(int hubHandle, in NanoAppFilter filter);
+
+    // send a message to a nanoApp
+    int sendMessage(int hubHandle, int nanoAppHandle, in ContextHubMessage msg);
+}
diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java
new file mode 100644
index 0000000..e8c7615
--- /dev/null
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+
+@SystemApi
+public class MemoryRegion implements Parcelable{
+
+    private int mSizeBytes;
+    private int mSizeBytesFree;
+    private boolean mIsReadable;
+    private boolean mIsWritable;
+    private boolean mIsExecutable;
+
+    /**
+     * get the capacity of the memory region in bytes
+     *
+     * @return int - the memory capacity in bytes
+     */
+    public int getCapacityBytes() {
+        return mSizeBytes;
+    }
+
+    /**
+     * get the free capacity of the memory region in bytes
+     *
+     * @return int - free bytes
+     */
+    public int getFreeCapacityBytes() {
+        return mSizeBytesFree;
+    }
+
+    /**
+     * Is the memory readable
+     *
+     * @return boolean - true if memory is readable, false otherwise
+     */
+    public boolean isReadable() {
+        return mIsReadable;
+    }
+
+    /**
+     * Is the memory writable
+     *
+     * @return boolean - true if memory is writable, false otherwise
+     */
+    public boolean isWritable() {
+        return mIsWritable;
+    }
+
+    /**
+     * Is the memory executable
+     *
+     * @return boolean - true if memory is executable, false
+     *         otherwise
+     */
+    public boolean isExecutable() {
+        return mIsExecutable;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSizeBytes);
+        dest.writeInt(mSizeBytesFree);
+        dest.writeInt(mIsReadable ? 1 : 0);
+        dest.writeInt(mIsWritable ? 1 : 0);
+        dest.writeInt(mIsExecutable ? 1 : 0);
+    }
+
+    public MemoryRegion(Parcel source) {
+        mSizeBytes = source.readInt();
+        mSizeBytesFree = source.readInt();
+        mIsReadable = source.readInt() != 0;
+        mIsWritable = source.readInt() != 0;
+        mIsExecutable = source.readInt() != 0;
+    }
+
+    public static final Parcelable.Creator<MemoryRegion> CREATOR
+            = new Parcelable.Creator<MemoryRegion>() {
+        public MemoryRegion createFromParcel(Parcel in) {
+            return new MemoryRegion(in);
+        }
+
+        public MemoryRegion[] newArray(int size) {
+            return new MemoryRegion[size];
+        }
+    };
+
+}
diff --git a/core/java/android/hardware/location/NanoApp.aidl b/core/java/android/hardware/location/NanoApp.aidl
new file mode 100644
index 0000000..d32c44a
--- /dev/null
+++ b/core/java/android/hardware/location/NanoApp.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+/*
+@hide
+*/
+parcelable NanoApp;
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
new file mode 100644
index 0000000..36d181f
--- /dev/null
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class describing nano apps.
+ * A nano app is a piece of executable code that can be
+ * downloaded onto a specific architecture. These are targtted
+ * for low power compute domains on a device.
+ *
+ * Nano apps are expected to be used only by bundled apps only
+ * at this time.
+ *
+ * @hide
+ */
+@SystemApi
+public class NanoApp {
+    private String mPublisher;
+    private String mName;
+
+    private int mAppId;
+    private int mAppVersion;
+
+    private int mNeededReadMemBytes;
+    private int mNeededWriteMemBytes;
+    private int mNeededExecMemBytes;
+
+    private int[] mNeededSensors;
+    private int[] mOutputEvents;
+    private byte[] mAppBinary;
+
+    public NanoApp() {
+    }
+
+    /**
+     * Set the publisher name
+     *
+     * @param publisher name of the publisher of this nano app
+     */
+    public void setPublisher(String publisher) {
+        mPublisher = publisher;
+    }
+
+    /**
+     * set the name of the app
+     *
+     * @param name   name of the app
+     */
+    public void setName(String name) {
+        mName = name;
+    }
+
+    /**
+     * set the app identifier
+     *
+     * @param appId  add identifier
+     */
+    public void setAppId(int appId) {
+        mAppId = appId;
+    }
+
+    /**
+     * Set the app version
+     *
+     * @param appVersion app version
+     */
+    public void setAppVersion(int appVersion) {
+        mAppVersion = appVersion;
+    }
+
+    /**
+     * set memory needed as read only
+     *
+     * @param neededReadMemBytes
+     *               read only memory needed in bytes
+     */
+    public void setNeededReadMemBytes(int neededReadMemBytes) {
+        mNeededReadMemBytes = neededReadMemBytes;
+    }
+
+    /**
+     * set writable memory needed in bytes
+     *
+     * @param neededWriteMemBytes
+     *               writable memory needed in bytes
+     */
+    public void setNeededWriteMemBytes(int neededWriteMemBytes) {
+        mNeededWriteMemBytes = neededWriteMemBytes;
+    }
+
+    /**
+     * set executable memory needed
+     *
+     * @param neededExecMemBytes
+     *               executable memory needed in bytes
+     */
+    public void setNeededExecMemBytes(int neededExecMemBytes) {
+        mNeededExecMemBytes = neededExecMemBytes;
+    }
+
+    /**
+     * set the sensors needed for this app
+     *
+     * @param neededSensors
+     *               needed Sensors
+     */
+    public void setNeededSensors(int[] neededSensors) {
+        mNeededSensors = neededSensors;
+    }
+
+    public void setOutputEvents(int[] outputEvents) {
+        mOutputEvents = outputEvents;
+    }
+
+    /**
+     * set output events returned by the nano app
+     *
+     * @param appBinary generated events
+     */
+    public void setAppBinary(byte[] appBinary) {
+        mAppBinary = appBinary;
+    }
+
+
+    /**
+     * get the publisher name
+     *
+     * @return publisher name
+     */
+    public String getPublisher() {
+      return mPublisher;
+    }
+
+    /**
+     * get the name of the app
+     *
+     * @return app name
+     */
+    public String getName() {
+    return mName;
+    }
+
+    /**
+     * get the identifier of the app
+     *
+     * @return identifier for this app
+     */
+    public int getAppId() {
+      return mAppId;
+    }
+
+    /**
+     * get the app version
+     *
+     * @return app version
+     */
+    public int getAppVersion() {
+      return mAppVersion;
+    }
+
+    /**
+     * get the ammount of readable memory needed by this app
+     *
+     * @return readable memory needed in bytes
+     */
+    public int getNeededReadMemBytes() {
+      return mNeededReadMemBytes;
+    }
+
+    /**
+     * get the ammount og writable memory needed in bytes
+     *
+     * @return writable memory needed in bytes
+     */
+    public int getNeededWriteMemBytes() {
+      return mNeededWriteMemBytes;
+    }
+
+    /**
+     * executable memory needed in bytes
+     *
+     * @return executable memory needed in bytes
+     */
+    public int getNeededExecMemBytes() {
+      return mNeededExecMemBytes;
+    }
+
+    /**
+     * get the sensors needed by this app
+     *
+     * @return sensors needed
+     */
+    public int[] getNeededSensors() {
+      return mNeededSensors;
+    }
+
+    /**
+     * get the events generated by this app
+     *
+     * @return generated events
+     */
+    public int[] getOutputEvents() {
+      return mOutputEvents;
+    }
+
+    /**
+     * get the binary for this app
+     *
+     * @return app binary
+     */
+    public byte[] getAppBinary() {
+      return mAppBinary;
+    }
+
+    private NanoApp(Parcel in) {
+        mPublisher = in.readString();
+        mName = in.readString();
+
+        mAppId = in.readInt();
+        mAppVersion = in.readInt();
+        mNeededReadMemBytes = in.readInt();
+        mNeededWriteMemBytes = in.readInt();
+        mNeededExecMemBytes = in.readInt();
+
+        int mNeededSensorsLength = in.readInt();
+        mNeededSensors = new int[mNeededSensorsLength];
+        in.readIntArray(mNeededSensors);
+
+        int mOutputEventsLength = in.readInt();
+        mOutputEvents = new int[mOutputEventsLength];
+        in.readIntArray(mOutputEvents);
+
+        int binaryLength = in.readInt();
+        mAppBinary = new byte[binaryLength];
+        in.readByteArray(mAppBinary);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mPublisher);
+        out.writeString(mName);
+        out.writeInt(mAppId);
+        out.writeInt(mAppVersion);
+        out.writeInt(mNeededReadMemBytes);
+        out.writeInt(mNeededWriteMemBytes);
+        out.writeInt(mNeededExecMemBytes);
+
+        out.writeInt(mNeededSensors.length);
+        out.writeIntArray(mNeededSensors);
+
+        out.writeInt(mOutputEvents.length);
+        out.writeIntArray(mOutputEvents);
+
+        out.writeInt(mAppBinary.length);
+        out.writeByteArray(mAppBinary);
+    }
+
+    public static final Parcelable.Creator<NanoApp> CREATOR
+            = new Parcelable.Creator<NanoApp>() {
+        public NanoApp createFromParcel(Parcel in) {
+            return new NanoApp(in);
+        }
+
+        public NanoApp[] newArray(int size) {
+            return new NanoApp[size];
+        }
+    };
+}
diff --git a/core/java/android/hardware/location/NanoAppFilter.aidl b/core/java/android/hardware/location/NanoAppFilter.aidl
new file mode 100644
index 0000000..cc6d475
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppFilter.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+/*
+@hide
+*/
+parcelable NanoAppFilter;
diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java
new file mode 100644
index 0000000..ac341e4
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppFilter.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+@SystemApi
+public class NanoAppFilter {
+
+    // The appId, can be set to APP_ID_ANY
+    private long mAppId;
+
+    // Version to filter apps
+    private int mAppVersion;
+
+    // filtering spec for version
+    private int mVersionRestrictionMask;
+
+    // If APP_ID is any, then a match is performef with the vendor mask
+    private long mAppIdVendorMask;
+
+    // Id of the context hub this instance is expected on
+    private int mContextHubId;
+
+    /**
+     * Flag indicating any version. With this flag set, all versions shall match provided version.
+     */
+    public static final int FLAGS_VERSION_ANY = -1;
+    /**
+     * If this flag is set, only versions strictly greater than the version specified shall match.
+     */
+    public static final int FLAGS_VERSION_GREAT_THAN  = 2;
+    /**
+     * If this flag is set, only versions strictly less than the version specified shall match.
+     */
+    public static final int FLAGS_VERSION_LESS_THAN   = 4;
+    public static final int FLAGS_VERSION_STRICTLY_EQUAL = 8;
+
+    /**
+     * If this flag is set, only versions strictly equal to the version specified shall match.
+     */
+    public static final int APP_ANY = -1;
+
+    /**
+     * If this flag is set, all vendors shall match.
+     */
+    public static final int VENDOR_ANY = -1;
+
+    /**
+     * If this flag is set, any hub shall match.
+     */
+    public static final int HUB_ANY = -1;
+
+    private NanoAppFilter(Parcel in) {
+        mAppId = in.readLong();
+        mAppVersion = in.readInt();
+        mVersionRestrictionMask = in.readInt();
+        mAppIdVendorMask = in.readInt();
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+
+        out.writeLong(mAppId);
+        out.writeInt(mAppVersion);
+        out.writeInt(mVersionRestrictionMask);
+        out.writeLong(mAppIdVendorMask);
+    }
+
+    /**
+     * Create a filter
+     *
+     * @param appId       application id
+     * @param appVersion  application version
+     * @param versionMask version
+     * @param vendorMask  vendor
+     */
+    public NanoAppFilter(long appId, int appVersion, int versionMask, long vendorMask) {
+        mAppId = appId;
+        mAppVersion = appVersion;
+        mVersionRestrictionMask = versionMask;
+        mAppIdVendorMask = vendorMask;
+    }
+
+    private boolean versionsMatch(int versionRestrictionMask, int expected, int actual){
+        // some refactoring of version restriction mask is needed, until then, return all
+        return true;
+    }
+    /**
+     *
+     * @param nano app instance info
+     *
+     * @return true if this is a match, false otherwise
+     */
+    public boolean testMatch(NanoAppInstanceInfo info) {
+        if ((mContextHubId == HUB_ANY || info.getContexthubId() == mContextHubId) &&
+                (mAppId == APP_ANY || info.getAppId() == mAppId) &&
+               // (mAppIdVendorMask == VENDOR_ANY) TODO : Expose Vendor mask cleanly
+                (versionsMatch(mVersionRestrictionMask, mAppVersion, info.getAppVersion()))) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static final Parcelable.Creator<NanoAppFilter> CREATOR
+            = new Parcelable.Creator<NanoAppFilter>() {
+        public NanoAppFilter createFromParcel(Parcel in) {
+            return new NanoAppFilter(in);
+        }
+
+        public NanoAppFilter[] newArray(int size) {
+            return new NanoAppFilter[size];
+        }
+    };
+}
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.aidl b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl
new file mode 100644
index 0000000..c8c40d7
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+/*
+@hide
+*/
+parcelable NanoAppInstanceInfo;
\ No newline at end of file
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
new file mode 100644
index 0000000..ac62919
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+@SystemApi
+public class NanoAppInstanceInfo {
+    private String mPublisher;
+    private String mName;
+
+    private int mAppId;
+    private int mAppVersion;
+
+    private int mNeededReadMemBytes;
+    private int mNeededWriteMemBytes;
+    private int mNeededExecMemBytes;
+
+    private int[] mNeededSensors;
+    private int[] mOutputEvents;
+
+    private int mContexthubId;
+    private int mHandle;
+
+    public NanoAppInstanceInfo() {
+    }
+
+    /**
+     * get the publisher of this app
+     *
+     * @return String - name of the publisher
+     */
+    public String getPublisher() {
+        return mPublisher;
+    }
+
+
+    /**
+     * set the publisher name for the app
+     *
+     * @param publisher - name of the publisher
+     */
+    public void setPublisher(String publisher) {
+        mPublisher = publisher;
+    }
+
+    /**
+     * get the name of the app
+     *
+     * @return String - name of the app
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * set the name of the app
+     *
+     * @param name - name of the app
+     */
+    public void setName(String name) {
+        mName = name;
+    }
+
+    /**
+     * Get the application identifier
+     *
+     * @return int - application identifier
+     */
+    public int getAppId() {
+        return mAppId;
+    }
+
+    /**
+     * Set the application identifier
+     *
+     * @param appId - application identifier
+     */
+    public void setAppId(int appId) {
+        mAppId = appId;
+    }
+
+    /**
+     * Set the application version
+     *
+     * @return int - version of the app
+     */
+    public int getAppVersion() {
+        return mAppVersion;
+    }
+
+    /**
+     * Set the application version
+     *
+     * @param appVersion - version of the app
+     */
+    public void setAppVersion(int appVersion) {
+        mAppVersion = appVersion;
+    }
+
+    /**
+     * Get the read memory needed by the app
+     *
+     * @return int - readable memory needed in bytes
+     */
+    public int getNeededReadMemBytes() {
+        return mNeededReadMemBytes;
+    }
+
+    /**
+     * Set the read memory needed by the app
+     *
+     * @param neededReadMemBytes - readable Memory needed in bytes
+     */
+    public void setNeededReadMemBytes(int neededReadMemBytes) {
+        mNeededReadMemBytes = neededReadMemBytes;
+    }
+
+    /**
+     *  get writable memory needed by the app
+     *
+     * @return int - writable memory needed by the app
+     */
+    public int getNeededWriteMemBytes() {
+        return mNeededWriteMemBytes;
+    }
+
+    /**
+     * set writable memory needed by the app
+     *
+     * @param neededWriteMemBytes - writable memory needed by the
+     *                            app
+     */
+    public void setNeededWriteMemBytes(int neededWriteMemBytes) {
+        mNeededWriteMemBytes = neededWriteMemBytes;
+    }
+
+    /**
+     * get executable memory needed by the app
+     *
+     * @return int - executable memory needed by the app
+     */
+    public int getNeededExecMemBytes() {
+        return mNeededExecMemBytes;
+    }
+
+    /**
+     * set executable memory needed by the app
+     *
+     * @param neededExecMemBytes - executable memory needed by the
+     *                           app
+     */
+    public void setNeededExecMemBytes(int neededExecMemBytes) {
+        mNeededExecMemBytes = neededExecMemBytes;
+    }
+
+    /**
+     * Get the sensors needed by this app
+     *
+     * @return int[] all the required sensors needed by this app
+     */
+    public int[] getNeededSensors() {
+        return mNeededSensors;
+    }
+
+    /**
+     * set the sensors needed by this app
+     *
+     * @param neededSensors - all the sensors needed by this app
+     */
+    public void setNeededSensors(int[] neededSensors) {
+        mNeededSensors = neededSensors;
+    }
+
+    /**
+     * get the events generated by this app
+     *
+     * @return all the events that can be generated by this app
+     */
+    public int[] getOutputEvents() {
+        return mOutputEvents;
+    }
+
+    /**
+     * set the output events that can be generated by this app
+     *
+     * @param outputEvents - the events that may be generated by
+     *                     this app
+     */
+    public void setOutputEvents(int[] outputEvents) {
+        mOutputEvents = outputEvents;
+    }
+
+    /**
+     * get the context hub identifier
+     *
+     * @return int - system unique hub identifier
+     */
+    public int getContexthubId() {
+        return mContexthubId;
+    }
+
+    /**
+     * set the context hub identifier
+     *
+     * @param contexthubId - system wide unique identifier
+     */
+    public void setContexthubId(int contexthubId) {
+        mContexthubId = contexthubId;
+    }
+
+    /**
+     * get a handle to the nano app instance
+     *
+     * @return int - handle to this instance
+     */
+    public int getHandle() {
+        return mHandle;
+    }
+
+    /**
+     * set the handle for an app instance
+     *
+     * @param handle - handle to this instance
+     */
+    public void setHandle(int handle) {
+        mHandle = handle;
+    }
+
+
+    private NanoAppInstanceInfo(Parcel in) {
+        mPublisher = in.readString();
+        mName = in.readString();
+
+        mAppId = in.readInt();
+        mAppVersion = in.readInt();
+        mNeededReadMemBytes = in.readInt();
+        mNeededWriteMemBytes = in.readInt();
+        mNeededExecMemBytes = in.readInt();
+
+        int mNeededSensorsLength = in.readInt();
+        mNeededSensors = new int[mNeededSensorsLength];
+        in.readIntArray(mNeededSensors);
+
+        int mOutputEventsLength = in.readInt();
+        mOutputEvents = new int[mOutputEventsLength];
+        in.readIntArray(mOutputEvents);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mPublisher);
+        out.writeString(mName);
+        out.writeInt(mAppId);
+        out.writeInt(mAppVersion);
+        out.writeInt(mContexthubId);
+        out.writeInt(mNeededReadMemBytes);
+        out.writeInt(mNeededWriteMemBytes);
+        out.writeInt(mNeededExecMemBytes);
+
+        out.writeInt(mNeededSensors.length);
+        out.writeIntArray(mNeededSensors);
+
+        out.writeInt(mOutputEvents.length);
+        out.writeIntArray(mOutputEvents);
+
+    }
+
+    public static final Parcelable.Creator<NanoAppInstanceInfo> CREATOR
+            = new Parcelable.Creator<NanoAppInstanceInfo>() {
+        public NanoAppInstanceInfo createFromParcel(Parcel in) {
+            return new NanoAppInstanceInfo(in);
+        }
+
+        public NanoAppInstanceInfo[] newArray(int size) {
+            return new NanoAppInstanceInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
index 2f6dbe7..597efa5 100644
--- a/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
+++ b/core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl
@@ -25,9 +25,12 @@
     /**
      * Called when the keyphrase is spoken.
      *
-     * @param data Optional trigger audio data, if it was requested and is available.
+     * @param recognitionEvent Object containing data relating to the
+     *                         recognition event such as trigger audio data, if it was requested
+     *                         and is available.
      */
-    void onDetected(in SoundTrigger.KeyphraseRecognitionEvent recognitionEvent);
+    void onDetected(in SoundTrigger.RecognitionEvent recognitionEvent);
+
     /**
      * Called when the detection fails due to an error.
      *
@@ -42,4 +45,4 @@
      * Called when the recognition is resumed after it was temporarily paused.
      */
     void onRecognitionResumed();
-}
\ No newline at end of file
+}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
index e16ea71..fec64ea 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
@@ -18,8 +18,11 @@
 
 parcelable SoundTrigger.ConfidenceLevel;
 parcelable SoundTrigger.Keyphrase;
+parcelable SoundTrigger.RecognitionEvent;
 parcelable SoundTrigger.KeyphraseRecognitionEvent;
+parcelable SoundTrigger.GenericSoundRecognitionEvent;
 parcelable SoundTrigger.KeyphraseRecognitionExtra;
 parcelable SoundTrigger.KeyphraseSoundModel;
+parcelable SoundTrigger.GenericSoundModel;
 parcelable SoundTrigger.ModuleProperties;
 parcelable SoundTrigger.RecognitionConfig;
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index d490409..882908a 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -195,6 +195,12 @@
         /** Keyphrase sound model */
         public static final int TYPE_KEYPHRASE = 0;
 
+        /**
+         * A generic sound model. Use this type only for non-keyphrase sound models such as
+         * ones that match a particular sound pattern.
+         */
+        public static final int TYPE_GENERIC_SOUND = 1;
+
         /** Unique sound model identifier */
         public final UUID uuid;
 
@@ -458,6 +464,63 @@
         }
     }
 
+
+    /*****************************************************************************
+     * A GenericSoundModel is a specialized {@link SoundModel} for non-voice sound
+     * patterns.
+     ****************************************************************************/
+    public static class GenericSoundModel extends SoundModel implements Parcelable {
+
+        public static final Parcelable.Creator<GenericSoundModel> CREATOR
+                = new Parcelable.Creator<GenericSoundModel>() {
+            public GenericSoundModel createFromParcel(Parcel in) {
+                return GenericSoundModel.fromParcel(in);
+            }
+
+            public GenericSoundModel[] newArray(int size) {
+                return new GenericSoundModel[size];
+            }
+        };
+
+        public GenericSoundModel(UUID uuid, UUID vendorUuid, byte[] data) {
+            super(uuid, vendorUuid, TYPE_GENERIC_SOUND, data);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        private static GenericSoundModel fromParcel(Parcel in) {
+            UUID uuid = UUID.fromString(in.readString());
+            UUID vendorUuid = null;
+            int length = in.readInt();
+            if (length >= 0) {
+                vendorUuid = UUID.fromString(in.readString());
+            }
+            byte[] data = in.readBlob();
+            return new GenericSoundModel(uuid, vendorUuid, data);
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeString(uuid.toString());
+            if (vendorUuid == null) {
+                dest.writeInt(-1);
+            } else {
+                dest.writeInt(vendorUuid.toString().length());
+                dest.writeString(vendorUuid.toString());
+            }
+            dest.writeBlob(data);
+        }
+
+        @Override
+        public String toString() {
+            return "GenericSoundModel [uuid=" + uuid + ", vendorUuid=" + vendorUuid
+                    + ", type=" + type + ", data=" + (data == null ? 0 : data.length) + "]";
+        }
+    }
+
     /**
      *  Modes for key phrase recognition
      */
@@ -1019,6 +1082,21 @@
     }
 
     /**
+     * Sub-class of RecognitionEvent specifically for sound-trigger based sound
+     * models(non-keyphrase). Currently does not contain any additional fields.
+     */
+    public static class GenericRecognitionEvent extends RecognitionEvent {
+        public GenericRecognitionEvent(int status, int soundModelHandle,
+                boolean captureAvailable, int captureSession, int captureDelayMs,
+                int capturePreambleMs, boolean triggerInData, AudioFormat captureFormat,
+                byte[] data) {
+            super(status, soundModelHandle, captureAvailable, captureSession,
+                    captureDelayMs, capturePreambleMs, triggerInData, captureFormat,
+                    data);
+        }
+    }
+
+    /**
      *  Status codes for {@link SoundModelEvent}
      */
     /** Sound Model was updated */
@@ -1118,7 +1196,7 @@
     public static final int SERVICE_STATE_DISABLED = 1;
 
     /**
-     * Returns a list of descriptors for all harware modules loaded.
+     * Returns a list of descriptors for all hardware modules loaded.
      * @param modules A ModuleProperties array where the list will be returned.
      * @return - {@link #STATUS_OK} in case of success
      *         - {@link #STATUS_ERROR} in case of unspecified error
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 92c721b..25b38c0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1189,7 +1189,7 @@
             return TYPE_NONE;
         }
 
-        // Do this only for SUPL, until GpsLocationProvider is fixed. http://b/25876485 .
+        // Do this only for SUPL, until GnssLocationProvider is fixed. http://b/25876485 .
         if (!netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
             // NOTE: if this causes app breakage, we should not just comment out this early return;
             // instead, we should make this early return conditional on the requesting app's target
@@ -3170,7 +3170,7 @@
 
     // Checks whether the calling app can use the legacy routing API (startUsingNetworkFeature,
     // stopUsingNetworkFeature, requestRouteToHost), and if not throw UnsupportedOperationException.
-    // TODO: convert the existing system users (Tethering, GpsLocationProvider) to the new APIs and
+    // TODO: convert the existing system users (Tethering, GnssLocationProvider) to the new APIs and
     // remove these exemptions. Note that this check is not secure, and apps can still access these
     // functions by accessing ConnectivityService directly. However, it should be clear that doing
     // so is unsupported and may break in the future. http://b/22728205
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 3bd12c0..e27c0fb 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -197,6 +197,19 @@
             (1 << NET_CAPABILITY_CAPTIVE_PORTAL);
 
     /**
+     * Network specifier for factories which want to match any network specifier
+     * (NS) in a request. Behavior:
+     * <li>Empty NS in request matches any network factory NS</li>
+     * <li>Empty NS in the network factory NS only matches a request with an
+     * empty NS</li>
+     * <li>"*" (this constant) NS in the network factory matches requests with
+     * any NS</li>
+     *
+     * @hide
+     */
+    public static final String MATCH_ALL_REQUESTS_NETWORK_SPECIFIER = "*";
+
+    /**
      * Network capabilities that are not allowed in NetworkRequests. This exists because the
      * NetworkFactory / NetworkAgent model does not deal well with the situation where a
      * capability's presence cannot be known in advance. If such a capability is requested, then we
@@ -596,7 +609,8 @@
     }
     private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
         return (TextUtils.isEmpty(mNetworkSpecifier) ||
-                mNetworkSpecifier.equals(nc.mNetworkSpecifier));
+                mNetworkSpecifier.equals(nc.mNetworkSpecifier) ||
+                MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(nc.mNetworkSpecifier));
     }
     private boolean equalsSpecifier(NetworkCapabilities nc) {
         if (TextUtils.isEmpty(mNetworkSpecifier)) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 7da4818..f1edcbe 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -188,6 +188,10 @@
          *                         networks.
          */
         public Builder setNetworkSpecifier(String networkSpecifier) {
+            if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(networkSpecifier)) {
+                throw new IllegalArgumentException("Invalid network specifier - must not be '"
+                        + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
+            }
             mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
             return this;
         }
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 4a8dfbc..53b027b 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -2343,7 +2343,7 @@
      */
     public void checkFileUriExposed(String location) {
         if ("file".equals(getScheme())) {
-            StrictMode.onFileUriExposed(location);
+            StrictMode.onFileUriExposed(this, location);
         }
     }
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9180506..52fa2ed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -201,9 +201,14 @@
     private static final String BATTERY_LEVEL_DATA = "lv";
     private static final String GLOBAL_WIFI_DATA = "gwfl";
     private static final String WIFI_DATA = "wfl";
-    private static final String GLOBAL_BLUETOOTH_DATA = "gble";
+    private static final String GLOBAL_WIFI_CONTROLLER_DATA = "gwfcd";
+    private static final String WIFI_CONTROLLER_DATA = "wfcd";
+    private static final String GLOBAL_BLUETOOTH_CONTROLLER_DATA = "gble";
+    private static final String BLUETOOTH_CONTROLLER_DATA = "ble";
     private static final String MISC_DATA = "m";
     private static final String GLOBAL_NETWORK_DATA = "gn";
+    private static final String GLOBAL_MODEM_CONTROLLER_DATA = "gmcd";
+    private static final String MODEM_CONTROLLER_DATA = "mcd";
     private static final String HISTORY_STRING_POOL = "hsp";
     private static final String HISTORY_DATA = "h";
     private static final String SCREEN_BRIGHTNESS_DATA = "br";
@@ -271,6 +276,39 @@
     }
 
     /**
+     * Container class that aggregates counters for transmit, receive, and idle state of a
+     * radio controller.
+     */
+    public static abstract class ControllerActivityCounter {
+        /**
+         * @return a non-null {@link LongCounter} representing time spent (milliseconds) in the
+         * idle state.
+         */
+        public abstract LongCounter getIdleTimeCounter();
+
+        /**
+         * @return a non-null {@link LongCounter} representing time spent (milliseconds) in the
+         * receive state.
+         */
+        public abstract LongCounter getRxTimeCounter();
+
+        /**
+         * An array of {@link LongCounter}, representing various transmit levels, where each level
+         * may draw a different amount of power. The levels themselves are controller-specific.
+         * @return non-null array of {@link LongCounter}s representing time spent (milliseconds) in
+         * various transmit level states.
+         */
+        public abstract LongCounter[] getTxTimeCounters();
+
+        /**
+         * @return a non-null {@link LongCounter} representing the power consumed by the controller
+         * in all states, measured in milli-ampere-milliseconds (mAms). The counter may always
+         * yield a value of 0 if the device doesn't support power calculations.
+         */
+        public abstract LongCounter getPowerCounter();
+    }
+
+    /**
      * State for keeping track of timing information.
      */
     public static abstract class Timer {
@@ -367,25 +405,9 @@
          */
         public abstract ArrayMap<String, ? extends Pkg> getPackageStats();
 
-        /**
-         * Returns the time in milliseconds that this app kept the WiFi controller in the
-         * specified state <code>type</code>.
-         * @param type one of {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, or
-         *             {@link #CONTROLLER_TX_TIME}.
-         * @param which one of {@link #STATS_CURRENT}, {@link #STATS_SINCE_CHARGED}, or
-         *              {@link #STATS_SINCE_UNPLUGGED}.
-         */
-        public abstract long getWifiControllerActivity(int type, int which);
-
-        /**
-         * Returns the time in milliseconds that this app kept the Bluetooth controller in the
-         * specified state <code>type</code>.
-         * @param type one of {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, or
-         *             {@link #CONTROLLER_TX_TIME}.
-         * @param which one of {@link #STATS_CURRENT}, {@link #STATS_SINCE_CHARGED}, or
-         *              {@link #STATS_SINCE_UNPLUGGED}.
-         */
-        public abstract long getBluetoothControllerActivity(int type, int which);
+        public abstract ControllerActivityCounter getWifiControllerActivity();
+        public abstract ControllerActivityCounter getBluetoothControllerActivity();
+        public abstract ControllerActivityCounter getModemControllerActivity();
 
         /**
          * {@hide}
@@ -2031,43 +2053,47 @@
     public abstract long getNetworkActivityBytes(int type, int which);
     public abstract long getNetworkActivityPackets(int type, int which);
 
-    public static final int CONTROLLER_IDLE_TIME = 0;
-    public static final int CONTROLLER_RX_TIME = 1;
-    public static final int CONTROLLER_TX_TIME = 2;
-    public static final int CONTROLLER_POWER_DRAIN = 3;
-    public static final int NUM_CONTROLLER_ACTIVITY_TYPES = CONTROLLER_POWER_DRAIN + 1;
-
-    /**
-     * Returns true if the BatteryStats object has detailed bluetooth power reports.
-     * When true, calling {@link #getBluetoothControllerActivity(int, int)} will yield the
-     * actual power data.
-     */
-    public abstract boolean hasBluetoothActivityReporting();
-
-    /**
-     * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
-     * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
-     * respective state.
-     * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
-     * milli-ampere-milliseconds (mAms).
-     */
-    public abstract long getBluetoothControllerActivity(int type, int which);
-
     /**
      * Returns true if the BatteryStats object has detailed WiFi power reports.
-     * When true, calling {@link #getWifiControllerActivity(int, int)} will yield the
+     * When true, calling {@link #getWifiControllerActivity()} will yield the
      * actual power data.
      */
     public abstract boolean hasWifiActivityReporting();
 
     /**
-     * For {@link #CONTROLLER_IDLE_TIME}, {@link #CONTROLLER_RX_TIME}, and
-     * {@link #CONTROLLER_TX_TIME}, returns the time spent (in milliseconds) in the
-     * respective state.
-     * For {@link #CONTROLLER_POWER_DRAIN}, returns the power used by the controller in
-     * milli-ampere-milliseconds (mAms).
+     * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent
+     * in various radio controller states, such as transmit, receive, and idle.
+     * @return non-null {@link ControllerActivityCounter}
      */
-    public abstract long getWifiControllerActivity(int type, int which);
+    public abstract ControllerActivityCounter getWifiControllerActivity();
+
+    /**
+     * Returns true if the BatteryStats object has detailed bluetooth power reports.
+     * When true, calling {@link #getBluetoothControllerActivity()} will yield the
+     * actual power data.
+     */
+    public abstract boolean hasBluetoothActivityReporting();
+
+    /**
+     * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent
+     * in various radio controller states, such as transmit, receive, and idle.
+     * @return non-null {@link ControllerActivityCounter}
+     */
+    public abstract ControllerActivityCounter getBluetoothControllerActivity();
+
+    /**
+     * Returns true if the BatteryStats object has detailed modem power reports.
+     * When true, calling {@link #getModemControllerActivity()} will yield the
+     * actual power data.
+     */
+    public abstract boolean hasModemActivityReporting();
+
+    /**
+     * Returns a {@link ControllerActivityCounter} which is an aggregate of the times spent
+     * in various radio controller states, such as transmit, receive, and idle.
+     * @return non-null {@link ControllerActivityCounter}
+     */
+    public abstract ControllerActivityCounter getModemControllerActivity();
 
     /**
      * Return the wall clock time when battery stats data collection started.
@@ -2496,6 +2522,17 @@
         return ",";
     }
     
+    private static final void dumpLineHeader(PrintWriter pw, int uid, String category,
+                                             String type) {
+        pw.print(BATTERY_STATS_CHECKIN_VERSION);
+        pw.print(',');
+        pw.print(uid);
+        pw.print(',');
+        pw.print(category);
+        pw.print(',');
+        pw.print(type);
+    }
+
     /**
      * Dump a comma-separated line of values for terse checkin mode.
      * 
@@ -2506,14 +2543,7 @@
      */
     private static final void dumpLine(PrintWriter pw, int uid, String category, String type, 
            Object... args ) {
-        pw.print(BATTERY_STATS_CHECKIN_VERSION);
-        pw.print(',');
-        pw.print(uid);
-        pw.print(',');
-        pw.print(category);
-        pw.print(',');
-        pw.print(type);
-
+        dumpLineHeader(pw, uid, category, type);
         for (Object arg : args) {
             pw.print(',');
             pw.print(arg);
@@ -2546,6 +2576,140 @@
     }
 
     /**
+     * Checks if the ControllerActivityCounter has any data worth dumping.
+     */
+    private static boolean controllerActivityHasData(ControllerActivityCounter counter, int which) {
+        if (counter == null) {
+            return false;
+        }
+
+        if (counter.getIdleTimeCounter().getCountLocked(which) != 0
+                || counter.getRxTimeCounter().getCountLocked(which) != 0
+                || counter.getPowerCounter().getCountLocked(which) != 0) {
+            return true;
+        }
+
+        for (LongCounter c : counter.getTxTimeCounters()) {
+            if (c.getCountLocked(which) != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Dumps the ControllerActivityCounter if it has any data worth dumping.
+     * The order of the arguments in the final check in line is:
+     *
+     * idle, rx, power, tx...
+     *
+     * where tx... is one or more transmit level times.
+     */
+    private static final void dumpControllerActivityLine(PrintWriter pw, int uid, String category,
+                                                         String type,
+                                                         ControllerActivityCounter counter,
+                                                         int which) {
+        if (!controllerActivityHasData(counter, which)) {
+            return;
+        }
+
+        dumpLineHeader(pw, uid, category, type);
+        pw.print(",");
+        pw.print(counter.getIdleTimeCounter().getCountLocked(which));
+        pw.print(",");
+        pw.print(counter.getRxTimeCounter().getCountLocked(which));
+        pw.print(",");
+        pw.print(counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60));
+        for (LongCounter c : counter.getTxTimeCounters()) {
+            pw.print(",");
+            pw.print(c.getCountLocked(which));
+        }
+        pw.println();
+    }
+
+    private final void printControllerActivityIfInteresting(PrintWriter pw, StringBuilder sb,
+                                                            String prefix, String controllerName,
+                                                            ControllerActivityCounter counter,
+                                                            int which) {
+        if (controllerActivityHasData(counter, which)) {
+            printControllerActivity(pw, sb, prefix, controllerName, counter, which);
+        }
+    }
+
+    private final void printControllerActivity(PrintWriter pw, StringBuilder sb, String prefix,
+                                               String controllerName,
+                                               ControllerActivityCounter counter, int which) {
+        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
+        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
+        final long powerDrainMaMs = counter.getPowerCounter().getCountLocked(which);
+        long totalTxTimeMs = 0;
+        for (LongCounter txState : counter.getTxTimeCounters()) {
+            totalTxTimeMs += txState.getCountLocked(which);
+        }
+
+        final long totalTimeMs = idleTimeMs + rxTimeMs + totalTxTimeMs;
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  ");
+        sb.append(controllerName);
+        sb.append(" Idle time:   ");
+        formatTimeMs(sb, idleTimeMs);
+        sb.append("(");
+        sb.append(formatRatioLocked(idleTimeMs, totalTimeMs));
+        sb.append(")");
+        pw.println(sb.toString());
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  ");
+        sb.append(controllerName);
+        sb.append(" Rx time:     ");
+        formatTimeMs(sb, rxTimeMs);
+        sb.append("(");
+        sb.append(formatRatioLocked(rxTimeMs, totalTimeMs));
+        sb.append(")");
+        pw.println(sb.toString());
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  ");
+        sb.append(controllerName);
+        sb.append(" Tx time:     ");
+        formatTimeMs(sb, totalTxTimeMs);
+        sb.append("(");
+        sb.append(formatRatioLocked(totalTxTimeMs, totalTimeMs));
+        sb.append(")");
+        pw.println(sb.toString());
+
+        final int numTxLvls = counter.getTxTimeCounters().length;
+        if (numTxLvls > 1) {
+            for (int lvl = 0; lvl < numTxLvls; lvl++) {
+                final long txLvlTimeMs = counter.getTxTimeCounters()[lvl].getCountLocked(which);
+                sb.setLength(0);
+                sb.append(prefix);
+                sb.append("    [");
+                sb.append(lvl);
+                sb.append("] ");
+                formatTimeMs(sb, txLvlTimeMs);
+                sb.append("(");
+                sb.append(formatRatioLocked(txLvlTimeMs, totalTxTimeMs));
+                sb.append(")");
+                pw.println(sb.toString());
+            }
+        }
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  ");
+        sb.append(controllerName);
+        sb.append(" Power drain: ").append(
+                BatteryStatsHelper.makemAh(powerDrainMaMs / (double) (1000*60*60)));
+        sb.append("mAh");
+        pw.println(sb.toString());
+    }
+
+    /**
      * Temporary for settings.
      */
     public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
@@ -2637,24 +2801,22 @@
                 mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
                 mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
 
+        // Dump Modem controller stats
+        dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_MODEM_CONTROLLER_DATA,
+                getModemControllerActivity(), which);
+
         // Dump Wifi controller stats
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
-        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
-        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
-        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
-        final long wifiPowerMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
-        dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA,
-                wifiOnTime / 1000, wifiRunningTime / 1000,
-                wifiIdleTimeMs, wifiRxTimeMs, wifiTxTimeMs, wifiPowerMaMs / (1000*60*60));
+        dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA, wifiOnTime / 1000,
+                wifiRunningTime / 1000, /* legacy fields follow, keep at 0 */ 0, 0, 0, 0);
+
+        dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_WIFI_CONTROLLER_DATA,
+                getWifiControllerActivity(), which);
 
         // Dump Bluetooth controller stats
-        final long btIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
-        final long btRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
-        final long btTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
-        final long btPowerMaMs = getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which);
-        dumpLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_DATA,
-                btIdleTimeMs, btRxTimeMs, btTxTimeMs, btPowerMaMs / (1000*60*60));
+        dumpControllerActivityLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_CONTROLLER_DATA,
+                getBluetoothControllerActivity(), which);
 
         // Dump misc stats
         dumpLine(pw, 0 /* uid */, category, MISC_DATA,
@@ -2865,21 +3027,25 @@
                         mobileActiveTime, mobileActiveCount);
             }
 
+            // Dump modem controller data, per UID.
+            dumpControllerActivityLine(pw, uid, category, MODEM_CONTROLLER_DATA,
+                    u.getModemControllerActivity(), which);
+
+            // Dump Wifi controller data, per UID.
             final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
             final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
             final int wifiScanCount = u.getWifiScanCount(which);
             final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
-            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
-            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
-            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
             if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
-                    || uidWifiRunningTime != 0 || uidWifiIdleTimeMs != 0 || uidWifiRxTimeMs != 0
-                    || uidWifiTxTimeMs != 0) {
-                dumpLine(pw, uid, category, WIFI_DATA,
-                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount,
-                        uidWifiIdleTimeMs, uidWifiRxTimeMs, uidWifiTxTimeMs);
+                    || uidWifiRunningTime != 0) {
+                dumpLine(pw, uid, category, WIFI_DATA, fullWifiLockOnTime, wifiScanTime,
+                        uidWifiRunningTime, wifiScanCount,
+                        /* legacy fields follow, keep at 0 */ 0, 0, 0, 0);
             }
 
+            dumpControllerActivityLine(pw, uid, category, WIFI_CONTROLLER_DATA,
+                    u.getWifiControllerActivity(), which);
+
             if (u.hasUserActivity()) {
                 args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
                 boolean hasData = false;
@@ -3409,6 +3575,8 @@
             pw.println(sb.toString());
         }
 
+        printControllerActivity(pw, sb, prefix, "Radio", getModemControllerActivity(), which);
+
         pw.print(prefix);
                 pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
                 pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
@@ -3494,85 +3662,14 @@
         if (!didOne) sb.append(" (no activity)");
         pw.println(sb.toString());
 
-        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
-        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
-        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
-        final long wifiPowerDrainMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
-        final long wifiTotalTimeMs = wifiIdleTimeMs + wifiRxTimeMs + wifiTxTimeMs;
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  WiFi Idle time: "); formatTimeMs(sb, wifiIdleTimeMs);
-        sb.append("(");
-        sb.append(formatRatioLocked(wifiIdleTimeMs, wifiTotalTimeMs));
-        sb.append(")");
-        pw.println(sb.toString());
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  WiFi Rx time:   "); formatTimeMs(sb, wifiRxTimeMs);
-        sb.append("(");
-        sb.append(formatRatioLocked(wifiRxTimeMs, wifiTotalTimeMs));
-        sb.append(")");
-        pw.println(sb.toString());
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  WiFi Tx time:   "); formatTimeMs(sb, wifiTxTimeMs);
-        sb.append("(");
-        sb.append(formatRatioLocked(wifiTxTimeMs, wifiTotalTimeMs));
-        sb.append(")");
-        pw.println(sb.toString());
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  WiFi Power drain: ").append(
-                BatteryStatsHelper.makemAh(wifiPowerDrainMaMs / (double) (1000*60*60)));
-        sb.append("mAh");
-        pw.println(sb.toString());
+        printControllerActivity(pw, sb, prefix, "WiFi", getWifiControllerActivity(), which);
 
         pw.print(prefix);
         pw.print("  Bluetooth total received: "); pw.print(formatBytesLocked(btRxTotalBytes));
         pw.print(", sent: "); pw.println(formatBytesLocked(btTxTotalBytes));
 
-        final long bluetoothIdleTimeMs =
-                getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
-        final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
-        final long bluetoothTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
-        final long bluetoothTotalTimeMs = bluetoothIdleTimeMs + bluetoothRxTimeMs +
-                bluetoothTxTimeMs;
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  Bluetooth Idle time: "); formatTimeMs(sb, bluetoothIdleTimeMs);
-        sb.append("(");
-        sb.append(formatRatioLocked(bluetoothIdleTimeMs, bluetoothTotalTimeMs));
-        sb.append(")");
-        pw.println(sb.toString());
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  Bluetooth Rx time:   "); formatTimeMs(sb, bluetoothRxTimeMs);
-        sb.append("(");
-        sb.append(formatRatioLocked(bluetoothRxTimeMs, bluetoothTotalTimeMs));
-        sb.append(")");
-        pw.println(sb.toString());
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  Bluetooth Tx time:   "); formatTimeMs(sb, bluetoothTxTimeMs);
-        sb.append("(");
-        sb.append(formatRatioLocked(bluetoothTxTimeMs, bluetoothTotalTimeMs));
-        sb.append(")");
-        pw.println(sb.toString());
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh(
-                getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) /
-                        (double)(1000*60*60)));
-        sb.append("mAh");
-        pw.println(sb.toString());
+        printControllerActivity(pw, sb, prefix, "Bluetooth", getBluetoothControllerActivity(),
+                which);
 
         pw.println();
 
@@ -3897,6 +3994,9 @@
                 pw.println(sb.toString());
             }
 
+            printControllerActivityIfInteresting(pw, sb, prefix + "  ", "Modem",
+                    u.getModemControllerActivity(), which);
+
             if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
                 pw.print(prefix); pw.print("    Wi-Fi network: ");
                         pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
@@ -3925,26 +4025,8 @@
                 pw.println(sb.toString());
             }
 
-            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
-            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
-            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
-            final long uidWifiTotalTimeMs = uidWifiIdleTimeMs + uidWifiRxTimeMs + uidWifiTxTimeMs;
-            if (uidWifiTotalTimeMs > 0) {
-                sb.setLength(0);
-                sb.append(prefix).append("    WiFi Idle time: ");
-                formatTimeMs(sb, uidWifiIdleTimeMs);
-                sb.append("(").append(formatRatioLocked(uidWifiIdleTimeMs, uidWifiTotalTimeMs))
-                        .append(")\n");
-
-                sb.append(prefix).append("    WiFi Rx time:   "); formatTimeMs(sb, uidWifiRxTimeMs);
-                sb.append("(").append(formatRatioLocked(uidWifiRxTimeMs, uidWifiTotalTimeMs))
-                        .append(")\n");
-
-                sb.append(prefix).append("    WiFi Tx time:   "); formatTimeMs(sb, uidWifiTxTimeMs);
-                sb.append("(").append(formatRatioLocked(uidWifiTxTimeMs, uidWifiTotalTimeMs))
-                        .append(")");
-                pw.println(sb.toString());
-            }
+            printControllerActivityIfInteresting(pw, sb, prefix + "  ", "WiFi",
+                    u.getWifiControllerActivity(), which);
 
             if (btRxBytes > 0 || btTxBytes > 0) {
                 pw.print(prefix); pw.print("    Bluetooth network: ");
@@ -3953,30 +4035,6 @@
                 pw.println(" sent");
             }
 
-            final long uidBtIdleTimeMs = u.getBluetoothControllerActivity(CONTROLLER_IDLE_TIME,
-                    which);
-            final long uidBtRxTimeMs = u.getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
-            final long uidBtTxTimeMs = u.getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
-            final long uidBtTotalTimeMs = uidBtIdleTimeMs + uidBtRxTimeMs + uidBtTxTimeMs;
-            if (uidBtTotalTimeMs > 0) {
-                sb.setLength(0);
-                sb.append(prefix).append("    Bluetooth Idle time: ");
-                formatTimeMs(sb, uidBtIdleTimeMs);
-                sb.append("(").append(formatRatioLocked(uidBtIdleTimeMs, uidBtTotalTimeMs))
-                        .append(")\n");
-
-                sb.append(prefix).append("    Bluetooth Rx time:   ");
-                formatTimeMs(sb, uidBtRxTimeMs);
-                sb.append("(").append(formatRatioLocked(uidBtRxTimeMs, uidBtTotalTimeMs))
-                        .append(")\n");
-
-                sb.append(prefix).append("    Bluetooth Tx time:   ");
-                formatTimeMs(sb, uidBtTxTimeMs);
-                sb.append("(").append(formatRatioLocked(uidBtTxTimeMs, uidBtTotalTimeMs))
-                        .append(")");
-                pw.println(sb.toString());
-            }
-
             if (u.hasUserActivity()) {
                 boolean hasData = false;
                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
diff --git a/core/java/android/os/CpuUsageInfo.java b/core/java/android/os/CpuUsageInfo.java
new file mode 100644
index 0000000..54caa15
--- /dev/null
+++ b/core/java/android/os/CpuUsageInfo.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * CPU usage information per core.
+ */
+public final class CpuUsageInfo implements Parcelable {
+    private long mActive;
+    private long mTotal;
+
+    public static final Parcelable.Creator<CpuUsageInfo> CREATOR = new
+            Parcelable.Creator<CpuUsageInfo>() {
+                    public CpuUsageInfo createFromParcel(Parcel in) {
+                        return new CpuUsageInfo(in);
+                    }
+
+                    public CpuUsageInfo[] newArray(int size) {
+                        return new CpuUsageInfo[size];
+                    }
+                };
+
+    /** @hide */
+    public CpuUsageInfo(long activeTime, long totalTime) {
+        mActive = activeTime;
+        mTotal = totalTime;
+    }
+
+    private CpuUsageInfo(Parcel in) {
+        readFromParcel(in);
+    }
+
+    /**
+     * Gets the active time in milliseconds since the system last booted.
+     *
+     * @return Active time in milliseconds.
+     */
+    public long getActive() {
+        return mActive;
+    }
+
+    /**
+     * Gets the total time in milliseconds that the CPU has been enabled since the system last
+     * booted. This includes time the CPU spent idle.
+     *
+     * @return Total time in milliseconds.
+     */
+    public long getTotal() {
+        return mTotal;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeLong(mActive);
+        out.writeLong(mTotal);
+    }
+
+    private void readFromParcel(Parcel in) {
+        mActive = in.readLong();
+        mTotal = in.readLong();
+    }
+}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index ba215bb..c776ef8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -402,7 +402,7 @@
      * type.
      */
     public static String DIRECTORY_PODCASTS = "Podcasts";
-    
+
     /**
      * Standard directory in which to place any audio files that should be
      * in the list of ringtones that the user can select (not as regular
@@ -414,7 +414,7 @@
      * type.
      */
     public static String DIRECTORY_RINGTONES = "Ringtones";
-    
+
     /**
      * Standard directory in which to place any audio files that should be
      * in the list of alarms that the user can select (not as regular
@@ -426,7 +426,7 @@
      * type.
      */
     public static String DIRECTORY_ALARMS = "Alarms";
-    
+
     /**
      * Standard directory in which to place any audio files that should be
      * in the list of notifications that the user can select (not as regular
@@ -438,7 +438,7 @@
      * type.
      */
     public static String DIRECTORY_NOTIFICATIONS = "Notifications";
-    
+
     /**
      * Standard directory in which to place pictures that are available to
      * the user.  Note that this is primarily a convention for the top-level
@@ -446,7 +446,7 @@
      * in any directory.
      */
     public static String DIRECTORY_PICTURES = "Pictures";
-    
+
     /**
      * Standard directory in which to place movies that are available to
      * the user.  Note that this is primarily a convention for the top-level
@@ -454,7 +454,7 @@
      * in any directory.
      */
     public static String DIRECTORY_MOVIES = "Movies";
-    
+
     /**
      * Standard directory in which to place files that have been downloaded by
      * the user.  Note that this is primarily a convention for the top-level
@@ -464,7 +464,7 @@
      * backwards compatibility reasons.
      */
     public static String DIRECTORY_DOWNLOADS = "Download";
-    
+
     /**
      * The traditional location for pictures and videos when mounting the
      * device as a camera.  Note that this is primarily a convention for the
@@ -496,7 +496,7 @@
      * </ul>
      * @hide
      */
-    public static final String[] STANDARD_DIRECTORIES = {
+    private static final String[] STANDARD_DIRECTORIES = {
             DIRECTORY_MUSIC,
             DIRECTORY_PODCASTS,
             DIRECTORY_RINGTONES,
@@ -510,6 +510,18 @@
     };
 
     /**
+     * @hide
+     */
+    public static boolean isStandardDirectory(String dir) {
+        for (String valid : STANDARD_DIRECTORIES) {
+            if (valid.equals(dir)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Get a top-level shared/external storage directory for placing files of a
      * particular type. This is where the user will typically place and manage
      * their own files, so you should be careful about what you put here to
@@ -559,7 +571,7 @@
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppDataDirs(packageName);
     }
-    
+
     /**
      * Generates the raw path to an application's media
      * @hide
@@ -568,7 +580,7 @@
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppMediaDirs(packageName);
     }
-    
+
     /**
      * Generates the raw path to an application's OBB files
      * @hide
@@ -577,7 +589,7 @@
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppObbDirs(packageName);
     }
-    
+
     /**
      * Generates the path to an application's files.
      * @hide
@@ -595,7 +607,7 @@
         throwIfUserRequired();
         return sCurrentUser.buildExternalStorageAppCacheDirs(packageName);
     }
-    
+
     /**
      * Return the download/cache content directory.
      */
diff --git a/core/java/android/os/FileUriExposedException.java b/core/java/android/os/FileUriExposedException.java
new file mode 100644
index 0000000..e47abe2
--- /dev/null
+++ b/core/java/android/os/FileUriExposedException.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.content.Intent;
+
+/**
+ * The exception that is thrown when an application exposes a {@code file://}
+ * {@link android.net.Uri} to another app.
+ * <p>
+ * This exposure is discouraged since the receiving app may not have access to
+ * the shared path. For example, the receiving app may not have requested the
+ * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime permission,
+ * or the platform may be sharing the {@link android.net.Uri} across user
+ * profile boundaries.
+ * <p>
+ * Instead, apps should use {@code content://} Uris so the platform can extend
+ * temporary permission for the receiving app to access the resource.
+ * <p>
+ * This is only thrown for applications targeting {@link Build.VERSION_CODES#N}
+ * or higher. Applications targeting earlier SDK versions are allowed to share
+ * {@code file://} {@link android.net.Uri}, but it's strongly discouraged.
+ *
+ * @see android.support.v4.content.FileProvider
+ * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
+ */
+public class FileUriExposedException extends RuntimeException {
+    public FileUriExposedException(String message) {
+        super(message);
+    }
+}
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
new file mode 100644
index 0000000..bc317b6
--- /dev/null
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a
+ * device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc.
+ */
+public class HardwarePropertiesManager {
+
+    private static final String TAG = HardwarePropertiesManager.class.getSimpleName();
+
+    private static native void nativeInit();
+
+    private static native float[] nativeGetFanSpeeds();
+    private static native float[] nativeGetDeviceTemperatures(int type);
+    private static native CpuUsageInfo[] nativeGetCpuUsages();
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        DEVICE_TEMPERATURE_CPU, DEVICE_TEMPERATURE_GPU, DEVICE_TEMPERATURE_BATTERY
+    })
+    public @interface DeviceTemperatureType {}
+
+    /**
+     * Device temperature types. These must match the values in
+     * frameworks/native/include/hardwareproperties/HardwarePropertiesManager.h
+     */
+    /** Temperature of CPUs in Celsius. */
+    public static final int DEVICE_TEMPERATURE_CPU = 0;
+
+    /** Temperature of GPUs in Celsius. */
+    public static final int DEVICE_TEMPERATURE_GPU = 1;
+
+    /** Temperature of battery in Celsius. */
+    public static final int DEVICE_TEMPERATURE_BATTERY = 2;
+
+    /** @hide */
+    public HardwarePropertiesManager() {
+        nativeInit();
+    }
+
+    /**
+     * Return an array of device temperatures in Celsius.
+     *
+     * @param type type of requested device temperature, one of {@link #DEVICE_TEMPERATURE_CPU},
+     * {@link #DEVICE_TEMPERATURE_GPU} or {@link #DEVICE_TEMPERATURE_BATTERY}.
+     * @return an array of requested float device temperatures.
+     *         Empty if platform doesn't provide the queried temperature.
+     *
+     * @throws IllegalArgumentException if an incorrect temperature type is queried.
+    */
+    public @NonNull float[] getDeviceTemperatures(@DeviceTemperatureType int type) {
+        switch (type) {
+        case DEVICE_TEMPERATURE_CPU:
+        case DEVICE_TEMPERATURE_GPU:
+        case DEVICE_TEMPERATURE_BATTERY:
+            return nativeGetDeviceTemperatures(type);
+        default:
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /**
+     * Return an array of CPU usage info for each core.
+     *
+     * @return an array of {@link android.os.CpuUsageInfo} for each core.
+     *         Empty if CPU usage is not supported on this system.
+     */
+    public @NonNull CpuUsageInfo[] getCpuUsages() {
+        return nativeGetCpuUsages();
+    }
+
+    /**
+     * Return an array of fan speeds in RPM.
+     *
+     * @return an arrat of float fan speeds. Empty if there is no fans or fan speed
+     *         not supported on this system.
+     */
+    public @NonNull float[] getFanSpeeds() {
+        return nativeGetFanSpeeds();
+    }
+}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 4159d89..314b7d5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -219,6 +219,15 @@
     public static final int DRAW_WAKE_LOCK = 0x00000080;
 
     /**
+     * Wake lock level: Enables Sustained Performance Mode.
+     * <p>
+     * This is used by Gaming and VR applications to ensure the device provides
+     * will provide consistent performance over a large amount of time.
+     * </p>
+     */
+    public static final int SUSTAINED_PERFORMANCE_WAKE_LOCK = 0x00000100;
+
+    /**
      * Mask for the wake lock level component of a combined wake lock level and flags integer.
      *
      * @hide
@@ -525,6 +534,7 @@
             case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
             case DOZE_WAKE_LOCK:
             case DRAW_WAKE_LOCK:
+            case SUSTAINED_PERFORMANCE_WAKE_LOCK:
                 break;
             default:
                 throw new IllegalArgumentException("Must specify a valid wake lock level.");
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index eca2c3b..1552a3c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -150,6 +150,12 @@
     public static final int AUDIOSERVER_UID = 1041;
 
     /**
+     * Defines the UID/GID for the cameraserver process
+     * @hide
+     */
+    public static final int CAMERASERVER_UID = 1046;
+
+    /**
      * Defines the start of a range of UIDs (and GIDs), going from this
      * number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
      * to applications.
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f1672df..91d88da 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.net.Uri;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Printer;
@@ -46,7 +47,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -243,42 +243,15 @@
 
     // Byte 3: Penalty
 
-    /**
-     * @hide
-     */
+    /** {@hide} */
     public static final int PENALTY_LOG = 0x01 << 16;  // normal android.util.Log
-
-    // Used for both process and thread policy:
-
-    /**
-     * @hide
-     */
+    /** {@hide} */
     public static final int PENALTY_DIALOG = 0x02 << 16;
-
-    /**
-     * Death on any detected violation.
-     *
-     * @hide
-     */
+    /** {@hide} */
     public static final int PENALTY_DEATH = 0x04 << 16;
-
-    /**
-     * Death just for detected network usage.
-     *
-     * @hide
-     */
-    public static final int PENALTY_DEATH_ON_NETWORK = 0x08 << 16;
-
-    /**
-     * Flash the screen during violations.
-     *
-     * @hide
-     */
+    /** {@hide} */
     public static final int PENALTY_FLASH = 0x10 << 16;
-
-    /**
-     * @hide
-     */
+    /** {@hide} */
     public static final int PENALTY_DROPBOX = 0x20 << 16;
 
     /**
@@ -294,12 +267,28 @@
      */
     public static final int PENALTY_GATHER = 0x40 << 16;
 
+    // Byte 4: Special cases
+
+    /**
+     * Death when network traffic is detected on main thread.
+     *
+     * @hide
+     */
+    public static final int PENALTY_DEATH_ON_NETWORK = 0x01 << 24;
+
     /**
      * Death when cleartext network traffic is detected.
      *
      * @hide
      */
-    public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x80 << 16;
+    public static final int PENALTY_DEATH_ON_CLEARTEXT_NETWORK = 0x02 << 24;
+
+    /**
+     * Death when file exposure is detected.
+     *
+     * @hide
+     */
+    public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
 
     /**
      * Mask of all the penalty bits valid for thread policies.
@@ -312,7 +301,7 @@
      * Mask of all the penalty bits valid for VM policies.
      */
     private static final int VM_PENALTY_MASK = PENALTY_LOG | PENALTY_DEATH | PENALTY_DROPBOX
-            | PENALTY_DEATH_ON_CLEARTEXT_NETWORK;
+            | PENALTY_DEATH_ON_CLEARTEXT_NETWORK | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
 
     /** {@hide} */
     public static final int NETWORK_POLICY_ACCEPT = 0;
@@ -748,10 +737,22 @@
             }
 
             /**
-             * Detect when a {@code file://} {@link android.net.Uri} is exposed beyond this
-             * app. The receiving app may not have access to the sent path.
-             * Instead, when sharing files between apps, {@code content://}
-             * should be used with permission grants.
+             * Detect when this application exposes a {@code file://}
+             * {@link android.net.Uri} to another app.
+             * <p>
+             * This exposure is discouraged since the receiving app may not have
+             * access to the shared path. For example, the receiving app may not
+             * have requested the
+             * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} runtime
+             * permission, or the platform may be sharing the
+             * {@link android.net.Uri} across user profile boundaries.
+             * <p>
+             * Instead, apps should use {@code content://} Uris so the platform
+             * can extend temporary permission for the receiving app to access
+             * the resource.
+             *
+             * @see android.support.v4.content.FileProvider
+             * @see Intent#FLAG_GRANT_READ_URI_PERMISSION
              */
             public Builder detectFileUriExposure() {
                 return enable(DETECT_VM_FILE_URI_EXPOSURE);
@@ -798,6 +799,16 @@
             }
 
             /**
+             * Crashes the whole process when a {@code file://}
+             * {@link android.net.Uri} is exposed beyond this app.
+             *
+             * @see #detectFileUriExposure()
+             */
+            public Builder penaltyDeathOnFileUriExposure() {
+                return enable(PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
+            }
+
+            /**
              * Log detected violations to the system log.
              */
             public Builder penaltyLog() {
@@ -1111,6 +1122,25 @@
     }
 
     /**
+     * Used by the framework to make file usage a fatal error.
+     *
+     * @hide
+     */
+    public static void enableDeathOnFileUriExposure() {
+        sVmPolicyMask |= DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
+    }
+
+    /**
+     * Used by lame internal apps that haven't done the hard work to get
+     * themselves off file:// Uris yet.
+     *
+     * @hide
+     */
+    public static void disableDeathOnFileUriExposure() {
+        sVmPolicyMask &= ~(DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
+    }
+
+    /**
      * Parses the BlockGuard policy mask out from the Exception's
      * getMessage() String value.  Kinda gross, but least
      * invasive.  :/
@@ -1755,9 +1785,13 @@
     /**
      * @hide
      */
-    public static void onFileUriExposed(String location) {
-        final String message = "file:// Uri exposed through " + location;
-        onVmPolicyViolation(null, new Throwable(message));
+    public static void onFileUriExposed(Uri uri, String location) {
+        final String message = uri + " exposed beyond app through " + location;
+        if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
+            throw new FileUriExposedException(message);
+        } else {
+            onVmPolicyViolation(null, new Throwable(message));
+        }
     }
 
     /**
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index bcc1213..344d06e 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -144,6 +144,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public static UserHandle of(@UserIdInt int userId) {
         return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId);
     }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index fe834a1..1ac798b 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
@@ -621,6 +622,20 @@
     /** @hide */
     public static final int PIN_VERIFICATION_SUCCESS = -1;
 
+    /**
+     * Error result indicating that this user is not allowed to add other users on this device.
+     * This is a result code returned from the activity created by the intent
+     * {@link #createUserCreationIntent(String, String, String, PersistableBundle)}.
+     */
+    public static final int USER_CREATION_FAILED_NOT_PERMITTED = Activity.RESULT_FIRST_USER;
+
+    /**
+     * Error result indicating that no more users can be created on this device.
+     * This is a result code returned from the activity created by the intent
+     * {@link #createUserCreationIntent(String, String, String, PersistableBundle)}.
+     */
+    public static final int USER_CREATION_FAILED_NO_MORE_USERS = Activity.RESULT_FIRST_USER + 1;
+
     /** @hide */
     public static UserManager get(Context context) {
         return (UserManager) context.getSystemService(Context.USER_SERVICE);
@@ -1194,7 +1209,10 @@
      * If this device does not support multiple users, null is returned.
      * <p/>
      * The intent should be launched using startActivityForResult and the return result will
-     * indicate if the user consented to adding a new user and if the operation succeeded.
+     * indicate if the user consented to adding a new user and if the operation succeeded. Any
+     * errors in creating the user will be returned in the result code. If the user cancels the
+     * request, the return result will be {@link Activity#RESULT_CANCELED}. On success, the
+     * result code will be {@link Activity#RESULT_OK}.
      * <p/>
      * The new user is created but not initialized. After switching into the user for the first
      * time, the preferred user name and account information are used by the setup process for that
@@ -1211,6 +1229,8 @@
      *                       Handler)}.
      * @return An Intent that can be launched from an Activity or null if creating users is not
      *         supported on this device.
+     * @see #USER_CREATION_FAILED_NOT_PERMITTED
+     * @see #USER_CREATION_FAILED_NO_MORE_USERS
      */
     public static Intent createUserCreationIntent(@Nullable String userName,
             @Nullable String accountName,
@@ -1362,7 +1382,7 @@
     /**
      * Returns information for all users on this device.
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
-     * @return the list of users that were created.
+     * @return the list of users that exist on the device.
      * @hide
      */
     public List<UserInfo> getUsers() {
@@ -1375,6 +1395,29 @@
     }
 
     /**
+     * Returns serial numbers of all users on this device.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     *
+     * @param excludeDying specify if the list should exclude users being removed.
+     * @return the list of serial numbers of users that exist on the device.
+     * @hide
+     */
+    @SystemApi
+    public long[] getSerialNumbersOfUsers(boolean excludeDying) {
+        try {
+            List<UserInfo> users = mService.getUsers(excludeDying);
+            long[] result = new long[users.size()];
+            for (int i = 0; i < result.length; i++) {
+                result[i] = users.get(i).serialNumber;
+            }
+            return result;
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get users list", re);
+            return null;
+        }
+    }
+
+    /**
      * @return the user's account name, null if not found.
      * @hide
      */
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index f765336..58a0269 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -91,4 +91,19 @@
      * the icon is in this method.
      */
     public abstract void setUserIcon(int userId, Bitmap bitmap);
+
+    /**
+     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to inform the
+     * user manager whether all users should be created ephemeral.
+     */
+    public abstract void setForceEphemeralUsers(boolean forceEphemeralUsers);
+
+    /**
+     * Switches to the system user and deletes all other users.
+     *
+     * <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
+     * the force-ephemeral-users policy is toggled on to make sure there are no pre-existing
+     * non-ephemeral users left.
+     */
+    public abstract void removeAllUsers();
 }
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index fda6326..ebb12fd 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -16,6 +16,7 @@
 
 package android.preference;
 
+import android.annotation.SystemApi;
 import android.annotation.XmlRes;
 import android.app.Activity;
 import android.content.Context;
@@ -24,8 +25,8 @@
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.res.XmlResourceParser;
 import android.os.Bundle;
 import android.util.Log;
@@ -110,7 +111,13 @@
      * managed by this instance.
      */
     private int mSharedPreferencesMode;
-    
+
+    private static final int STORAGE_DEFAULT = 0;
+    private static final int STORAGE_DEVICE_ENCRYPTED = 1;
+    private static final int STORAGE_CREDENTIAL_ENCRYPTED = 2;
+
+    private int mStorage = STORAGE_DEFAULT;
+
     /**
      * The {@link PreferenceScreen} at the root of the preference hierarchy.
      */
@@ -343,6 +350,46 @@
     }
 
     /**
+     * Sets the storage location used internally by this class to be the default
+     * provided by the hosting {@link Context}.
+     */
+    public void setStorageDefault() {
+        mStorage = STORAGE_DEFAULT;
+        mSharedPreferences = null;
+    }
+
+    /**
+     * Explicitly set the storage location used internally by this class to be
+     * device-encrypted storage.
+     * <p>
+     * Data stored in device-encrypted storage is typically encrypted with a key
+     * tied to the physical device, and it can be accessed when the device has
+     * booted successfully, both <em>before and after</em> the user has
+     * authenticated with their credentials (such as a lock pattern or PIN).
+     * Because device-encrypted data is available before user authentication,
+     * you should carefully consider what data you store using this mode.
+     *
+     * @see Context#createDeviceEncryptedStorageContext()
+     */
+    public void setStorageDeviceEncrypted() {
+        mStorage = STORAGE_DEVICE_ENCRYPTED;
+        mSharedPreferences = null;
+    }
+
+    /**
+     * Explicitly set the storage location used internally by this class to be
+     * credential-encrypted storage.
+     *
+     * @see Context#createCredentialEncryptedStorageContext()
+     * @hide
+     */
+    @SystemApi
+    public void setStorageCredentialEncrypted() {
+        mStorage = STORAGE_CREDENTIAL_ENCRYPTED;
+        mSharedPreferences = null;
+    }
+
+    /**
      * Gets a SharedPreferences instance that preferences managed by this will
      * use.
      * 
@@ -351,7 +398,20 @@
      */
     public SharedPreferences getSharedPreferences() {
         if (mSharedPreferences == null) {
-            mSharedPreferences = mContext.getSharedPreferences(mSharedPreferencesName,
+            final Context storageContext;
+            switch (mStorage) {
+                case STORAGE_DEVICE_ENCRYPTED:
+                    storageContext = mContext.createDeviceEncryptedStorageContext();
+                    break;
+                case STORAGE_CREDENTIAL_ENCRYPTED:
+                    storageContext = mContext.createCredentialEncryptedStorageContext();
+                    break;
+                default:
+                    storageContext = mContext;
+                    break;
+            }
+
+            mSharedPreferences = storageContext.getSharedPreferences(mSharedPreferencesName,
                     mSharedPreferencesMode);
         }
         
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index cdd88f6..032d83d 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -234,6 +234,9 @@
          * @see #FLAG_DIR_PREFERS_LAST_MODIFIED
          * @see #FLAG_VIRTUAL_DOCUMENT
          * @see #FLAG_ARCHIVE
+         * @see #FLAG_SUPPORTS_COPY
+         * @see #FLAG_SUPPORTS_MOVE
+         * @see #FLAG_SUPPORTS_REMOVE
          */
         public static final String COLUMN_FLAGS = "flags";
 
@@ -371,6 +374,15 @@
         public static final int FLAG_ARCHIVE = 1 << 10;
 
         /**
+         * Flag indicating that a document can be removed from a parent.
+         *
+         * @see #COLUMN_FLAGS
+         * @see DocumentsContract#removeDocument(ContentProviderClient, Uri, Uri)
+         * @see DocumentsProvider#removeDocument(String, String)
+         */
+        public static final int FLAG_SUPPORTS_REMOVE = 1 << 11;
+
+        /**
          * Flag indicating that document titles should be hidden when viewing
          * this directory in a larger format grid. For example, a directory
          * containing only images may want the image thumbnails to speak for
@@ -612,6 +624,8 @@
     public static final String METHOD_MOVE_DOCUMENT = "android:moveDocument";
     /** {@hide} */
     public static final String METHOD_IS_CHILD_DOCUMENT = "android:isChildDocument";
+    /** {@hide} */
+    public static final String METHOD_REMOVE_DOCUMENT = "android:removeDocument";
 
     /** {@hide} */
     public static final String EXTRA_PARENT_URI = "parentUri";
@@ -835,7 +849,12 @@
         return uri != null && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme());
     }
 
-    /** {@hide} */
+    /**
+     * Test if the given URI represents a {@link Document} tree.
+     *
+     * @see #buildTreeDocumentUri(String, String)
+     * @see #getTreeDocumentId(Uri, String)
+     */
     public static boolean isTreeUri(Uri uri) {
         final List<String> paths = uri.getPathSegments();
         return (paths.size() >= 2 && PATH_TREE.equals(paths.get(0)));
@@ -1204,6 +1223,41 @@
     }
 
     /**
+     * Removes the given document from a parent directory.
+     *
+     * <p>In contrast to {@link #deleteDocument} it requires specifying the parent.
+     * This method is especially useful if the document can be in multiple parents.
+     *
+     * @param documentUri document with {@link Document#FLAG_SUPPORTS_REMOVE}
+     * @param parentDocumentUri parent document of the document to remove.
+     * @return true if the document was removed successfully.
+     */
+    public static boolean removeDocument(ContentResolver resolver, Uri documentUri,
+            Uri parentDocumentUri) {
+        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
+                documentUri.getAuthority());
+        try {
+            removeDocument(client, documentUri, parentDocumentUri);
+            return true;
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to remove document", e);
+            return false;
+        } finally {
+            ContentProviderClient.releaseQuietly(client);
+        }
+    }
+
+    /** {@hide} */
+    public static void removeDocument(ContentProviderClient client, Uri documentUri,
+            Uri parentDocumentUri) throws RemoteException {
+        final Bundle in = new Bundle();
+        in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
+        in.putParcelable(DocumentsContract.EXTRA_PARENT_URI, parentDocumentUri);
+
+        client.call(METHOD_REMOVE_DOCUMENT, null, in);
+    }
+
+    /**
      * Open the given image for thumbnail purposes, using any embedded EXIF
      * thumbnail if available, and providing orientation hints from the parent
      * image.
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index bae928d..7a82cd1e 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -21,6 +21,7 @@
 import static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_IS_CHILD_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_MOVE_DOCUMENT;
+import static android.provider.DocumentsContract.METHOD_REMOVE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_RENAME_DOCUMENT;
 import static android.provider.DocumentsContract.buildDocumentUri;
 import static android.provider.DocumentsContract.buildDocumentUriMaybeUsingTree;
@@ -300,6 +301,25 @@
             throws FileNotFoundException {
         throw new UnsupportedOperationException("Move not supported");
     }
+
+    /**
+     * Removes the requested document or a document tree.
+     *
+     * <p>In contrast to {@link #deleteDocument} it requires specifying the parent.
+     * This method is especially useful if the document can be in multiple parents.
+     *
+     * <p>It's the responsibility of the provider to revoke grants if the document is
+     * removed from the last parent, and effectively the document is deleted.
+     *
+     * @param documentId the document to remove.
+     * @param parentDocumentId the parent of the document to move.
+     */
+    @SuppressWarnings("unused")
+    public boolean removeDocument(String documentId, String parentDocumentId)
+            throws FileNotFoundException {
+        throw new UnsupportedOperationException("Remove not supported");
+    }
+
     /**
      * Return all roots currently provided. To display to users, you must define
      * at least one root. You should avoid making network requests to keep this
@@ -822,6 +842,17 @@
             // Original document no longer exists, clean up any grants.
             revokeDocumentPermission(documentId);
 
+        } else if (METHOD_REMOVE_DOCUMENT.equals(method)) {
+            final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
+            final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
+
+            enforceReadPermissionInner(parentSourceUri, getCallingPackage(), null);
+            enforceWritePermissionInner(documentUri, getCallingPackage(), null);
+            removeDocument(documentId, parentSourceId);
+
+            // It's responsibility of the provider to revoke any grants, as the document may be
+            // still attached to another parents.
+
         } else {
             throw new UnsupportedOperationException("Method not supported " + method);
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a9fd3c8..c9c0cde 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -501,6 +501,23 @@
             "android.settings.USER_DICTIONARY_SETTINGS";
 
     /**
+     * Activity Action: Show settings to configure the hardware keyboard layout.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     *
+     * @see android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_KEYBOARD_LAYOUT_SETTINGS =
+            "android.settings.KEYBOARD_LAYOUT_SETTINGS";
+
+    /**
      * Activity Action: Adds a word to the user dictionary.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -5073,6 +5090,14 @@
         public static final String TTS_DEFAULT_SYNTH = "tts_default_synth";
 
         /**
+         * Whether text-to-speech higher speech rate is enabled.
+         * 0 = disabled.
+         * 1 = enabled.
+         * @hide
+         */
+        public static final String TTS_DEFAULT_HIGHER_SPEECH_RATE_ENABLED =
+            "tts_default_higher_speech_rate_enabled";
+        /**
          * Default text-to-speech language.
          *
          * @deprecated this setting is no longer in use, as of the Ice Cream
@@ -5884,6 +5909,7 @@
             ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
             TTS_USE_DEFAULTS,
             TTS_DEFAULT_RATE,
+            TTS_DEFAULT_HIGHER_SPEECH_RATE_ENABLED,
             TTS_DEFAULT_PITCH,
             TTS_DEFAULT_SYNTH,
             TTS_DEFAULT_LANG,
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 24683cb..8ee9d1e 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -101,6 +101,12 @@
     public static final String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
 
     /**
+     * Broadcast intent to request all voicemail sources to perform a sync with the remote server.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SYNC_VOICEMAIL = "android.intent.action.SYNC_VOICEMAIL";
+
+    /**
      * Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
      * receiving package made this change.
      */
@@ -393,6 +399,14 @@
          * <P>Type: INTEGER</P>
          */
         public static final String CONFIGURATION_STATE = "configuration_state";
+        /**
+         * Value of {@link #CONFIGURATION_STATE} passed into
+         * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the
+         * {@link #CONFIGURATION_STATE} field is not to be changed
+         *
+         * @hide
+         */
+        public static final int CONFIGURATION_STATE_IGNORE = -1;
         /** Value of {@link #CONFIGURATION_STATE} to indicate an all OK configuration status. */
         public static final int CONFIGURATION_STATE_OK = 0;
         /**
@@ -418,15 +432,50 @@
          */
         public static final String DATA_CHANNEL_STATE = "data_channel_state";
         /**
+         * Value of {@link #DATA_CHANNEL_STATE} passed into
+         * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the
+         * {@link #DATA_CHANNEL_STATE} field is not to be changed
+         *
+         * @hide
+         */
+        public static final int DATA_CHANNEL_STATE_IGNORE = -1;
+        /**
          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel is working fine.
          */
         public static final int DATA_CHANNEL_STATE_OK = 0;
         /**
-         * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel connection is not
-         * working.
+         *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel failed to find a
+         *  suitable network to connect to the server.
          */
         public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1;
         /**
+         *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel failed to find a
+         *  suitable network to connect to the server, and the carrier requires using cellular
+         *  data network to connect to the server.
+         */
+        public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2;
+        /**
+         *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel received incorrect
+         *  settings or credentials to connect to the server
+         */
+        public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3;
+        /**
+         *  Value of {@link #DATA_CHANNEL_STATE} to indicate that a error has occurred in the data
+         *  channel while communicating with the server
+         */
+        public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4;
+        /**
+         *  Value of {@link #DATA_CHANNEL_STATE} to indicate that the server reported an internal
+         *  error to the data channel.
+         */
+        public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5;
+        /**
+         *  Value of {@link #DATA_CHANNEL_STATE} to indicate that while there is a suitable network,
+         *  the data channel is unable to establish a connection with the server.
+         */
+        public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6;
+
+        /**
          * The notification channel state of the voicemail source. This is the channel through which
          * the source gets notified of new voicemails on the remote server.
          * <P> Possible values:
@@ -438,6 +487,14 @@
          */
         public static final String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
         /**
+         * Value of {@link #NOTIFICATION_CHANNEL_STATE} passed into
+         * {@link #setStatus(Context, PhoneAccountHandle, int, int, int)} to indicate that the
+         * {@link #NOTIFICATION_CHANNEL_STATE} field is not to be changed
+         *
+         * @hide
+         */
+        public static final int NOTIFICATION_CHANNEL_STATE_IGNORE = -1;
+        /**
          * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel is
          * working fine.
          */
@@ -497,21 +554,22 @@
          */
         public static void setStatus(Context context, PhoneAccountHandle accountHandle,
                 int configurationState, int dataChannelState, int notificationChannelState) {
-            ContentResolver contentResolver = context.getContentResolver();
-            Uri statusUri = buildSourceUri(context.getPackageName());
             ContentValues values = new ContentValues();
             values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME,
                     accountHandle.getComponentName().flattenToString());
             values.put(Status.PHONE_ACCOUNT_ID, accountHandle.getId());
-            values.put(Status.CONFIGURATION_STATE, configurationState);
-            values.put(Status.DATA_CHANNEL_STATE, dataChannelState);
-            values.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState);
-
-            if (isStatusPresent(contentResolver, statusUri)) {
-                contentResolver.update(statusUri, values, null, null);
-            } else {
-                contentResolver.insert(statusUri, values);
+            if(configurationState != CONFIGURATION_STATE_IGNORE) {
+                values.put(Status.CONFIGURATION_STATE, configurationState);
             }
+            if(dataChannelState != DATA_CHANNEL_STATE_IGNORE) {
+                values.put(Status.DATA_CHANNEL_STATE, dataChannelState);
+            }
+            if(notificationChannelState != NOTIFICATION_CHANNEL_STATE_IGNORE) {
+                values.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState);
+            }
+            ContentResolver contentResolver = context.getContentResolver();
+            Uri statusUri = buildSourceUri(context.getPackageName());
+            contentResolver.insert(statusUri, values);
         }
 
         /**
@@ -540,28 +598,7 @@
 
             ContentResolver contentResolver = context.getContentResolver();
             Uri statusUri = buildSourceUri(context.getPackageName());
-            if (isStatusPresent(contentResolver, statusUri)) {
-                contentResolver.update(statusUri, values, null, null);
-            } else {
-                contentResolver.insert(statusUri, values);
-            }
-        }
-
-        /**
-         * Determines if a voicemail source exists in the status table.
-         *
-         * @param contentResolver A content resolver constructed from the appropriate context.
-         * @param statusUri The content uri for the source.
-         * @return {@code true} if a status entry for this source exists
-         */
-        private static boolean isStatusPresent(ContentResolver contentResolver, Uri statusUri) {
-            Cursor cursor = null;
-            try {
-                cursor = contentResolver.query(statusUri, null, null, null, null);
-                return cursor != null && cursor.getCount() != 0;
-            } finally {
-                if (cursor != null) cursor.close();
-            }
+            contentResolver.insert(statusUri, values);
         }
     }
 }
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 035462d..bd41fb5 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -98,6 +98,9 @@
     /** Notification was canceled by the user banning the topic. */
     public static final int REASON_TOPIC_BANNED = 14;
 
+    /** Notification was canceled by the device administrator suspending the package. */
+    public static final int REASON_PACKAGE_SUSPENDED = 15;
+
     public class Adjustment {
         int mImportance;
         CharSequence mExplanation;
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index ac7d539..76a401d 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -31,6 +31,7 @@
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
 import android.media.AudioFormat;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -616,7 +617,11 @@
         }
 
         @Override
-        public void onDetected(KeyphraseRecognitionEvent event) {
+        public void onDetected(RecognitionEvent event) {
+            if (! (event instanceof KeyphraseRecognitionEvent)) {
+                Slog.e(TAG, "onDetected() called for a soundtrigger event.");
+                return;
+            }
             if (DBG) {
                 Slog.d(TAG, "onDetected(" + event + ")");
             } else {
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 0c6a0c6..6ff9fe7 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1170,7 +1170,7 @@
         }
         try {
             intent.migrateExtraStreamToClipData();
-            intent.prepareToLeaveProcess();
+            intent.prepareToLeaveProcess(mContext);
             int res = mSystemService.startVoiceActivity(mToken, intent,
                     intent.resolveType(mContext.getContentResolver()));
             Instrumentation.checkStartActivityResult(res, intent);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index cd19607..a985517 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -271,7 +271,7 @@
             @Override
             public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
                     Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
-                    Configuration newConfig, Rect backDropRect) {
+                    Configuration newConfig, Rect backDropRect, boolean forceLayout) {
                 Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED,
                         reportDraw ? 1 : 0, outsets);
                 mCaller.sendMessage(msg);
diff --git a/core/java/android/test/AndroidTestCase.java b/core/java/android/test/AndroidTestCase.java
index 2ecbfae..1e6bd9c 100644
--- a/core/java/android/test/AndroidTestCase.java
+++ b/core/java/android/test/AndroidTestCase.java
@@ -29,7 +29,13 @@
 
 /**
  * Extend this if you need to access Resources or other things that depend on Activity Context.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class AndroidTestCase extends TestCase {
 
     protected Context mContext;
diff --git a/core/java/android/test/FlakyTest.java b/core/java/android/test/FlakyTest.java
index 919767f..4e5c4e3 100644
--- a/core/java/android/test/FlakyTest.java
+++ b/core/java/android/test/FlakyTest.java
@@ -26,7 +26,13 @@
  * test methods. When the annotation is present, the test method is re-executed if
  * the test fails. The total number of executions is specified by the tolerance and
  * defaults to 1.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/FlakyTest.html">
+ * FlakyTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface FlakyTest {
diff --git a/core/java/android/test/InstrumentationTestCase.java b/core/java/android/test/InstrumentationTestCase.java
index ca427ea..6b79314 100644
--- a/core/java/android/test/InstrumentationTestCase.java
+++ b/core/java/android/test/InstrumentationTestCase.java
@@ -32,7 +32,13 @@
 
 /**
  * A test case that has access to {@link Instrumentation}.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class InstrumentationTestCase extends TestCase {
 
     private Instrumentation mInstrumentation;
@@ -40,7 +46,7 @@
     /**
      * Injects instrumentation into this test case. This method is
      * called by the test runner during test setup.
-     * 
+     *
      * @param instrumentation the instrumentation to use with this instance
      */
     public void injectInstrumentation(Instrumentation instrumentation) {
diff --git a/core/java/android/test/InstrumentationTestSuite.java b/core/java/android/test/InstrumentationTestSuite.java
index 7a78ffb..a53fa26 100644
--- a/core/java/android/test/InstrumentationTestSuite.java
+++ b/core/java/android/test/InstrumentationTestSuite.java
@@ -25,7 +25,13 @@
 /**
  * A {@link junit.framework.TestSuite} that injects {@link android.app.Instrumentation} into
  * {@link InstrumentationTestCase} before running them.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class InstrumentationTestSuite extends TestSuite {
 
     private final Instrumentation mInstrumentation;
diff --git a/core/java/android/test/PerformanceTestCase.java b/core/java/android/test/PerformanceTestCase.java
index 679ad40..65bd4a4 100644
--- a/core/java/android/test/PerformanceTestCase.java
+++ b/core/java/android/test/PerformanceTestCase.java
@@ -18,10 +18,11 @@
 
 /**
  * More complex interface performance for test cases.
- * 
+ *
  * If you want your test to be used as a performance test, you must
  * implement this interface.
  */
+@Deprecated
 public interface PerformanceTestCase
 {
     /**
@@ -37,27 +38,27 @@
     }
 
     /**
-     * Set up to begin performance tests.  The 'intermediates' is a
+     * Set up to begin performance tests. The 'intermediates' is a
      * communication channel to send back intermediate performance numbers --
      * if you use it, you will probably want to ensure your test is only
      * executed once by returning 1.  Otherwise, return 0 to allow the test
      * harness to decide the number of iterations.
-     * 
+     *
      * <p>If you return a non-zero iteration count, you should call
      * {@link Intermediates#startTiming intermediates.startTiming} and
      * {@link Intermediates#finishTiming intermediates.endTiming} to report the
      * duration of the test whose performance should actually be measured.
-     * 
+     *
      * @param intermediates Callback for sending intermediate results.
-     * 
+     *
      * @return int Maximum number of iterations to run, or 0 to let the caller
-     *         decide.
+     * decide.
      */
     int startPerformance(Intermediates intermediates);
-    
+
     /**
      * This method is used to determine what modes this test case can run in.
-     * 
+     *
      * @return true if this test case can only be run in performance mode.
      */
     boolean isPerformanceOnly();
diff --git a/core/java/android/test/UiThreadTest.java b/core/java/android/test/UiThreadTest.java
index cd92231..cd06ab8 100644
--- a/core/java/android/test/UiThreadTest.java
+++ b/core/java/android/test/UiThreadTest.java
@@ -26,7 +26,13 @@
  * When the annotation is present, the test method is executed on the application's
  * main thread (or UI thread.) Note that instrumentation methods may not be used
  * when this annotation is present.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/annotation/UiThreadTest.html">
+ * UiThreadTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface UiThreadTest {
diff --git a/core/java/android/test/suitebuilder/annotation/LargeTest.java b/core/java/android/test/suitebuilder/annotation/LargeTest.java
index a6269e7..dc77ee6 100644
--- a/core/java/android/test/suitebuilder/annotation/LargeTest.java
+++ b/core/java/android/test/suitebuilder/annotation/LargeTest.java
@@ -23,7 +23,13 @@
 
 /**
  * Marks a test that should run as part of the large tests.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/LargeTest.html">
+ * LargeTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.TYPE})
 public @interface LargeTest {
diff --git a/core/java/android/test/suitebuilder/annotation/MediumTest.java b/core/java/android/test/suitebuilder/annotation/MediumTest.java
index 8afeb91..b941da0 100644
--- a/core/java/android/test/suitebuilder/annotation/MediumTest.java
+++ b/core/java/android/test/suitebuilder/annotation/MediumTest.java
@@ -24,7 +24,12 @@
 /**
  * Marks a test that should run as part of the medium tests.
  *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/MediumTest.html">
+ * MediumTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.TYPE})
 public @interface MediumTest {
diff --git a/core/java/android/test/suitebuilder/annotation/SmallTest.java b/core/java/android/test/suitebuilder/annotation/SmallTest.java
index ad530e2..d3c74f0 100644
--- a/core/java/android/test/suitebuilder/annotation/SmallTest.java
+++ b/core/java/android/test/suitebuilder/annotation/SmallTest.java
@@ -23,7 +23,13 @@
 
 /**
  * Marks a test that should run as part of the small tests.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/SmallTest.html">
+ * SmallTest</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.TYPE})
 public @interface SmallTest {
diff --git a/core/java/android/test/suitebuilder/annotation/Smoke.java b/core/java/android/test/suitebuilder/annotation/Smoke.java
index 237e033..aac2937 100644
--- a/core/java/android/test/suitebuilder/annotation/Smoke.java
+++ b/core/java/android/test/suitebuilder/annotation/Smoke.java
@@ -27,7 +27,11 @@
  * will run all tests with this annotation.
  *
  * @see android.test.suitebuilder.SmokeTestSuiteBuilder
+ *
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.TYPE})
 public @interface Smoke {
diff --git a/core/java/android/test/suitebuilder/annotation/Suppress.java b/core/java/android/test/suitebuilder/annotation/Suppress.java
index f16c8fa..629a3cf 100644
--- a/core/java/android/test/suitebuilder/annotation/Suppress.java
+++ b/core/java/android/test/suitebuilder/annotation/Suppress.java
@@ -26,7 +26,12 @@
  * suite. If the annotation appears on the class then no tests in that class will be included. If
  * the annotation appears only on a test method then only that method will be excluded.
  *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/filters/Suppress.html">
+ * Suppress</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.TYPE})
 public @interface Suppress {
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 7e73b0c..ed91239c 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -26,6 +26,8 @@
 import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
 
+import android.app.ActivityThread;
+import android.app.Application;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Color;
@@ -33,6 +35,7 @@
 import android.graphics.drawable.Drawable;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.AlignmentSpan;
+import android.text.style.BackgroundColorSpan;
 import android.text.style.BulletSpan;
 import android.text.style.CharacterStyle;
 import android.text.style.ForegroundColorSpan;
@@ -162,6 +165,11 @@
             | FROM_HTML_SEPARATOR_LINE_BREAK_DIV
             | FROM_HTML_SEPARATOR_LINE_BREAK_BLOCKQUOTE;
 
+    /**
+     * The bit which indicates if lines delimited by '\n' will be grouped into &lt;p&gt; elements.
+     */
+    private static final int TO_HTML_PARAGRAPH_FLAG = 0x00000001;
+
     private Html() { }
 
     /**
@@ -252,7 +260,7 @@
      */
     public static String toHtml(Spanned text, int option) {
         StringBuilder out = new StringBuilder();
-        withinHtml(out, text);
+        withinHtml(out, text, option);
         return out.toString();
     }
 
@@ -265,11 +273,20 @@
         return out.toString();
     }
 
-    private static void withinHtml(StringBuilder out, Spanned text) {
+    private static void withinHtml(StringBuilder out, Spanned text, int option) {
+        if ((option & TO_HTML_PARAGRAPH_FLAG) == TO_HTML_PARAGRAPH_LINES_CONSECUTIVE) {
+            encodeTextAlignmentByDiv(out, text, option);
+            return;
+        }
+
+        withinDiv(out, text, 0, text.length(), option);
+    }
+
+    private static void encodeTextAlignmentByDiv(StringBuilder out, Spanned text, int option) {
         int len = text.length();
 
         int next;
-        for (int i = 0; i < text.length(); i = next) {
+        for (int i = 0; i < len; i = next) {
             next = text.nextSpanTransition(i, len, ParagraphStyle.class);
             ParagraphStyle[] style = text.getSpans(i, next, ParagraphStyle.class);
             String elements = " ";
@@ -293,7 +310,7 @@
                 out.append("<div ").append(elements).append(">");
             }
 
-            withinDiv(out, text, i, next);
+            withinDiv(out, text, i, next, option);
 
             if (needDiv) {
                 out.append("</div>");
@@ -301,8 +318,8 @@
         }
     }
 
-    private static void withinDiv(StringBuilder out, Spanned text,
-            int start, int end) {
+    private static void withinDiv(StringBuilder out, Spanned text, int start, int end,
+            int option) {
         int next;
         for (int i = start; i < end; i = next) {
             next = text.nextSpanTransition(i, end, QuoteSpan.class);
@@ -312,7 +329,7 @@
                 out.append("<blockquote>");
             }
 
-            withinBlockquote(out, text, i, next);
+            withinBlockquote(out, text, i, next, option);
 
             for (QuoteSpan quote : quotes) {
                 out.append("</blockquote>\n");
@@ -320,7 +337,7 @@
         }
     }
 
-    private static String getOpenParaTagWithDirection(Spanned text, int start, int end) {
+    private static String getTextDirection(Spanned text, int start, int end) {
         final int len = end - start;
         final byte[] levels = ArrayUtils.newUnpaddedByteArray(len);
         final char[] buffer = TextUtils.obtain(len);
@@ -330,16 +347,101 @@
                 false /* no info */);
         switch(paraDir) {
             case Layout.DIR_RIGHT_TO_LEFT:
-                return "<p dir=\"rtl\">";
+                return " dir=\"rtl\"";
             case Layout.DIR_LEFT_TO_RIGHT:
             default:
-                return "<p dir=\"ltr\">";
+                return " dir=\"ltr\"";
         }
     }
 
-    private static void withinBlockquote(StringBuilder out, Spanned text,
-                                         int start, int end) {
-        out.append(getOpenParaTagWithDirection(text, start, end));
+    private static String getTextStyles(Spanned text, int start, int end) {
+        final StringBuilder style = new StringBuilder(" style=\"margin-top:0; margin-bottom:0;");
+
+        final AlignmentSpan[] alignmentSpans = text.getSpans(start, end, AlignmentSpan.class);
+        final int len = alignmentSpans.length;
+        if (len > 0) {
+            final Layout.Alignment alignment = alignmentSpans[len - 1].getAlignment();
+            if (alignment == Layout.Alignment.ALIGN_NORMAL) {
+                style.append(" text-align:start;");
+            } else if (alignment == Layout.Alignment.ALIGN_CENTER) {
+                style.append(" text-align:center;");
+            } else if (alignment == Layout.Alignment.ALIGN_OPPOSITE) {
+                style.append(" text-align:end;");
+            }
+        }
+
+        style.append("\"");
+        return style.toString();
+    }
+
+    private static void withinBlockquote(StringBuilder out, Spanned text, int start, int end,
+            int option) {
+        if ((option & TO_HTML_PARAGRAPH_FLAG) == TO_HTML_PARAGRAPH_LINES_CONSECUTIVE) {
+            withinBlockquoteConsecutive(out, text, start, end);
+        } else {
+            withinBlockquoteIndividual(out, text, start, end);
+        }
+    }
+
+    private static void withinBlockquoteIndividual(StringBuilder out, Spanned text, int start,
+            int end) {
+        boolean isInList = false;
+        int next;
+        for (int i = start; i <= end; i = next) {
+            next = TextUtils.indexOf(text, '\n', i, end);
+            if (next < 0) {
+                next = end;
+            }
+
+            boolean isListItem = false;
+            ParagraphStyle[] paragraphStyles = text.getSpans(i, next, ParagraphStyle.class);
+            for (ParagraphStyle paragraphStyle : paragraphStyles) {
+                final int spanFlags = text.getSpanFlags(paragraphStyle);
+                if ((spanFlags & Spanned.SPAN_PARAGRAPH) == Spanned.SPAN_PARAGRAPH
+                        && paragraphStyle instanceof BulletSpan) {
+                    isListItem = true;
+                    break;
+                }
+            }
+
+            if (isListItem && !isInList) {
+                // Current paragraph is the first item in a list
+                isInList = true;
+                out.append("<ul>\n");
+            }
+
+            if (isInList && !isListItem) {
+                // Current paragraph is no longer a list item; close the previously opened list
+                isInList = false;
+                out.append("</ul>\n");
+            }
+
+            String tagType = isListItem ? "li" : "p";
+            out.append("<").append(tagType).append(getTextDirection(text, start, next))
+                    .append(getTextStyles(text, start, next)).append(">");
+
+            if (next - i == 0) {
+                out.append("<br>");
+            } else {
+                withinParagraph(out, text, i, next);
+            }
+
+            out.append("</");
+            out.append(tagType);
+            out.append(">\n");
+
+            if (next == end && isInList) {
+                isInList = false;
+                out.append("</ul>\n");
+            }
+
+            next++;
+        }
+    }
+
+    private static void withinBlockquoteConsecutive(StringBuilder out, Spanned text, int start,
+            int end) {
+        out.append("<p").append(getTextDirection(text, start, end)).append(">");
 
         int next;
         for (int i = start; i < end; i = next) {
@@ -355,25 +457,30 @@
                 next++;
             }
 
-            if (withinParagraph(out, text, i, next - nl, nl, next == end)) {
-                /* Paragraph should be closed */
-                out.append("</p>\n");
-                out.append(getOpenParaTagWithDirection(text, next, end));
+            withinParagraph(out, text, i, next - nl);
+
+            if (nl == 1) {
+                out.append("<br>\n");
+            } else {
+                for (int j = 2; j < nl; j++) {
+                    out.append("<br>");
+                }
+                if (next != end) {
+                    /* Paragraph should be closed and reopened */
+                    out.append("</p>\n");
+                    out.append("<p").append(getTextDirection(text, start, end)).append(">");
+                }
             }
         }
 
         out.append("</p>\n");
     }
 
-    /* Returns true if the caller should close and reopen the paragraph. */
-    private static boolean withinParagraph(StringBuilder out, Spanned text,
-                                        int start, int end, int nl,
-                                        boolean last) {
+    private static void withinParagraph(StringBuilder out, Spanned text, int start, int end) {
         int next;
         for (int i = start; i < end; i = next) {
             next = text.nextSpanTransition(i, end, CharacterStyle.class);
-            CharacterStyle[] style = text.getSpans(i, next,
-                                                   CharacterStyle.class);
+            CharacterStyle[] style = text.getSpans(i, next, CharacterStyle.class);
 
             for (int j = 0; j < style.length; j++) {
                 if (style[j] instanceof StyleSpan) {
@@ -403,7 +510,7 @@
                     out.append("<u>");
                 }
                 if (style[j] instanceof StrikethroughSpan) {
-                    out.append("<strike>");
+                    out.append("<span style=\"text-decoration:line-through;\">");
                 }
                 if (style[j] instanceof URLSpan) {
                     out.append("<a href=\"");
@@ -419,36 +526,51 @@
                     i = next;
                 }
                 if (style[j] instanceof AbsoluteSizeSpan) {
-                    out.append("<font size =\"");
-                    out.append(((AbsoluteSizeSpan) style[j]).getSize() / 6);
-                    out.append("\">");
+                    AbsoluteSizeSpan s = ((AbsoluteSizeSpan) style[j]);
+                    float sizeDip = s.getSize();
+                    if (!s.getDip()) {
+                        Application application = ActivityThread.currentApplication();
+                        sizeDip /= application.getResources().getDisplayMetrics().density;
+                    }
+
+                    // px in CSS is the equivalance of dip in Android
+                    out.append(String.format("<span style=\"font-size:%.0fpx\";>", sizeDip));
+                }
+                if (style[j] instanceof RelativeSizeSpan) {
+                    float sizeEm = ((RelativeSizeSpan) style[j]).getSizeChange();
+                    out.append(String.format("<span style=\"font-size:%.2fem;\">", sizeEm));
                 }
                 if (style[j] instanceof ForegroundColorSpan) {
-                    out.append("<font color =\"#");
-                    String color = Integer.toHexString(((ForegroundColorSpan)
-                            style[j]).getForegroundColor() + 0x01000000);
-                    while (color.length() < 6) {
-                        color = "0" + color;
-                    }
-                    out.append(color);
-                    out.append("\">");
+                    int color = ((ForegroundColorSpan) style[j]).getForegroundColor();
+                    out.append(String.format("<span style=\"color:#%06X;\">", 0xFFFFFF & color));
+                }
+                if (style[j] instanceof BackgroundColorSpan) {
+                    int color = ((BackgroundColorSpan) style[j]).getBackgroundColor();
+                    out.append(String.format("<span style=\"background-color:#%06X;\">",
+                            0xFFFFFF & color));
                 }
             }
 
             withinStyle(out, text, i, next);
 
             for (int j = style.length - 1; j >= 0; j--) {
+                if (style[j] instanceof BackgroundColorSpan) {
+                    out.append("</span>");
+                }
                 if (style[j] instanceof ForegroundColorSpan) {
-                    out.append("</font>");
+                    out.append("</span>");
+                }
+                if (style[j] instanceof RelativeSizeSpan) {
+                    out.append("</span>");
                 }
                 if (style[j] instanceof AbsoluteSizeSpan) {
-                    out.append("</font>");
+                    out.append("</span>");
                 }
                 if (style[j] instanceof URLSpan) {
                     out.append("</a>");
                 }
                 if (style[j] instanceof StrikethroughSpan) {
-                    out.append("</strike>");
+                    out.append("</span>");
                 }
                 if (style[j] instanceof UnderlineSpan) {
                     out.append("</u>");
@@ -478,16 +600,6 @@
                 }
             }
         }
-
-        if (nl == 1) {
-            out.append("<br>\n");
-            return false;
-        } else {
-            for (int i = 2; i < nl; i++) {
-                out.append("<br>");
-            }
-            return !last;
-        }
     }
 
     private static void withinStyle(StringBuilder out, CharSequence text,
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index c5ed39a..3688d50 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -49,7 +49,7 @@
 
     void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets,
             in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw,
-            in Configuration newConfig, in Rect backDropFrame);
+            in Configuration newConfig, in Rect backDropFrame, boolean forceLayout);
     void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
diff --git a/core/java/android/view/KeyboardShortcutGroup.java b/core/java/android/view/KeyboardShortcutGroup.java
index 013255b..57d07c0 100644
--- a/core/java/android/view/KeyboardShortcutGroup.java
+++ b/core/java/android/view/KeyboardShortcutGroup.java
@@ -32,6 +32,8 @@
 public final class KeyboardShortcutGroup implements Parcelable {
     private final CharSequence mLabel;
     private final List<KeyboardShortcutInfo> mItems;
+    // The system group looks different UI wise.
+    private boolean mSystemGroup;
 
     /**
      * @param label The title to be used for this group, or null if there is none.
@@ -50,10 +52,33 @@
         this(label, Collections.<KeyboardShortcutInfo>emptyList());
     }
 
+    /**
+     * @param label The title to be used for this group, or null if there is none.
+     * @param items The set of items to be included.
+     * @param isSystemGroup Set this to {@code true} if this is s system group.
+     * @hide
+     */
+    public KeyboardShortcutGroup(@Nullable CharSequence label,
+            @NonNull List<KeyboardShortcutInfo> items, boolean isSystemGroup) {
+        mLabel = label;
+        mItems = new ArrayList<>(checkNotNull(items));
+        mSystemGroup = isSystemGroup;
+    }
+
+    /**
+     * @param label The title to be used for this group, or null if there is none.
+     * @param isSystemGroup Set this to {@code true} if this is s system group.
+     * @hide
+     */
+    public KeyboardShortcutGroup(@Nullable CharSequence label, boolean isSystemGroup) {
+        this(label, Collections.<KeyboardShortcutInfo>emptyList(), isSystemGroup);
+    }
+
     private KeyboardShortcutGroup(Parcel source) {
         mItems = new ArrayList<>();
         mLabel = source.readCharSequence();
         source.readTypedList(mItems, KeyboardShortcutInfo.CREATOR);
+        mSystemGroup = source.readInt() == 1;
     }
 
     /**
@@ -70,6 +95,11 @@
         return mItems;
     }
 
+    /** @hide **/
+    public boolean isSystemGroup() {
+        return mSystemGroup;
+    }
+
     /**
      * Adds an item to the existing list.
      *
@@ -88,6 +118,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeCharSequence(mLabel);
         dest.writeTypedList(mItems);
+        dest.writeInt(mSystemGroup ? 1 : 0);
     }
 
     public static final Creator<KeyboardShortcutGroup> CREATOR =
@@ -99,4 +130,4 @@
             return new KeyboardShortcutGroup[size];
         }
     };
-}
\ No newline at end of file
+}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 1c0ea0f..34713ad 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -25,8 +25,6 @@
 import android.widget.RemoteViews;
 import android.widget.TextView;
 
-import com.android.internal.R;
-
 import java.util.ArrayList;
 
 /**
@@ -39,6 +37,7 @@
     public static final int NO_COLOR = -1;
     private final int mHeaderMinWidth;
     private final int mExpandTopPadding;
+    private final int mContentEndMargin;
     private View mAppName;
     private View mSubTextView;
     private OnClickListener mExpandClickListener;
@@ -51,6 +50,7 @@
     private int mOriginalNotificationColor;
     private boolean mGroupHeader;
     private boolean mExpanded;
+    private boolean mShowWorkBadgeAtEnd;
 
     public NotificationHeaderView(Context context) {
         this(context, null);
@@ -68,6 +68,8 @@
         super(context, attrs, defStyleAttr, defStyleRes);
         mHeaderMinWidth = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.notification_header_shrink_min_width);
+        mContentEndMargin = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_end);
         mExpandTopPadding = (int) (1 * getResources().getDisplayMetrics().density);
     }
 
@@ -135,6 +137,9 @@
         super.onLayout(changed, l, t, r, b);
         if (mProfileBadge.getVisibility() != View.GONE) {
             int paddingEnd = getPaddingEnd();
+            if (mShowWorkBadgeAtEnd) {
+                paddingEnd = mContentEndMargin;
+            }
             if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
                 mProfileBadge.layout(paddingEnd,
                         mProfileBadge.getTop(),
@@ -225,6 +230,17 @@
         mExpandButton.setPadding(0, paddingTop, 0, 0);
     }
 
+    public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) {
+        if (showWorkBadgeAtEnd != mShowWorkBadgeAtEnd) {
+            setClipToPadding(!showWorkBadgeAtEnd);
+            mShowWorkBadgeAtEnd = showWorkBadgeAtEnd;
+        }
+    }
+
+    public View getWorkProfileIcon() {
+        return mProfileBadge;
+    }
+
     public class HeaderTouchListener implements View.OnTouchListener {
 
         private final ArrayList<Rect> mTouchRects = new ArrayList<>();
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 7ba046b..81bb638 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -139,9 +139,7 @@
 
     private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);
     private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
-
-    /** @hide */
-    public static boolean sUseLargeIcons = false;
+    private static boolean sUseLargeIcons = false;
 
     private final int mStyle;
     private int mSystemIconResourceId;
@@ -235,6 +233,15 @@
     }
 
     /**
+     * Updates wheter accessibility large icons are used or not.
+     * @hide
+     */
+    public static void setUseLargeIcons(boolean use) {
+        sUseLargeIcons = use;
+        gSystemIcons.clear();
+    }
+
+    /**
      * Creates a custom pointer from the given bitmap and hotspot information.
      *
      * @param bitmap The bitmap for the icon.
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9f6d3e5..5b48e28 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -698,7 +698,7 @@
         @Override
         public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
                 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
-                Configuration newConfig, Rect backDropRect) {
+                Configuration newConfig, Rect backDropRect, boolean forceLayout) {
             SurfaceView surfaceView = mSurfaceView.get();
             if (surfaceView != null) {
                 if (DEBUG) Log.v(
@@ -711,7 +711,8 @@
                         surfaceView.mReportDrawNeeded = true;
                         surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
                     } else if (surfaceView.mWinFrame.width() != frame.width()
-                            || surfaceView.mWinFrame.height() != frame.height()) {
+                            || surfaceView.mWinFrame.height() != frame.height()
+                            || forceLayout) {
                         surfaceView.mUpdateWindowNeeded = true;
                         surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
                     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5d41477..98e3289 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -263,6 +264,7 @@
     boolean mNewSurfaceNeeded;
     boolean mHasHadWindowFocus;
     boolean mLastWasImTarget;
+    boolean mForceNextWindowRelayout;
     CountDownLatch mWindowDrawCountDown;
 
     boolean mIsDrawing;
@@ -1625,7 +1627,8 @@
 
         final boolean isViewVisible = viewVisibility == View.VISIBLE;
         if (mFirst || windowShouldResize || insetsChanged ||
-                viewVisibilityChanged || params != null) {
+                viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
+            mForceNextWindowRelayout = false;
 
             if (isViewVisible) {
                 // If this window is giving internal insets to the window
@@ -2099,7 +2102,7 @@
 
         boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
 
-        if (!cancelDraw && !newSurface) {
+        if (!cancelDraw) {
             if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                 for (int i = 0; i < mPendingTransitions.size(); ++i) {
                     mPendingTransitions.get(i).startChangingAnimations();
@@ -2148,6 +2151,7 @@
             }
         }
     }
+
     private void handleOutOfResourcesException(Surface.OutOfResourcesException e) {
         Log.e(mTag, "OutOfResourcesException initializing HW surface", e);
         try {
@@ -3365,7 +3369,8 @@
                         && mPendingVisibleInsets.equals(args.arg3)
                         && mPendingOutsets.equals(args.arg7)
                         && mPendingBackDropFrame.equals(args.arg8)
-                        && args.arg4 == null) {
+                        && args.arg4 == null
+                        && args.argi1 == 0) {
                     break;
                 }
                 } // fall through...
@@ -3385,6 +3390,7 @@
                     mPendingVisibleInsets.set((Rect) args.arg3);
                     mPendingOutsets.set((Rect) args.arg7);
                     mPendingBackDropFrame.set((Rect) args.arg8);
+                    mForceNextWindowRelayout = args.argi1 != 0;
 
                     args.recycle();
 
@@ -5829,7 +5835,7 @@
 
     public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
             Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
-            Configuration newConfig, Rect backDropFrame) {
+            Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
         if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString()
                 + " contentInsets=" + contentInsets.toShortString()
                 + " visibleInsets=" + visibleInsets.toShortString()
@@ -5863,6 +5869,7 @@
         args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets;
         args.arg7 = sameProcessCall ? new Rect(outsets) : outsets;
         args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame;
+        args.argi1 = forceLayout ? 1 : 0;
         msg.obj = args;
         mHandler.sendMessage(msg);
     }
@@ -6878,11 +6885,12 @@
         @Override
         public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
                 Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
-                Configuration newConfig, Rect backDropFrame) {
+                Configuration newConfig, Rect backDropFrame, boolean forceLayout) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
                 viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
-                        visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame);
+                        visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame,
+                        forceLayout);
             }
         }
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 772eeec..0c5a5fc 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -589,14 +589,14 @@
         public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31;
 
         /**
-         * Window type: Windows that are overlaid <em>only</em> by an {@link
+         * Window type: Windows that are overlaid <em>only</em> by a connected {@link
          * android.accessibilityservice.AccessibilityService} for interception of
          * user interactions without changing the windows an accessibility service
          * can introspect. In particular, an accessibility service can introspect
          * only windows that a sighted user can interact with which is they can touch
          * these windows or can type into these windows. For example, if there
          * is a full screen accessibility overlay that is touchable, the windows
-         * below it will be introspectable by an accessibility service regardless
+         * below it will be introspectable by an accessibility service even though
          * they are covered by a touchable window.
          */
         public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 1327ea1..b673386 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -38,8 +38,8 @@
 /**
  * This class represents a node of the window content as well as actions that
  * can be requested from its source. From the point of view of an
- * {@link android.accessibilityservice.AccessibilityService} a window content is
- * presented as tree of accessibility node info which may or may not map one-to-one
+ * {@link android.accessibilityservice.AccessibilityService} a window's content is
+ * presented as a tree of accessibility node infos, which may or may not map one-to-one
  * to the view hierarchy. In other words, a custom view is free to report itself as
  * a tree of accessibility node info.
  * </p>
@@ -50,7 +50,7 @@
  * <p>
  * Please refer to {@link android.accessibilityservice.AccessibilityService} for
  * details about how to obtain a handle to window content as a tree of accessibility
- * node info as well as familiarizing with the security model.
+ * node info as well as details about the security model.
  * </p>
  * <div class="special reference">
  * <h3>Developer Guides</h3>
@@ -2422,18 +2422,30 @@
     }
 
     /**
-     * Gets the text selection start.
+     * Gets the text selection start or the cursor position.
+     * <p>
+     * If no text is selected, both this method and
+     * {@link AccessibilityNodeInfo#getTextSelectionEnd()} return the same value:
+     * the current location of the cursor.
+     * </p>
      *
-     * @return The text selection start if there is selection or -1.
+     * @return The text selection start, the cursor location if there is no selection, or -1 if
+     *         there is no text selection and no cursor.
      */
     public int getTextSelectionStart() {
         return mTextSelectionStart;
     }
 
     /**
-     * Gets the text selection end.
+     * Gets the text selection end if text is selected.
+     * <p>
+     * If no text is selected, both this method and
+     * {@link AccessibilityNodeInfo#getTextSelectionStart()} return the same value:
+     * the current location of the cursor.
+     * </p>
      *
-     * @return The text selection end if there is selection or -1.
+     * @return The text selection end, the cursor location if there is no selection, or -1 if
+     *         there is no text selection and no cursor.
      */
     public int getTextSelectionEnd() {
         return mTextSelectionEnd;
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 9e79057..655c9b3 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -51,7 +51,7 @@
     void removeAccessibilityInteractionConnection(IWindow windowToken);
 
     void registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient client,
-        in AccessibilityServiceInfo info);
+        in AccessibilityServiceInfo info, int flags);
 
     void unregisterUiTestAutomationService(IAccessibilityServiceClient client);
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9561f08..df84970 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1036,6 +1036,7 @@
             mChoiceActionMode = startActionMode(mMultiChoiceModeCallback);
         }
 
+        final boolean itemCheckChanged;
         if (mChoiceMode == CHOICE_MODE_MULTIPLE || mChoiceMode == CHOICE_MODE_MULTIPLE_MODAL) {
             boolean oldValue = mCheckStates.get(position);
             mCheckStates.put(position, value);
@@ -1046,7 +1047,8 @@
                     mCheckedIdStates.delete(mAdapter.getItemId(position));
                 }
             }
-            if (oldValue != value) {
+            itemCheckChanged = oldValue != value;
+            if (itemCheckChanged) {
                 if (value) {
                     mCheckedItemCount++;
                 } else {
@@ -1062,6 +1064,7 @@
             boolean updateIds = mCheckedIdStates != null && mAdapter.hasStableIds();
             // Clear all values if we're checking something, or unchecking the currently
             // selected item
+            itemCheckChanged = isItemChecked(position) != value;
             if (value || isItemChecked(position)) {
                 mCheckStates.clear();
                 if (updateIds) {
@@ -1081,8 +1084,8 @@
             }
         }
 
-        // Do not generate a data change while we are in the layout phase
-        if (!mInLayout && !mBlockLayoutRequests) {
+        // Do not generate a data change while we are in the layout phase or data has not changed
+        if (!mInLayout && !mBlockLayoutRequests && itemCheckChanged) {
             mDataChanged = true;
             rememberSyncState();
             requestLayout();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 617d3dd..3a61fcd 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2872,6 +2872,7 @@
         protected PopupWindow mPopupWindow;
         protected ViewGroup mContentView;
         int mPositionX, mPositionY;
+        int mClippingLimitLeft, mClippingLimitRight;
 
         protected abstract void createPopupWindow();
         protected abstract void initContentView();
@@ -2939,8 +2940,9 @@
             // Horizontal clipping
             final DisplayMetrics displayMetrics = mTextView.getResources().getDisplayMetrics();
             final int width = mContentView.getMeasuredWidth();
-            positionX = Math.min(displayMetrics.widthPixels - width, positionX);
-            positionX = Math.max(0, positionX);
+            positionX = Math.min(
+                    displayMetrics.widthPixels - width + mClippingLimitRight, positionX);
+            positionX = Math.max(-mClippingLimitLeft, positionX);
 
             if (isShowing()) {
                 mPopupWindow.update(positionX, positionY, -1, -1);
@@ -3118,6 +3120,8 @@
         private TextView mAddToDictionaryButton;
         private TextView mDeleteButton;
         private SuggestionSpan mMisspelledSpan;
+        private int mContainerMarginWidth;
+        private int mContainerMarginTop;
 
         private class CustomPopupWindow extends PopupWindow {
             @Override
@@ -3155,10 +3159,20 @@
         protected void initContentView() {
             final LayoutInflater inflater = (LayoutInflater) mTextView.getContext().
                     getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-            final LinearLayout linearLayout = (LinearLayout) inflater.inflate(
+            final ViewGroup relativeLayout = (ViewGroup) inflater.inflate(
                     mTextView.mTextEditSuggestionContainerLayout, null);
 
-            final ListView suggestionListView = (ListView) linearLayout.findViewById(
+            final LinearLayout suggestionWindowContainer =
+                    (LinearLayout) relativeLayout.findViewById(
+                            com.android.internal.R.id.suggestionWindowContainer);
+            ViewGroup.MarginLayoutParams lp =
+                    (ViewGroup.MarginLayoutParams) suggestionWindowContainer.getLayoutParams();
+            mContainerMarginWidth = lp.leftMargin + lp.rightMargin;
+            mContainerMarginTop = lp.topMargin;
+            mClippingLimitLeft = lp.leftMargin;
+            mClippingLimitRight = lp.rightMargin;
+
+            final ListView suggestionListView = (ListView) relativeLayout.findViewById(
                     com.android.internal.R.id.suggestionContainer);
 
             mSuggestionsAdapter = new SuggestionAdapter();
@@ -3171,9 +3185,9 @@
                 mSuggestionInfos[i] = new SuggestionInfo();
             }
 
-            mContentView = linearLayout;
+            mContentView = relativeLayout;
 
-            mAddToDictionaryButton = (TextView) linearLayout.findViewById(
+            mAddToDictionaryButton = (TextView) relativeLayout.findViewById(
                     com.android.internal.R.id.addToDictionaryButton);
             mAddToDictionaryButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
@@ -3197,7 +3211,7 @@
                 }
             });
 
-            mDeleteButton = (TextView) linearLayout.findViewById(
+            mDeleteButton = (TextView) relativeLayout.findViewById(
                     com.android.internal.R.id.deleteButton);
             mDeleteButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
@@ -3306,6 +3320,8 @@
             mDeleteButton.measure(horizontalMeasure, verticalMeasure);
             width = Math.max(width, mDeleteButton.getMeasuredWidth());
 
+            width += mContainerMarginWidth;
+
             // Enforce the width based on actual text widths
             mContentView.measure(
                     View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
@@ -3327,7 +3343,7 @@
 
         @Override
         protected int getVerticalLocalPosition(int line) {
-            return mTextView.getLayout().getLineBottom(line);
+            return mTextView.getLayout().getLineBottom(line) - mContainerMarginTop;
         }
 
         @Override
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index b7b7400..2733391 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -66,6 +66,7 @@
 import android.widget.ListView;
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -209,7 +210,7 @@
         super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
                 null, false);
 
-        MetricsLogger.action(this, MetricsLogger.ACTION_ACTIVITY_CHOOSER_SHOWN);
+        MetricsLogger.action(this, MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN);
     }
 
     @Override
@@ -349,14 +350,14 @@
             int value = which;
             switch (mChooserListAdapter.getPositionTargetType(which)) {
                 case ChooserListAdapter.TARGET_CALLER:
-                    cat = MetricsLogger.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
+                    cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
                     break;
                 case ChooserListAdapter.TARGET_SERVICE:
-                    cat = MetricsLogger.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET;
+                    cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET;
                     value -= mChooserListAdapter.getCallerTargetCount();
                     break;
                 case ChooserListAdapter.TARGET_STANDARD:
-                    cat = MetricsLogger.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
+                    cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
                     value -= mChooserListAdapter.getCallerTargetCount()
                             + mChooserListAdapter.getServiceTargetCount();
                     break;
diff --git a/core/java/com/android/internal/app/ConfirmUserCreationActivity.java b/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
index 53d7793..03da9bc 100644
--- a/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
+++ b/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
@@ -64,6 +64,10 @@
 
         String message = checkUserCreationRequirements();
 
+        if (message == null) {
+            finish();
+            return;
+        }
         final AlertController.AlertParams ap = mAlertParams;
         ap.mMessage = message;
         ap.mPositiveButtonText = getString(android.R.string.ok);
@@ -104,11 +108,11 @@
         mCanProceed = true;
         final String appName = appInfo.loadLabel(getPackageManager()).toString();
         if (cantCreateUser) {
-            message = getString(R.string.user_creation_cannot_add, appName);
-            mCanProceed = false;
+            setResult(UserManager.USER_CREATION_FAILED_NOT_PERMITTED);
+            return null;
         } else if (cantCreateAnyMoreUsers) {
-            message = getString(R.string.user_creation_cannot_add_any_more, appName);
-            mCanProceed = false;
+            setResult(UserManager.USER_CREATION_FAILED_NO_MORE_USERS);
+            return null;
         } else if (accountExists) {
             message = getString(R.string.user_creation_account_exists, appName, mAccountName);
         } else {
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3b9b8db..ec53a2e 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -121,4 +121,7 @@
     void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
+
+    void noteBleScanStarted(in WorkSource ws);
+    void noteBleScanStopped(in WorkSource ws);
 }
diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl
new file mode 100644
index 0000000..9de4a6c
--- /dev/null
+++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.os.ParcelUuid;
+
+/**
+ * Service interface for a generic sound recognition model.
+ * @hide
+ */
+interface ISoundTriggerService {
+
+
+    SoundTrigger.GenericSoundModel getSoundModel(in ParcelUuid soundModelId);
+
+    void updateSoundModel(in SoundTrigger.GenericSoundModel soundModel);
+
+    void deleteSoundModel(in ParcelUuid soundModelId);
+
+    void startRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback);
+
+    /**
+     * Stops recognition.
+     */
+    void stopRecognition(in ParcelUuid soundModelId, in IRecognitionStatusCallback callback);
+}
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index 71c2c21..c7459d7 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -17,6 +17,7 @@
 package com.android.internal.app;
 
 import android.icu.util.ULocale;
+import android.icu.text.ListFormatter;
 import android.util.LocaleList;
 
 import java.text.Collator;
@@ -145,20 +146,16 @@
      * @return the locale aware list of locale names
      */
     public static String getDisplayLocaleList(LocaleList locales, Locale displayLocale) {
-        final StringBuilder result = new StringBuilder();
-
         final Locale dispLocale = displayLocale == null ? Locale.getDefault() : displayLocale;
+
         int localeCount = locales.size();
+        final String[] localeNames = new String[localeCount];
         for (int i = 0; i < localeCount; i++) {
-            Locale locale = locales.get(i);
-            result.append(LocaleHelper.getDisplayName(locale, dispLocale, false));
-            // TODO: language aware list formatter. ICU has one.
-            if (i < localeCount - 1) {
-                result.append(", ");
-            }
+            localeNames[i] = LocaleHelper.getDisplayName(locales.get(i), dispLocale, false);
         }
 
-        return result.toString();
+        ListFormatter lfn = ListFormatter.getInstance(dispLocale);
+        return lfn.format(localeNames);
     }
 
     /**
diff --git a/core/java/com/android/internal/app/NetInitiatedActivity.java b/core/java/com/android/internal/app/NetInitiatedActivity.java
index b951f50e..d3bae16 100644
--- a/core/java/com/android/internal/app/NetInitiatedActivity.java
+++ b/core/java/com/android/internal/app/NetInitiatedActivity.java
@@ -133,7 +133,7 @@
         notificationId = -1;
     }
 
-    // Respond to NI Handler under GpsLocationProvider, 1 = accept, 2 = deny
+    // Respond to NI Handler under GnssLocationProvider, 1 = accept, 2 = deny
     private void sendUserResponse(int response) {
         if (DEBUG) Log.d(TAG, "sendUserResponse, response: " + response);
         LocationManager locationManager = (LocationManager)
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index aa38de7..ec148c55 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1231,7 +1231,9 @@
                 }
 
                 // Filter out any activities that the launched uid does not
-                // have permission for.  We don't do this when we have an explicit
+                // have permission for.
+                // Also filter out those that are suspended because they couldn't
+                // be started. We don't do this when we have an explicit
                 // list of resolved activities, because that only happens when
                 // we are being subclassed, so we can safely launch whatever
                 // they gave us.
@@ -1242,7 +1244,9 @@
                         int granted = ActivityManager.checkComponentPermission(
                                 ai.permission, mLaunchedFromUid,
                                 ai.applicationInfo.uid, ai.exported);
-                        if (granted != PackageManager.PERMISSION_GRANTED) {
+                        boolean suspended = (ai.applicationInfo.flags
+                                & ApplicationInfo.FLAG_SUSPENDED) != 0;
+                        if (granted != PackageManager.PERMISSION_GRANTED || suspended) {
                             // Access not allowed!
                             if (mOrigResolveList == currentResolveList) {
                                 mOrigResolveList = new ArrayList<>(mOrigResolveList);
diff --git a/core/java/com/android/internal/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java
deleted file mode 100644
index 522732d..0000000
--- a/core/java/com/android/internal/logging/MetricsConstants.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.logging;
-
-/**
- * Constants for mestrics logs.
- *
- * @hide
- */
-public interface MetricsConstants {
-    // These constants must match those in the analytic pipeline, do not edit.
-    // define metric categories in frameworks/base/core/proto/src/metrics_constants.proto.
-    public static final int MAIN_SETTINGS = 1;
-    public static final int ACCESSIBILITY = 2;
-    public static final int ACCESSIBILITY_CAPTION_PROPERTIES = 3;
-    public static final int ACCESSIBILITY_SERVICE = 4;
-    public static final int ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
-    public static final int ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
-    public static final int ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
-    public static final int ACCOUNT = 8;
-    public static final int ACCOUNTS_ACCOUNT_SYNC = 9;
-    public static final int ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
-    public static final int ACCOUNTS_MANAGE_ACCOUNTS = 11;
-    public static final int APN = 12;
-    public static final int APN_EDITOR = 13;
-    public static final int APP_OPS_DETAILS = 14;
-    public static final int APP_OPS_SUMMARY = 15;
-    public static final int APPLICATION = 16;
-    public static final int APPLICATIONS_APP_LAUNCH = 17;
-    public static final int APPLICATIONS_APP_PERMISSION = 18;
-    public static final int APPLICATIONS_APP_STORAGE = 19;
-    public static final int APPLICATIONS_INSTALLED_APP_DETAILS = 20;
-    public static final int APPLICATIONS_PROCESS_STATS_DETAIL = 21;
-    public static final int APPLICATIONS_PROCESS_STATS_MEM_DETAIL = 22;
-    public static final int APPLICATIONS_PROCESS_STATS_UI = 23;
-    public static final int BLUETOOTH = 24;
-    public static final int BLUETOOTH_DEVICE_PICKER = 25;
-    public static final int BLUETOOTH_DEVICE_PROFILES = 26;
-    public static final int CHOOSE_LOCK_GENERIC = 27;
-    public static final int CHOOSE_LOCK_PASSWORD = 28;
-    public static final int CHOOSE_LOCK_PATTERN = 29;
-    public static final int CONFIRM_LOCK_PASSWORD = 30;
-    public static final int CONFIRM_LOCK_PATTERN = 31;
-    public static final int CRYPT_KEEPER = 32;
-    public static final int CRYPT_KEEPER_CONFIRM = 33;
-    public static final int DASHBOARD_SEARCH_RESULTS = 34;
-    public static final int DASHBOARD_SUMMARY = 35;
-    public static final int DATA_USAGE = 36;
-    public static final int DATA_USAGE_SUMMARY = 37;
-    public static final int DATE_TIME = 38;
-    public static final int DEVELOPMENT = 39;
-    public static final int DEVICEINFO = 40;
-    public static final int DEVICEINFO_IMEI_INFORMATION = 41;
-    public static final int DEVICEINFO_STORAGE = 42;
-    public static final int DEVICEINFO_SIM_STATUS = 43;
-    public static final int DEVICEINFO_STATUS = 44;
-    public static final int DEVICEINFO_USB = 45;
-    public static final int DISPLAY = 46;
-    public static final int DREAM = 47;
-    public static final int ENCRYPTION = 48;
-    public static final int FINGERPRINT = 49;
-    public static final int FINGERPRINT_ENROLL = 50;
-    public static final int FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
-    public static final int FUELGAUGE_BATTERY_SAVER = 52;
-    public static final int FUELGAUGE_POWER_USAGE_DETAIL = 53;
-    public static final int FUELGAUGE_POWER_USAGE_SUMMARY = 54;
-    public static final int HOME = 55;
-    public static final int ICC_LOCK = 56;
-    public static final int INPUTMETHOD_LANGUAGE = 57;
-    public static final int INPUTMETHOD_KEYBOARD = 58;
-    public static final int INPUTMETHOD_SPELL_CHECKERS = 59;
-    public static final int INPUTMETHOD_SUBTYPE_ENABLER = 60;
-    public static final int INPUTMETHOD_USER_DICTIONARY = 61;
-    public static final int INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
-    public static final int LOCATION = 63;
-    public static final int LOCATION_MODE = 64;
-    public static final int MANAGE_APPLICATIONS = 65;
-    public static final int MASTER_CLEAR = 66;
-    public static final int MASTER_CLEAR_CONFIRM = 67;
-    public static final int NET_DATA_USAGE_METERED = 68;
-    public static final int NFC_BEAM = 69;
-    public static final int NFC_PAYMENT = 70;
-    public static final int NOTIFICATION = 71;
-    public static final int NOTIFICATION_APP_NOTIFICATION = 72;
-    public static final int NOTIFICATION_OTHER_SOUND = 73;
-    public static final int NOTIFICATION_REDACTION = 74;
-    public static final int NOTIFICATION_STATION = 75;
-    public static final int NOTIFICATION_ZEN_MODE = 76;
-    public static final int OWNER_INFO = 77;
-    public static final int PRINT_JOB_SETTINGS = 78;
-    public static final int PRINT_SERVICE_SETTINGS = 79;
-    public static final int PRINT_SETTINGS = 80;
-    public static final int PRIVACY = 81;
-    public static final int PROXY_SELECTOR = 82;
-    public static final int RESET_NETWORK = 83;
-    public static final int RESET_NETWORK_CONFIRM = 84;
-    public static final int RUNNING_SERVICE_DETAILS = 85;
-    public static final int SCREEN_PINNING = 86;
-    public static final int SECURITY = 87;
-    public static final int SIM = 88;
-    public static final int TESTING = 89;
-    public static final int TETHER = 90;
-    public static final int TRUST_AGENT = 91;
-    public static final int TRUSTED_CREDENTIALS = 92;
-    public static final int TTS_ENGINE_SETTINGS = 93;
-    public static final int TTS_TEXT_TO_SPEECH = 94;
-    public static final int USAGE_ACCESS = 95;
-    public static final int USER = 96;
-    public static final int USERS_APP_RESTRICTIONS = 97;
-    public static final int USER_DETAILS = 98;
-    public static final int VOICE_INPUT = 99;
-    public static final int VPN = 100;
-    public static final int WALLPAPER_TYPE = 101;
-    public static final int WFD_WIFI_DISPLAY = 102;
-    public static final int WIFI = 103;
-    public static final int WIFI_ADVANCED = 104;
-    public static final int WIFI_CALLING = 105;
-    public static final int WIFI_SAVED_ACCESS_POINTS = 106;
-    public static final int WIFI_APITEST = 107;
-    public static final int WIFI_INFO = 108;
-    public static final int WIFI_P2P = 109;
-    public static final int WIRELESS = 110;
-    public static final int QS_AIRPLANEMODE = 112;
-    public static final int QS_BLUETOOTH = 113;
-    public static final int QS_CAST = 114;
-    public static final int QS_CELLULAR = 115;
-    public static final int QS_COLORINVERSION = 116;
-    public static final int QS_DATAUSAGEDETAIL = 117;
-    public static final int QS_DND = 118;
-    public static final int QS_FLASHLIGHT = 119;
-    public static final int QS_HOTSPOT = 120;
-    public static final int QS_INTENT = 121;
-    public static final int QS_LOCATION = 122;
-    public static final int QS_ROTATIONLOCK = 123;
-    public static final int QS_USERDETAILITE = 124;
-    public static final int QS_USERDETAIL = 125;
-    public static final int QS_WIFI = 126;
-    public static final int NOTIFICATION_PANEL = 127;
-    public static final int NOTIFICATION_ITEM = 128;
-    public static final int NOTIFICATION_ITEM_ACTION = 129;
-    public static final int APPLICATIONS_ADVANCED = 130;
-    public static final int LOCATION_SCANNING = 131;
-    public static final int MANAGE_APPLICATIONS_ALL = 132;
-    public static final int MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
-    public static final int ACTION_WIFI_ADD_NETWORK = 134;
-    public static final int ACTION_WIFI_CONNECT = 135;
-    public static final int ACTION_WIFI_FORCE_SCAN = 136;
-    public static final int ACTION_WIFI_FORGET = 137;
-    public static final int ACTION_WIFI_OFF = 138;
-    public static final int ACTION_WIFI_ON = 139;
-    public static final int MANAGE_PERMISSIONS = 140;
-    public static final int NOTIFICATION_ZEN_MODE_PRIORITY = 141;
-    public static final int NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
-    public static final int MANAGE_DOMAIN_URLS = 143;
-    public static final int NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
-    public static final int NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
-    public static final int NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
-    public static final int ACTION_BAN_APP_NOTES = 147;
-    public static final int ACTION_DISMISS_ALL_NOTES = 148;
-    public static final int QS_DND_DETAILS = 149;
-    public static final int QS_BLUETOOTH_DETAILS = 150;
-    public static final int QS_CAST_DETAILS = 151;
-    public static final int QS_WIFI_DETAILS = 152;
-    public static final int QS_WIFI_TOGGLE = 153;
-    public static final int QS_BLUETOOTH_TOGGLE = 154;
-    public static final int QS_CELLULAR_TOGGLE = 155;
-    public static final int QS_SWITCH_USER = 156;
-    public static final int QS_CAST_SELECT = 157;
-    public static final int QS_CAST_DISCONNECT = 158;
-    public static final int ACTION_BLUETOOTH_TOGGLE = 159;
-    public static final int ACTION_BLUETOOTH_SCAN = 160;
-    public static final int ACTION_BLUETOOTH_RENAME = 161;
-    public static final int ACTION_BLUETOOTH_FILES = 162;
-    public static final int QS_DND_TIME = 163;
-    public static final int QS_DND_CONDITION_SELECT = 164;
-    public static final int QS_DND_ZEN_SELECT = 165;
-    public static final int QS_DND_TOGGLE = 166;
-    public static final int ACTION_ZEN_ALLOW_REMINDERS = 167;
-    public static final int ACTION_ZEN_ALLOW_EVENTS = 168;
-    public static final int ACTION_ZEN_ALLOW_MESSAGES = 169;
-    public static final int ACTION_ZEN_ALLOW_CALLS = 170;
-    public static final int ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
-    public static final int ACTION_ZEN_ADD_RULE = 172;
-    public static final int ACTION_ZEN_ADD_RULE_OK = 173;
-    public static final int ACTION_ZEN_DELETE_RULE = 174;
-    public static final int ACTION_ZEN_DELETE_RULE_OK = 175;
-    public static final int ACTION_ZEN_ENABLE_RULE = 176;
-    public static final int ACTION_AIRPLANE_TOGGLE = 177;
-    public static final int ACTION_CELL_DATA_TOGGLE = 178;
-    public static final int NOTIFICATION_ACCESS = 179;
-    public static final int NOTIFICATION_ZEN_MODE_ACCESS = 180;
-    public static final int APPLICATIONS_DEFAULT_APPS = 181;
-    public static final int APPLICATIONS_STORAGE_APPS = 182;
-    public static final int APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
-    public static final int APPLICATIONS_HIGH_POWER_APPS = 184;
-    public static final int FUELGAUGE_HIGH_POWER_DETAILS = 185;
-    public static final int ACTION_LS_UNLOCK = 186;
-    public static final int ACTION_LS_SHADE = 187;
-    public static final int ACTION_LS_HINT = 188;
-    public static final int ACTION_LS_CAMERA = 189;
-    public static final int ACTION_LS_DIALER = 190;
-    public static final int ACTION_LS_LOCK = 191;
-    public static final int ACTION_LS_NOTE = 192;
-    public static final int ACTION_LS_QS = 193;
-    public static final int ACTION_SHADE_QS_PULL = 194;
-    public static final int ACTION_SHADE_QS_TAP = 195;
-    public static final int LOCKSCREEN = 196;
-    public static final int BOUNCER = 197;
-    public static final int SCREEN = 198;
-    public static final int NOTIFICATION_ALERT = 199;
-    public static final int ACTION_EMERGENCY_CALL = 200;
-    public static final int APPLICATIONS_MANAGE_ASSIST = 201;
-    public static final int PROCESS_STATS_SUMMARY = 202;
-    public static final int ACTION_ROTATION_LOCK = 203;
-    public static final int ACTION_NOTE_CONTROLS = 204;
-    public static final int ACTION_NOTE_INFO = 205;
-    public static final int ACTION_APP_NOTE_SETTINGS = 206;
-    public static final int VOLUME_DIALOG = 207;
-    public static final int VOLUME_DIALOG_DETAILS = 208;
-    public static final int ACTION_VOLUME_SLIDER = 209;
-    public static final int ACTION_VOLUME_STREAM = 210;
-    public static final int ACTION_VOLUME_KEY = 211;
-    public static final int ACTION_VOLUME_ICON = 212;
-    public static final int ACTION_RINGER_MODE = 213;
-    public static final int ACTION_ACTIVITY_CHOOSER_SHOWN = 214;
-    public static final int ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
-    public static final int ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
-    public static final int ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
-    public static final int ACTION_BRIGHTNESS = 218;
-    public static final int ACTION_BRIGHTNESS_AUTO = 219;
-    public static final int BRIGHTNESS_DIALOG = 220;
-    public static final int SYSTEM_ALERT_WINDOW_APPS = 221;
-    public static final int DREAMING = 222;
-    public static final int DOZING = 223;
-    public static final int OVERVIEW_ACTIVITY = 224;
-    public static final int ABOUT_LEGAL_SETTINGS = 225;
-    public static final int ACTION_SEARCH_RESULTS = 226;
-    public static final int TUNER = 227;
-    public static final int TUNER_QS = 228;
-    public static final int TUNER_DEMO_MODE = 229;
-    public static final int TUNER_QS_REORDER = 230;
-    public static final int TUNER_QS_ADD = 231;
-    public static final int TUNER_QS_REMOVE = 232;
-    public static final int TUNER_STATUS_BAR_ENABLE = 233;
-    public static final int TUNER_STATUS_BAR_DISABLE = 234;
-    public static final int TUNER_DEMO_MODE_ENABLED = 235;
-    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;
-    public static final int QS_WORKMODE = 257;
-    public static final int BACKGROUND_CHECK_SUMMARY = 258;
-    public static final int QS_LOCK_TILE = 259;
-    public static final int QS_USER_TILE = 260;
-    public static final int QS_BATTERY_TILE = 261;
-    public static final int NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 262;
-    public static final int ACTION_ZEN_ALLOW_PEEK = 263;
-    public static final int ACTION_ZEN_ALLOW_LIGHTS = 264;
-    public static final int NOTIFICATION_TOPIC_NOTIFICATION = 265;
-    public static final int ACTION_DEFAULT_SMS_APP_CHANGED = 266;
-    public static final int QS_COLOR_MATRIX = 267;
-    public static final int QS_CUSTOM = 268;
-    public static final int ACTION_ZEN_ALLOW_SCREEN_ON = 269;
-
-    /**
-     * Logged when the user docks a window from recents by longpressing a task and dragging it to
-     * the dock area.
-     */
-    public static final int ACTION_WINDOW_DOCK_DRAG_DROP = 270;
-
-    /**
-     * Logged when the user docks a fullscreen window by long pressing recents which also opens
-     * recents on the lower/right side.
-     */
-    public static final int ACTION_WINDOW_DOCK_LONGPRESS = 271;
-
-    /**
-     * Logged when the user docks a window by dragging from the navbar which also opens recents on
-     * the lower/right side.
-     */
-    public static final int ACTION_WINDOW_DOCK_SWIPE = 272;
-
-    /**
-     * Logged when the user launches a profile-specific app and we intercept it with the confirm
-     * credentials UI.
-     */
-    public static final int PROFILE_CHALLENGE = 273;
-    public static final int QS_BATTERY_DETAIL = 274;
-
-    /**
-     * Logged when the user goes into the overview history.
-     */
-    public static final int OVERVIEW_HISTORY = 275;
-
-    /**
-     * Logged when the user pages through overview.
-     */
-    public static final int ACTION_OVERVIEW_PAGE = 276;
-
-    /**
-     * Logged when the user launches a task from overview.
-     */
-    public static final int ACTION_OVERVIEW_SELECT = 277;
-
-    /** Logged when the user views the emergency info. */
-    public static final int ACTION_VIEW_EMERGENCY_INFO = 278;
-
-    /** Logged when the user views the edit emergency info activity. */
-    public static final int ACTION_EDIT_EMERGENCY_INFO = 279;
-
-    /** Logged when the user edits an emergency info field. */
-    public static final int ACTION_EDIT_EMERGENCY_INFO_FIELD = 280;
-
-    /** Logged when the user adds a new emergency contact. */
-    public static final int ACTION_ADD_EMERGENCY_CONTACT = 281;
-
-    /** Logged when the user deletes an emergency contact. */
-    public static final int ACTION_DELETE_EMERGENCY_CONTACT = 282;
-
-    /** Logged when the user calls an emergency contact. */
-    public static final int ACTION_CALL_EMERGENCY_CONTACT = 283;
-}
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 183d8d7..ef725da 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -26,8 +26,8 @@
  *
  * @hide
  */
-public class MetricsLogger implements com.android.internal.logging.MetricsConstants {
-    // define metric categories in frameworks/base/core/proto/src/metrics_constants.proto.
+public class MetricsLogger {
+    // define metric categories in frameworks/base/proto/src/metrics_constants.proto.
 
     public static final int VIEW_UNKNOWN = MetricsEvent.VIEW_UNKNOWN;
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 57220b1..c71c131 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,6 +41,7 @@
 import android.os.SystemProperties;
 import android.os.WorkSource;
 import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -106,7 +107,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 139 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 140 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -119,6 +120,12 @@
     // in to one common name.
     private static final int MAX_WAKELOCKS_PER_UID = 100;
 
+    // Number of transmit power states the Wifi controller can be in.
+    private static final int NUM_WIFI_TX_LEVELS = 1;
+
+    // Number of transmit power states the Bluetooth controller can be in.
+    private static final int NUM_BT_TX_LEVELS = 1;
+
     private final JournaledFile mFile;
     public final AtomicFile mCheckinFile;
     public final AtomicFile mDailyFile;
@@ -379,11 +386,38 @@
     final LongSamplingCounter[] mNetworkPacketActivityCounters =
             new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
 
-    final LongSamplingCounter[] mBluetoothActivityCounters =
-            new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+    /**
+     * The WiFi controller activity (time in tx, rx, idle, and power consumed) for the device.
+     */
+    ControllerActivityCounterImpl mWifiActivity;
 
-    final LongSamplingCounter[] mWifiActivityCounters =
-            new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+    /**
+     * The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
+     */
+    ControllerActivityCounterImpl mBluetoothActivity;
+
+    /**
+     * The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
+     */
+    ControllerActivityCounterImpl mModemActivity;
+
+    /**
+     * Whether the device supports WiFi controller energy reporting. This is set to true on
+     * the first WiFi energy report. See {@link #mWifiActivity}.
+     */
+    boolean mHasWifiReporting = false;
+
+    /**
+     * Whether the device supports Bluetooth controller energy reporting. This is set to true on
+     * the first Bluetooth energy report. See {@link #mBluetoothActivity}.
+     */
+    boolean mHasBluetoothReporting = false;
+
+    /**
+     * Whether the device supports Modem controller energy reporting. This is set to true on
+     * the first Modem energy report. See {@link #mModemActivity}.
+     */
+    boolean mHasModemReporting = false;
 
     boolean mWifiOn;
     StopwatchTimer mWifiOnTimer;
@@ -479,8 +513,6 @@
     private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
 
     private PowerProfile mPowerProfile;
-    private boolean mHasWifiEnergyReporting = false;
-    private boolean mHasBluetoothEnergyReporting = false;
 
     /*
      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
@@ -1770,6 +1802,131 @@
         public abstract T instantiateObject();
     }
 
+    public static class ControllerActivityCounterImpl extends ControllerActivityCounter
+            implements Parcelable {
+        private final LongSamplingCounter mIdleTimeMillis;
+        private final LongSamplingCounter mRxTimeMillis;
+        private final LongSamplingCounter[] mTxTimeMillis;
+        private final LongSamplingCounter mPowerDrainMaMs;
+
+        public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) {
+            mIdleTimeMillis = new LongSamplingCounter(timeBase);
+            mRxTimeMillis = new LongSamplingCounter(timeBase);
+            mTxTimeMillis = new LongSamplingCounter[numTxStates];
+            for (int i = 0; i < numTxStates; i++) {
+                mTxTimeMillis[i] = new LongSamplingCounter(timeBase);
+            }
+            mPowerDrainMaMs = new LongSamplingCounter(timeBase);
+        }
+
+        public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) {
+            mIdleTimeMillis = new LongSamplingCounter(timeBase, in);
+            mRxTimeMillis = new LongSamplingCounter(timeBase, in);
+            final int recordedTxStates = in.readInt();
+            if (recordedTxStates != numTxStates) {
+                throw new ParcelFormatException("inconsistent tx state lengths");
+            }
+
+            mTxTimeMillis = new LongSamplingCounter[numTxStates];
+            for (int i = 0; i < numTxStates; i++) {
+                mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in);
+            }
+            mPowerDrainMaMs = new LongSamplingCounter(timeBase, in);
+        }
+
+        public void readSummaryFromParcel(Parcel in) {
+            mIdleTimeMillis.readSummaryFromParcelLocked(in);
+            mRxTimeMillis.readSummaryFromParcelLocked(in);
+            final int recordedTxStates = in.readInt();
+            if (recordedTxStates != mTxTimeMillis.length) {
+                throw new ParcelFormatException("inconsistent tx state lengths");
+            }
+            for (LongSamplingCounter counter : mTxTimeMillis) {
+                counter.readSummaryFromParcelLocked(in);
+            }
+            mPowerDrainMaMs.readSummaryFromParcelLocked(in);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeSummaryToParcel(Parcel dest) {
+            mIdleTimeMillis.writeSummaryFromParcelLocked(dest);
+            mRxTimeMillis.writeSummaryFromParcelLocked(dest);
+            dest.writeInt(mTxTimeMillis.length);
+            for (LongSamplingCounter counter : mTxTimeMillis) {
+                counter.writeSummaryFromParcelLocked(dest);
+            }
+            mPowerDrainMaMs.writeSummaryFromParcelLocked(dest);
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            mIdleTimeMillis.writeToParcel(dest);
+            mRxTimeMillis.writeToParcel(dest);
+            dest.writeInt(mTxTimeMillis.length);
+            for (LongSamplingCounter counter : mTxTimeMillis) {
+                counter.writeToParcel(dest);
+            }
+            mPowerDrainMaMs.writeToParcel(dest);
+        }
+
+        public void reset(boolean detachIfReset) {
+            mIdleTimeMillis.reset(detachIfReset);
+            mRxTimeMillis.reset(detachIfReset);
+            for (LongSamplingCounter counter : mTxTimeMillis) {
+                counter.reset(detachIfReset);
+            }
+            mPowerDrainMaMs.reset(detachIfReset);
+        }
+
+        public void detach() {
+            mIdleTimeMillis.detach();
+            mRxTimeMillis.detach();
+            for (LongSamplingCounter counter : mTxTimeMillis) {
+                counter.detach();
+            }
+            mPowerDrainMaMs.detach();
+        }
+
+        /**
+         * @return a LongSamplingCounter, measuring time spent in the idle state in
+         * milliseconds.
+         */
+        @Override
+        public LongSamplingCounter getIdleTimeCounter() {
+            return mRxTimeMillis;
+        }
+
+        /**
+         * @return a LongSamplingCounter, measuring time spent in the receive state in
+         * milliseconds.
+         */
+        @Override
+        public LongSamplingCounter getRxTimeCounter() {
+            return mRxTimeMillis;
+        }
+
+        /**
+         * @return a LongSamplingCounter[], measuring time spent in various transmit states in
+         * milliseconds.
+         */
+        @Override
+        public LongSamplingCounter[] getTxTimeCounters() {
+            return mTxTimeMillis;
+        }
+
+        /**
+         * @return a LongSamplingCounter, measuring power use in milli-ampere milliseconds (mAmS).
+         */
+        @Override
+        public LongSamplingCounter getPowerCounter() {
+            return mPowerDrainMaMs;
+        }
+    }
+
     /*
      * Get the wakeup reason counter, and create a new one if one
      * doesn't already exist.
@@ -3198,7 +3355,7 @@
                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
             } else {
                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
-                updateMobileRadioStateLocked(realElapsedRealtimeMs);
+                updateMobileRadioStateLocked(realElapsedRealtimeMs, null);
                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
             }
         }
@@ -4144,8 +4301,7 @@
         // During device boot, qtaguid isn't enabled until after the inital
         // loading of battery stats. Now that they're enabled, take our initial
         // snapshot for future delta calculation.
-        final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
-        updateMobileRadioStateLocked(elapsedRealtimeMs);
+        updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), null);
         updateWifiStateLocked(null);
     }
 
@@ -4328,26 +4484,34 @@
         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
     }
 
-    @Override public boolean hasBluetoothActivityReporting() {
-        return mHasBluetoothEnergyReporting;
+    @Override
+    public ControllerActivityCounter getBluetoothControllerActivity() {
+        return mBluetoothActivity;
     }
 
-    @Override public long getBluetoothControllerActivity(int type, int which) {
-        if (type >= 0 && type < mBluetoothActivityCounters.length) {
-            return mBluetoothActivityCounters[type].getCountLocked(which);
-        }
-        return 0;
+    @Override
+    public ControllerActivityCounter getWifiControllerActivity() {
+        return mWifiActivity;
     }
 
-    @Override public boolean hasWifiActivityReporting() {
-        return mHasWifiEnergyReporting;
+    @Override
+    public ControllerActivityCounter getModemControllerActivity() {
+        return mModemActivity;
     }
 
-    @Override public long getWifiControllerActivity(int type, int which) {
-        if (type >= 0 && type < mWifiActivityCounters.length) {
-            return mWifiActivityCounters[type].getCountLocked(which);
-        }
-        return 0;
+    @Override
+    public boolean hasBluetoothActivityReporting() {
+        return mHasBluetoothReporting;
+    }
+
+    @Override
+    public boolean hasWifiActivityReporting() {
+        return mHasWifiReporting;
+    }
+
+    @Override
+    public boolean hasModemActivityReporting() {
+        return mHasModemReporting;
     }
 
     @Override
@@ -4457,15 +4621,21 @@
 
         /**
          * The amount of time this uid has kept the WiFi controller in idle, tx, and rx mode.
+         * Can be null if the UID has had no such activity.
          */
-        LongSamplingCounter[] mWifiControllerTime =
-                new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+        private ControllerActivityCounterImpl mWifiControllerActivity;
 
         /**
          * The amount of time this uid has kept the Bluetooth controller in idle, tx, and rx mode.
+         * Can be null if the UID has had no such activity.
          */
-        LongSamplingCounter[] mBluetoothControllerTime =
-                new LongSamplingCounter[NUM_CONTROLLER_ACTIVITY_TYPES];
+        private ControllerActivityCounterImpl mBluetoothControllerActivity;
+
+        /**
+         * The amount of time this uid has kept the Modem controller in idle, tx, and rx mode.
+         * Can be null if the UID has had no such activity.
+         */
+        private ControllerActivityCounterImpl mModemControllerActivity;
 
         /**
          * The CPU times we had at the last history details update.
@@ -4684,18 +4854,43 @@
             }
         }
 
-        public void noteWifiControllerActivityLocked(int type, long timeMs) {
-            if (mWifiControllerTime[type] == null) {
-                mWifiControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase);
-            }
-            mWifiControllerTime[type].addCountLocked(timeMs);
+        @Override
+        public ControllerActivityCounter getWifiControllerActivity() {
+            return mWifiControllerActivity;
         }
 
-        public void noteBluetoothControllerActivityLocked(int type, long timeMs) {
-            if (mBluetoothControllerTime[type] == null) {
-                mBluetoothControllerTime[type] = new LongSamplingCounter(mOnBatteryTimeBase);
+        @Override
+        public ControllerActivityCounter getBluetoothControllerActivity() {
+            return mBluetoothControllerActivity;
+        }
+
+        @Override
+        public ControllerActivityCounter getModemControllerActivity() {
+            return mModemControllerActivity;
+        }
+
+        public ControllerActivityCounterImpl getOrCreateWifiControllerActivityLocked() {
+            if (mWifiControllerActivity == null) {
+                mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                        NUM_BT_TX_LEVELS);
             }
-            mBluetoothControllerTime[type].addCountLocked(timeMs);
+            return mWifiControllerActivity;
+        }
+
+        public ControllerActivityCounterImpl getOrCreateBluetoothControllerActivityLocked() {
+            if (mBluetoothControllerActivity == null) {
+                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                        NUM_BT_TX_LEVELS);
+            }
+            return mBluetoothControllerActivity;
+        }
+
+        public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() {
+            if (mModemControllerActivity == null) {
+                mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                        ModemActivityInfo.TX_POWER_LEVELS);
+            }
+            return mModemControllerActivity;
         }
 
         public StopwatchTimer createAudioTurnedOnTimerLocked() {
@@ -5083,24 +5278,6 @@
             return 0;
         }
 
-        @Override
-        public long getWifiControllerActivity(int type, int which) {
-            if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES &&
-                    mWifiControllerTime[type] != null) {
-                return mWifiControllerTime[type].getCountLocked(which);
-            }
-            return 0;
-        }
-
-        @Override
-        public long getBluetoothControllerActivity(int type, int which) {
-            if (type >= 0 && type < NUM_CONTROLLER_ACTIVITY_TYPES &&
-                    mBluetoothControllerTime[type] != null) {
-                return mBluetoothControllerTime[type].getCountLocked(which);
-            }
-            return 0;
-        }
-
         void initNetworkActivityLocked() {
             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
@@ -5190,14 +5367,16 @@
                 mMobileRadioActiveCount.reset(false);
             }
 
-            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-                if (mWifiControllerTime[i] != null) {
-                    mWifiControllerTime[i].reset(false);
-                }
+            if (mWifiControllerActivity != null) {
+                mWifiControllerActivity.reset(false);
+            }
 
-                if (mBluetoothControllerTime[i] != null) {
-                    mBluetoothControllerTime[i].reset(false);
-                }
+            if (mBluetoothActivity != null) {
+                mBluetoothActivity.reset(false);
+            }
+
+            if (mModemActivity != null) {
+                mModemActivity.reset(false);
             }
 
             mUserCpuTime.reset(false);
@@ -5342,15 +5521,18 @@
                     }
                 }
 
-                for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-                    if (mWifiControllerTime[i] != null) {
-                        mWifiControllerTime[i].detach();
-                    }
-
-                    if (mBluetoothControllerTime[i] != null) {
-                        mBluetoothControllerTime[i].detach();
-                    }
+                if (mWifiControllerActivity != null) {
+                    mWifiControllerActivity.detach();
                 }
+
+                if (mBluetoothControllerActivity != null) {
+                    mBluetoothControllerActivity.detach();
+                }
+
+                if (mModemControllerActivity != null) {
+                    mModemControllerActivity.detach();
+                }
+
                 mPids.clear();
 
                 mUserCpuTime.detach();
@@ -5521,22 +5703,25 @@
                 out.writeInt(0);
             }
 
-            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-                if (mWifiControllerTime[i] != null) {
-                    out.writeInt(1);
-                    mWifiControllerTime[i].writeToParcel(out);
-                } else {
-                    out.writeInt(0);
-                }
+            if (mWifiControllerActivity != null) {
+                out.writeInt(1);
+                mWifiControllerActivity.writeToParcel(out, 0);
+            } else {
+                out.writeInt(0);
             }
 
-            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-                if (mBluetoothControllerTime[i] != null) {
-                    out.writeInt(1);
-                    mBluetoothControllerTime[i].writeToParcel(out);
-                } else {
-                    out.writeInt(0);
-                }
+            if (mBluetoothControllerActivity != null) {
+                out.writeInt(1);
+                mBluetoothControllerActivity.writeToParcel(out, 0);
+            } else {
+                out.writeInt(0);
+            }
+
+            if (mModemControllerActivity != null) {
+                out.writeInt(1);
+                mModemControllerActivity.writeToParcel(out, 0);
+            } else {
+                out.writeInt(0);
             }
 
             mUserCpuTime.writeToParcel(out);
@@ -5727,20 +5912,25 @@
                 mNetworkPacketActivityCounters = null;
             }
 
-            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-                if (in.readInt() != 0) {
-                    mWifiControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
-                } else {
-                    mWifiControllerTime[i] = null;
-                }
+            if (in.readInt() != 0) {
+                mWifiControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                        NUM_WIFI_TX_LEVELS, in);
+            } else {
+                mWifiControllerActivity = null;
             }
 
-            for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-                if (in.readInt() != 0) {
-                    mBluetoothControllerTime[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
-                } else {
-                    mBluetoothControllerTime[i] = null;
-                }
+            if (in.readInt() != 0) {
+                mBluetoothControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                        NUM_BT_TX_LEVELS, in);
+            } else {
+                mBluetoothControllerActivity = null;
+            }
+
+            if (in.readInt() != 0) {
+                mModemControllerActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                        ModemActivityInfo.TX_POWER_LEVELS, in);
+            } else {
+                mModemControllerActivity = null;
             }
 
             mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
@@ -6916,10 +7106,12 @@
             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
         }
-        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
-            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
-        }
+        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_WIFI_TX_LEVELS);
+        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                NUM_BT_TX_LEVELS);
+        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                ModemActivityInfo.TX_POWER_LEVELS);
+
         mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
         mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
         mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase);
@@ -7567,10 +7759,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].reset(false);
         }
-        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mBluetoothActivityCounters[i].reset(false);
-            mWifiActivityCounters[i].reset(false);
-        }
+        mWifiActivity.reset(false);
+        mBluetoothActivity.reset(false);
+        mModemActivity.reset(false);
         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
 
         for (int i=0; i<mUidStats.size(); i++) {
@@ -7781,7 +7972,7 @@
         }
 
         if (info != null) {
-            mHasWifiEnergyReporting = true;
+            mHasWifiReporting = true;
 
             // Measured in mAms
             final long txTimeMs = info.getControllerTxTimeMillis();
@@ -7861,8 +8052,11 @@
                                 + scanRxTimeSinceMarkMs + " ms  Tx:"
                                 + scanTxTimeSinceMarkMs + " ms)");
                     }
-                    uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, scanRxTimeSinceMarkMs);
-                    uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, scanTxTimeSinceMarkMs);
+
+                    ControllerActivityCounterImpl activityCounter =
+                            uid.getOrCreateWifiControllerActivityLocked();
+                    activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
+                    activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
                     leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
                     leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
                 }
@@ -7881,7 +8075,8 @@
                         Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
                                 + myIdleTimeMs + " ms");
                     }
-                    uid.noteWifiControllerActivityLocked(CONTROLLER_IDLE_TIME, myIdleTimeMs);
+                    uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
+                            .addCountLocked(myIdleTimeMs);
                 }
             }
 
@@ -7898,7 +8093,8 @@
                 if (DEBUG_ENERGY) {
                     Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
                 }
-                uid.noteWifiControllerActivityLocked(CONTROLLER_TX_TIME, myTxTimeMs);
+                uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
+                        .addCountLocked(myTxTimeMs);
             }
 
             // Distribute the remaining Rx power appropriately between all apps that received
@@ -7909,25 +8105,23 @@
                 if (DEBUG_ENERGY) {
                     Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
                 }
-                uid.noteWifiControllerActivityLocked(CONTROLLER_RX_TIME, myRxTimeMs);
+                uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
+                        .addCountLocked(myRxTimeMs);
             }
 
             // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
 
             // Update WiFi controller stats.
-            mWifiActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
-                    info.getControllerRxTimeMillis());
-            mWifiActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
-                    info.getControllerTxTimeMillis());
-            mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
-                    info.getControllerIdleTimeMillis());
+            mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
+            mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis());
+            mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis());
 
             // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
             final double opVolt = mPowerProfile.getAveragePower(
                     PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
             if (opVolt != 0) {
                 // We store the power drain as mAms.
-                mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
+                mWifiActivity.getPowerCounter().addCountLocked(
                         (long)(info.getControllerEnergyUsed() / opVolt));
             }
         }
@@ -7936,9 +8130,10 @@
     /**
      * Distribute Cell radio energy info and network traffic to apps.
      */
-    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
+    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs,
+                                             final ModemActivityInfo activityInfo) {
         if (DEBUG_ENERGY) {
-            Slog.d(TAG, "Updating mobile radio stats");
+            Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
         }
 
         NetworkStats delta = null;
@@ -7951,60 +8146,112 @@
             return;
         }
 
-        if (delta == null || !mOnBatteryInternal) {
+        if (!mOnBatteryInternal) {
             return;
         }
 
         long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
                 elapsedRealtimeMs * 1000);
         mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
-        long totalPackets = delta.getTotalPackets();
 
-        final int size = delta.size();
-        for (int i = 0; i < size; i++) {
-            final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+        long totalRxPackets = 0;
+        long totalTxPackets = 0;
+        if (delta != null) {
+            final int size = delta.size();
+            for (int i = 0; i < size; i++) {
+                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+                if (entry.rxPackets == 0 || entry.txPackets == 0) {
+                    continue;
+                }
 
-            if (entry.rxBytes == 0 || entry.txBytes == 0) {
-                continue;
+                if (DEBUG_ENERGY) {
+                    Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
+                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+                            + " txPackets=" + entry.txPackets);
+                }
+
+                totalRxPackets += entry.rxPackets;
+                totalTxPackets += entry.txPackets;
+
+                final Uid u = getUidStatsLocked(mapUid(entry.uid));
+                u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
+                u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
+
+                mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                        entry.rxBytes);
+                mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                        entry.txBytes);
+                mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                        entry.rxPackets);
+                mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                        entry.txPackets);
             }
 
-            if (DEBUG_ENERGY) {
-                Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
-                        + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
-                        + " txPackets=" + entry.txPackets);
-            }
+            // Now distribute proportional blame to the apps that did networking.
+            long totalPackets = totalRxPackets + totalTxPackets;
+            if (totalPackets > 0) {
+                for (int i = 0; i < size; i++) {
+                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+                    if (entry.rxPackets == 0 && entry.txPackets == 0) {
+                        continue;
+                    }
 
-            final Uid u = getUidStatsLocked(mapUid(entry.uid));
-            u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
-                    entry.rxPackets);
-            u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
-                    entry.txPackets);
+                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
+
+                    // Distribute total radio active time in to this app.
+                    final long appPackets = entry.rxPackets + entry.txPackets;
+                    final long appRadioTime = (radioTime * appPackets) / totalPackets;
+                    u.noteMobileRadioActiveTimeLocked(appRadioTime);
+
+                    // Remove this app from the totals, so that we don't lose any time
+                    // due to rounding.
+                    radioTime -= appRadioTime;
+                    totalPackets -= appPackets;
+
+                    if (activityInfo != null) {
+                        ControllerActivityCounterImpl activityCounter =
+                                u.getOrCreateModemControllerActivityLocked();
+                        if (entry.rxPackets != 0) {
+                            final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
+                                    / totalRxPackets;
+                            activityCounter.getRxTimeCounter().addCountLocked(rxMs);
+                        }
+
+                        if (entry.txPackets != 0) {
+                            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+                                long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
+                                txMs /= totalTxPackets;
+                                activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
+                            }
+                        }
+                    }
+                }
+            }
 
             if (radioTime > 0) {
-                // Distribute total radio active time in to this app.
-                long appPackets = entry.rxPackets + entry.txPackets;
-                long appRadioTime = (radioTime*appPackets)/totalPackets;
-                u.noteMobileRadioActiveTimeLocked(appRadioTime);
-                // Remove this app from the totals, so that we don't lose any time
-                // due to rounding.
-                radioTime -= appRadioTime;
-                totalPackets -= appPackets;
+                // Whoops, there is some radio time we can't blame on an app!
+                mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
+                mMobileRadioActiveUnknownCount.addCountLocked(1);
             }
-
-            mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                    entry.rxBytes);
-            mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                    entry.txBytes);
-            mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                    entry.rxPackets);
-            mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                    entry.txPackets);
         }
 
-        if (radioTime > 0) {
-            // Whoops, there is some radio time we can't blame on an app!
-            mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
-            mMobileRadioActiveUnknownCount.addCountLocked(1);
+        if (activityInfo != null) {
+            mHasModemReporting = true;
+            mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis());
+            mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
+            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+                mModemActivity.getTxTimeCounters()[lvl]
+                        .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
+            }
+
+            // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
+            final double opVolt = mPowerProfile.getAveragePower(
+                    PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+            if (opVolt != 0) {
+                // We store the power drain as mAms.
+                mModemActivity.getPowerCounter().addCountLocked(
+                        (long) (activityInfo.getEnergyUsed() / opVolt));
+            }
         }
     }
 
@@ -8018,12 +8265,12 @@
         }
 
         if (info != null && mOnBatteryInternal) {
-            mHasBluetoothEnergyReporting = true;
-            mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
+            mHasBluetoothReporting = true;
+            mBluetoothActivity.getRxTimeCounter().addCountLocked(
                     info.getControllerRxTimeMillis());
-            mBluetoothActivityCounters[CONTROLLER_TX_TIME].addCountLocked(
+            mBluetoothActivity.getTxTimeCounters()[0].addCountLocked(
                     info.getControllerTxTimeMillis());
-            mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
+            mBluetoothActivity.getIdleTimeCounter().addCountLocked(
                     info.getControllerIdleTimeMillis());
 
             // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
@@ -8031,7 +8278,7 @@
                     PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
             if (opVolt != 0) {
                 // We store the power drain as mAms.
-                mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
+                mBluetoothActivity.getPowerCounter().addCountLocked(
                         (long) (info.getControllerEnergyUsed() / opVolt));
             }
 
@@ -9337,12 +9584,12 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
         }
-        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mBluetoothActivityCounters[i].readSummaryFromParcelLocked(in);
-        }
-        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mWifiActivityCounters[i].readSummaryFromParcelLocked(in);
-        }
+        mWifiActivity.readSummaryFromParcel(in);
+        mBluetoothActivity.readSummaryFromParcel(in);
+        mModemActivity.readSummaryFromParcel(in);
+        mHasWifiReporting = in.readInt() != 0;
+        mHasBluetoothReporting = in.readInt() != 0;
+        mHasModemReporting = in.readInt() != 0;
 
         mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt();
         mFlashlightOnNesting = 0;
@@ -9671,12 +9918,13 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
-        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mBluetoothActivityCounters[i].writeSummaryFromParcelLocked(out);
-        }
-        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mWifiActivityCounters[i].writeSummaryFromParcelLocked(out);
-        }
+        mWifiActivity.writeSummaryToParcel(out);
+        mBluetoothActivity.writeSummaryToParcel(out);
+        mModemActivity.writeSummaryToParcel(out);
+        out.writeInt(mHasWifiReporting ? 1 : 0);
+        out.writeInt(mHasBluetoothReporting ? 1 : 0);
+        out.writeInt(mHasModemReporting ? 1 : 0);
+
         out.writeInt(mNumConnectivityChange);
         mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -10019,15 +10267,17 @@
             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
                     null, mOnBatteryTimeBase, in);
         }
-        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
-        }
-        for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
-        }
 
-        mHasWifiEnergyReporting = in.readInt() != 0;
-        mHasBluetoothEnergyReporting = in.readInt() != 0;
+        mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                NUM_WIFI_TX_LEVELS, in);
+        mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                NUM_BT_TX_LEVELS, in);
+        mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
+                ModemActivityInfo.TX_POWER_LEVELS, in);
+        mHasWifiReporting = in.readInt() != 0;
+        mHasBluetoothReporting = in.readInt() != 0;
+        mHasModemReporting = in.readInt() != 0;
+
         mNumConnectivityChange = in.readInt();
         mLoadedNumConnectivityChange = in.readInt();
         mUnpluggedNumConnectivityChange = in.readInt();
@@ -10174,14 +10424,13 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
         }
-        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mBluetoothActivityCounters[i].writeToParcel(out);
-        }
-        for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
-            mWifiActivityCounters[i].writeToParcel(out);
-        }
-        out.writeInt(mHasWifiEnergyReporting ? 1 : 0);
-        out.writeInt(mHasBluetoothEnergyReporting ? 1 : 0);
+        mWifiActivity.writeToParcel(out, 0);
+        mBluetoothActivity.writeToParcel(out, 0);
+        mModemActivity.writeToParcel(out, 0);
+        out.writeInt(mHasWifiReporting ? 1 : 0);
+        out.writeInt(mHasBluetoothReporting ? 1 : 0);
+        out.writeInt(mHasModemReporting ? 1 : 0);
+
         out.writeInt(mNumConnectivityChange);
         out.writeInt(mLoadedNumConnectivityChange);
         out.writeInt(mUnpluggedNumConnectivityChange);
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 1f59672..531d1fa 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -40,15 +40,15 @@
     @Override
     public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
                                    long rawUptimeUs, int statsType) {
-        final long idleTimeMs = stats.getBluetoothControllerActivity(
-                BatteryStats.CONTROLLER_IDLE_TIME, statsType);
-        final long txTimeMs = stats.getBluetoothControllerActivity(
-                BatteryStats.CONTROLLER_TX_TIME, statsType);
-        final long rxTimeMs = stats.getBluetoothControllerActivity(
-                BatteryStats.CONTROLLER_RX_TIME, statsType);
+        final BatteryStats.ControllerActivityCounter counter =
+                stats.getBluetoothControllerActivity();
+
+        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
+        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
         final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
-        double powerMah = stats.getBluetoothControllerActivity(
-                BatteryStats.CONTROLLER_POWER_DRAIN, statsType) / (double)(1000*60*60);
+        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
+                 / (double)(1000*60*60);
 
         if (powerMah == 0) {
             // Some devices do not report the power, so calculate it.
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index aaa9f73..14ebe22 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -93,6 +93,12 @@
     public static final String POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE =
             "bluetooth.controller.voltage";
 
+    public static final String POWER_MODEM_CONTROLLER_IDLE = "modem.controller.idle";
+    public static final String POWER_MODEM_CONTROLLER_RX = "modem.controller.rx";
+    public static final String POWER_MODEM_CONTROLLER_TX = "modem.controller.tx";
+    public static final String POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE =
+            "modem.controller.voltage";
+
     /**
      * Power consumption when GPS is on.
      */
@@ -100,17 +106,23 @@
 
     /**
      * Power consumption when Bluetooth driver is on.
+     * @deprecated
      */
+    @Deprecated
     public static final String POWER_BLUETOOTH_ON = "bluetooth.on";
 
     /**
      * Power consumption when Bluetooth driver is transmitting/receiving.
+     * @deprecated
      */
+    @Deprecated
     public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active";
 
     /**
      * Power consumption when Bluetooth driver gets an AT command.
+     * @deprecated
      */
+    @Deprecated
     public static final String POWER_BLUETOOTH_AT_CMD = "bluetooth.at";
 
 
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 146c0f8..2a27f70 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -39,10 +39,14 @@
     @Override
     public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
                              long rawUptimeUs, int statsType) {
-        final long idleTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_IDLE_TIME,
-                statsType);
-        final long txTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_TX_TIME, statsType);
-        final long rxTime = u.getWifiControllerActivity(BatteryStats.CONTROLLER_RX_TIME, statsType);
+        final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
+        if (counter == null) {
+            return;
+        }
+
+        final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
+        final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+        final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
         app.wifiRunningTimeMs = idleTime + rxTime + txTime;
         app.wifiPowerMah =
                 ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa))
@@ -67,16 +71,15 @@
     @Override
     public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
                                    long rawUptimeUs, int statsType) {
-        final long idleTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_IDLE_TIME,
-                statsType);
-        final long rxTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_RX_TIME,
-                statsType);
-        final long txTimeMs = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_TX_TIME,
-                statsType);
+        final BatteryStats.ControllerActivityCounter counter = stats.getWifiControllerActivity();
+
+        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
+        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
         app.wifiRunningTimeMs = idleTimeMs + rxTimeMs + txTimeMs;
 
-        double powerDrainMah = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_POWER_DRAIN,
-                statsType) / (double)(1000*60*60);
+        double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType)
+                / (double)(1000*60*60);
         if (powerDrainMah == 0) {
             // Some controllers do not report power drain, so we can calculate it here.
             powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index a572486..a38139f 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -139,7 +139,12 @@
     }
 
     public SnapTarget getClosestDismissTarget(int position) {
-        if (position - mDismissStartTarget.position < mDismissEndTarget.position - position) {
+        if (position < mFirstSplitTarget.position) {
+            return mDismissStartTarget;
+        } else if (position > mLastSplitTarget.position) {
+            return mDismissEndTarget;
+        } else if (position - mDismissStartTarget.position
+                < mDismissEndTarget.position - position) {
             return mDismissStartTarget;
         } else {
             return mDismissEndTarget;
diff --git a/core/java/com/android/internal/policy/DockedDividerUtils.java b/core/java/com/android/internal/policy/DockedDividerUtils.java
index f7f5f15..00c65bd 100644
--- a/core/java/com/android/internal/policy/DockedDividerUtils.java
+++ b/core/java/com/android/internal/policy/DockedDividerUtils.java
@@ -48,17 +48,21 @@
                 outRect.top = position + dividerSize;
                 break;
         }
-        if (outRect.left >= outRect.right) {
-            outRect.left = outRect.right - 1;
+        sanitizeStackBounds(outRect);
+    }
+
+    public static void sanitizeStackBounds(Rect bounds) {
+        if (bounds.left >= bounds.right) {
+            bounds.left = bounds.right - 1;
         }
-        if (outRect.top >= outRect.bottom) {
-            outRect.top = outRect.bottom - 1;
+        if (bounds.top >= bounds.bottom) {
+            bounds.top = bounds.bottom - 1;
         }
-        if (outRect.right <= outRect.left) {
-            outRect.right = outRect.left + 1;
+        if (bounds.right <= bounds.left) {
+            bounds.right = bounds.left + 1;
         }
-        if (outRect.bottom <= outRect.top) {
-            outRect.bottom = outRect.top + 1;
+        if (bounds.bottom <= bounds.top) {
+            bounds.bottom = bounds.top + 1;
         }
     }
 
diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java
index b4d2d730..968d920 100644
--- a/core/java/com/android/internal/util/GrowingArrayUtils.java
+++ b/core/java/com/android/internal/util/GrowingArrayUtils.java
@@ -97,6 +97,21 @@
     }
 
     /**
+     * Primitive float version of {@link #append(Object[], int, Object)}.
+     */
+    public static float[] append(float[] array, int currentSize, float element) {
+        assert currentSize <= array.length;
+
+        if (currentSize + 1 > array.length) {
+            float[] newArray = ArrayUtils.newUnpaddedFloatArray(growSize(currentSize));
+            System.arraycopy(array, 0, newArray, 0, currentSize);
+            array = newArray;
+        }
+        array[currentSize] = element;
+        return array;
+    }
+
+    /**
      * Inserts an element into the array at the specified index, growing the array if there is no
      * more room.
      *
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 7dfc15d..bcc310f 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -38,7 +38,7 @@
     @Override
     public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets,
             Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig,
-            Rect backDropFrame) {
+            Rect backDropFrame, boolean forceLayout) {
         if (reportDraw) {
             try {
                 mSession.finishDrawing(this);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index c51c191..480d806 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1268,7 +1268,7 @@
         }
 
         private void maybeComputeTransitionDurationScale() {
-            if (mMainPanelSize == null || mOverflowPanel == null) {
+            if (mMainPanelSize != null && mOverflowPanelSize != null) {
                 int w = mMainPanelSize.getWidth() - mOverflowPanelSize.getWidth();
                 int h = mOverflowPanelSize.getHeight() - mMainPanelSize.getHeight();
                 mTransitionDurationScale = (int) (Math.sqrt(w * w + h * h) /
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 4e4552d..b07e36a 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -39,4 +39,5 @@
     void registerStrongAuthTracker(in IStrongAuthTracker tracker);
     void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
     void requireStrongAuth(int strongAuthReason, int userId);
+    void systemReady();
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 3f468ac..ba456f9 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -17,7 +17,6 @@
 package com.android.internal.widget;
 
 import android.annotation.IntDef;
-import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.IStrongAuthTracker;
 import android.app.trust.TrustManager;
@@ -503,10 +502,9 @@
         if (userHandle == UserHandle.USER_SYSTEM) {
             // Set the encryption password to default.
             updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
+            setCredentialRequiredToDecrypt(false);
         }
 
-        setCredentialRequiredToDecrypt(false);
-
         getDevicePolicyManager().setActivePasswordState(
                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle);
 
@@ -1340,9 +1338,9 @@
     }
 
     public void setCredentialRequiredToDecrypt(boolean required) {
-        if (ActivityManager.getCurrentUser() != UserHandle.USER_SYSTEM) {
-            Log.w(TAG, "Only device owner may call setCredentialRequiredForDecrypt()");
-            return;
+        if (!(getUserManager().isSystemUser() || getUserManager().isPrimaryUser())) {
+            throw new IllegalStateException(
+                    "Only the system or primary user may call setCredentialRequiredForDecrypt()");
         }
 
         if (isDeviceEncryptionEnabled()){
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
new file mode 100644
index 0000000..b45fd06
--- /dev/null
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.widget;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.RemoteViews;
+
+/**
+ * A TextView that can float around an image on the end.
+ *
+ * @hide
+ */
+@RemoteViews.RemoteView
+public class MediaNotificationView extends RelativeLayout {
+
+    private final int mMaxImageSize;
+    private final int mImageMarginBottom;
+    private final int mImageMinTopMargin;
+    private final int mNotificationContentMarginEnd;
+    private final int mNotificationContentImageMarginEnd;
+    private ImageView mRightIcon;
+    private View mActions;
+    private View mHeader;
+
+    public MediaNotificationView(Context context) {
+        this(context, null);
+    }
+
+    public MediaNotificationView(Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public MediaNotificationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int mode = MeasureSpec.getMode(widthMeasureSpec);
+        boolean hasIcon = mRightIcon.getVisibility() != GONE;
+        if (hasIcon && mode != MeasureSpec.UNSPECIFIED) {
+            measureChild(mActions, widthMeasureSpec, heightMeasureSpec);
+            int size = MeasureSpec.getSize(widthMeasureSpec);
+            int height = MeasureSpec.getSize(heightMeasureSpec);
+            size = size - mActions.getMeasuredWidth();
+            ViewGroup.MarginLayoutParams layoutParams =
+                    (MarginLayoutParams) mRightIcon.getLayoutParams();
+            size -= layoutParams.getMarginEnd();
+            size = Math.min(size, mMaxImageSize);
+            size = Math.max(size, mRightIcon.getMinimumWidth());
+            layoutParams.width = size;
+            layoutParams.height = size;
+            // because we can't allign it to the bottom with a margin, we add a topmargin to it
+            layoutParams.topMargin = height - size - mImageMarginBottom;
+            // If the topMargin is high enough we can also remove the header constraint!
+            if (layoutParams.topMargin >= mImageMinTopMargin) {
+                resetHeaderIndention();
+            } else {
+                int paddingEnd = mNotificationContentImageMarginEnd;
+                ViewGroup.MarginLayoutParams headerParams =
+                        (MarginLayoutParams) mHeader.getLayoutParams();
+                headerParams.setMarginEnd(size + layoutParams.getMarginEnd());
+                if (mHeader.getPaddingEnd() != paddingEnd) {
+                    mHeader.setPadding(
+                            isLayoutRtl() ? paddingEnd : mHeader.getPaddingLeft(),
+                            mHeader.getPaddingTop(),
+                            isLayoutRtl() ? mHeader.getPaddingLeft() : paddingEnd,
+                            mHeader.getPaddingBottom());
+                    mHeader.setLayoutParams(headerParams);
+                }
+            }
+            mRightIcon.setLayoutParams(layoutParams);
+        } else if (!hasIcon && mHeader.getPaddingEnd() != mNotificationContentMarginEnd) {
+            resetHeaderIndention();
+        }
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    private void resetHeaderIndention() {
+        if (mHeader.getPaddingEnd() != mNotificationContentMarginEnd) {
+            ViewGroup.MarginLayoutParams headerParams =
+                    (MarginLayoutParams) mHeader.getLayoutParams();
+            headerParams.setMarginEnd(0);
+            mHeader.setPadding(
+                    isLayoutRtl() ? mNotificationContentMarginEnd : mHeader.getPaddingLeft(),
+                    mHeader.getPaddingTop(),
+                    isLayoutRtl() ? mHeader.getPaddingLeft() : mNotificationContentMarginEnd,
+                    mHeader.getPaddingBottom());
+            mHeader.setLayoutParams(headerParams);
+        }
+    }
+
+    public MediaNotificationView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mMaxImageSize = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.media_notification_expanded_image_max_size);
+        mImageMarginBottom = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.media_notification_expanded_image_margin_bottom);
+        mImageMinTopMargin = (int) (context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_top)
+                + getResources().getDisplayMetrics().density * 2);
+        mNotificationContentMarginEnd = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_end);
+        mNotificationContentImageMarginEnd = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_image_margin_end);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mRightIcon = (ImageView) findViewById(com.android.internal.R.id.right_icon);
+        mActions = findViewById(com.android.internal.R.id.media_actions);
+        mHeader = findViewById(com.android.internal.R.id.notification_header);
+    }
+}
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
index 3f76e13..cee98b8 100644
--- a/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -47,6 +47,7 @@
     private static final String PREFERRED_HELPER = "preferred_activities";
     private static final String NOTIFICATION_HELPER = "notifications";
     private static final String PERMISSION_HELPER = "permissions";
+    private static final String USAGE_STATS_HELPER = "usage_stats";
 
     // These paths must match what the WallpaperManagerService uses.  The leaf *_FILENAME
     // are also used in the full-backup file format, so must not change unless steps are
@@ -96,7 +97,7 @@
         addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
         addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
         addHelper(PERMISSION_HELPER, new PermissionBackupHelper());
-
+        addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this));
         super.onBackup(oldState, data, newState);
     }
 
@@ -131,6 +132,7 @@
         addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
         addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
         addHelper(PERMISSION_HELPER, new PermissionBackupHelper());
+        addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this));
 
         try {
             super.onRestore(data, appVersionCode, newState);
@@ -183,7 +185,7 @@
             if (restoredWallpaper) {
                 IWallpaperManager wallpaper =
                         (IWallpaperManager)ServiceManager.getService(
-                        Context.WALLPAPER_SERVICE);
+                                Context.WALLPAPER_SERVICE);
                 if (wallpaper != null) {
                     try {
                         wallpaper.settingsRestored();
diff --git a/core/java/com/android/server/backup/UsageStatsBackupHelper.java b/core/java/com/android/server/backup/UsageStatsBackupHelper.java
new file mode 100644
index 0000000..bde2396
--- /dev/null
+++ b/core/java/com/android/server/backup/UsageStatsBackupHelper.java
@@ -0,0 +1,70 @@
+package com.android.server.backup;
+
+
+import android.app.backup.BlobBackupHelper;
+import android.app.usage.IUsageStatsManager;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.server.LocalServices;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class UsageStatsBackupHelper extends BlobBackupHelper {
+    static final String TAG = "UsgStatsBackupHelper";   // must be < 23 chars
+    static final boolean DEBUG = false;
+
+    // Current version of the blob schema
+    static final int BLOB_VERSION = 1;
+
+    // Key under which the payload blob is stored
+    // same as UsageStatsBackupHelperAssistant.KEY_USAGE_STATS
+    static final String KEY_USAGE_STATS = "usage_stats";
+
+    public UsageStatsBackupHelper(Context context) {
+        super(BLOB_VERSION, KEY_USAGE_STATS);
+    }
+
+    @Override
+    protected byte[] getBackupPayload(String key) {
+        if(KEY_USAGE_STATS.equals(key)) {
+            UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            DataOutputStream out  = new DataOutputStream(baos);
+            try{
+                out.writeInt(UserHandle.USER_SYSTEM);
+                out.write(localUsageStatsManager.getBackupPayload(UserHandle.USER_SYSTEM, key));
+            } catch (IOException ioe){
+                if (DEBUG) Log.e(TAG, "Failed to backup Usage Stats", ioe);
+                baos.reset();
+            }
+            return baos.toByteArray();
+        }
+        return null;
+    }
+
+
+    @Override
+    protected void applyRestoredPayload(String key, byte[] payload)  {
+        if (KEY_USAGE_STATS.equals(key)) {
+            UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class);
+            DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
+            try{
+                int user = in.readInt();
+                byte[] restoreData = new byte[payload.length - 4];
+                in.read(restoreData, 0, payload.length-4);
+                localUsageStatsManager.applyRestoredPayload(user, key, restoreData);
+            } catch (IOException ioe){
+                if (DEBUG) Log.e(TAG, "Failed to restore Usage Stats", ioe);
+            }
+        }
+    }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 644ecc6..8c4683d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -176,7 +176,8 @@
     com_android_internal_net_NetworkStatsFactory.cpp \
     com_android_internal_os_Zygote.cpp \
     com_android_internal_util_VirtualRefBasePtr.cpp \
-    com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
+    com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp \
+    android_os_HardwarePropertiesManager.cpp
 
 LOCAL_C_INCLUDES += \
     $(JNI_H_INCLUDE) \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 321440c..2e45f8c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -197,6 +197,7 @@
 extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
 extern int register_com_android_internal_os_Zygote(JNIEnv *env);
 extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
+extern int register_android_os_HardwarePropertiesManager(JNIEnv *env);
 
 static AndroidRuntime* gCurRuntime = NULL;
 
@@ -1387,7 +1388,7 @@
     REG_JNI(register_android_animation_PropertyValuesHolder),
     REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
     REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
-
+    REG_JNI(register_android_os_HardwarePropertiesManager),
 
 };
 
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 53d4c6a..563ec8b 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -90,6 +90,18 @@
             strokeLineJoin);
 }
 
+static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
+    VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
+    SkShader* fillShader = reinterpret_cast<SkShader*>(fillGradientPtr);
+    path->setFillGradient(fillShader);
+}
+
+static void updateFullPathStrokeGradient(JNIEnv*, jobject, jlong pathPtr, jlong strokeGradientPtr) {
+    VectorDrawable::FullPath* path = reinterpret_cast<VectorDrawable::FullPath*>(pathPtr);
+    SkShader* strokeShader = reinterpret_cast<SkShader*>(strokeGradientPtr);
+    path->setStrokeGradient(strokeShader);
+}
+
 static jboolean getFullPathProperties(JNIEnv* env, jobject, jlong fullPathPtr,
         jbyteArray outProperties, jint length) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
@@ -331,6 +343,8 @@
         {"nCreateFullPath", "!()J", (void*)createEmptyFullPath},
         {"nCreateFullPath", "!(J)J", (void*)createFullPath},
         {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
+        {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient},
+        {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient},
         {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties},
         {"nGetGroupProperties", "(J[FI)Z", (void*)getGroupProperties},
 
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 414eba7..806fcc3 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -534,7 +534,7 @@
     if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
         // Default path: hal version is don't care, do normal camera connect.
         camera = Camera::connect(cameraId, clientName,
-                Camera::USE_CALLING_UID);
+                Camera::USE_CALLING_UID, Camera::USE_CALLING_PID);
     } else {
         jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
                 Camera::USE_CALLING_UID, camera);
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 2e5cda0..4842e1b 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -23,6 +23,7 @@
 
 #include <utils/Log.h>
 #include <utils/Looper.h>
+#include <utils/Vector.h>
 
 #include <gui/Sensor.h>
 #include <gui/SensorManager.h>
@@ -39,12 +40,14 @@
     jclass clazz;
     jmethodID dispatchSensorEvent;
     jmethodID dispatchFlushCompleteEvent;
+    jmethodID dispatchAdditionalInfoEvent;
 } gBaseEventQueueClassInfo;
 
 namespace android {
 
 struct SensorOffsets
 {
+    jclass      clazz;
     jfieldID    name;
     jfieldID    vendor;
     jfieldID    version;
@@ -60,8 +63,13 @@
     jfieldID    maxDelay;
     jfieldID    flags;
     jmethodID   setType;
+    jmethodID   init;
 } gSensorOffsets;
 
+struct ListOffsets {
+    jclass      clazz;
+    jmethodID   add;
+} gListOffsets;
 
 /*
  * The method below are not thread-safe and not intended to be
@@ -70,8 +78,10 @@
 static void
 nativeClassInit (JNIEnv *_env, jclass _this)
 {
-    jclass sensorClass = _env->FindClass("android/hardware/Sensor");
+    //android.hardware.Sensor
     SensorOffsets& sensorOffsets = gSensorOffsets;
+    jclass sensorClass = (jclass) _env->NewGlobalRef(_env->FindClass("android/hardware/Sensor"));
+    sensorOffsets.clazz       = sensorClass;
     sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
     sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
     sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
@@ -88,7 +98,15 @@
                                                         "Ljava/lang/String;");
     sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");
     sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
+
     sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
+    sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
+
+    // java.util.List;
+    ListOffsets& listOffsets = gListOffsets;
+    jclass listClass = (jclass) _env->NewGlobalRef(_env->FindClass("java/util/List"));
+    listOffsets.clazz = listClass;
+    listOffsets.add = _env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
 }
 
 /**
@@ -141,6 +159,46 @@
     return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
 }
 
+static jobject
+translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nativeSensor) {
+    const SensorOffsets& sensorOffsets(gSensorOffsets);
+
+    if (sensor == NULL) {
+        // Sensor sensor = new Sensor();
+        sensor = env->NewObject(sensorOffsets.clazz, sensorOffsets.init, "");
+    }
+
+    if (sensor != NULL) {
+        jstring name = env->NewStringUTF(nativeSensor.getName().string());
+        jstring vendor = env->NewStringUTF(nativeSensor.getVendor().string());
+        jstring requiredPermission =
+                env->NewStringUTF(nativeSensor.getRequiredPermission().string());
+
+        env->SetObjectField(sensor, sensorOffsets.name,      name);
+        env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
+        env->SetIntField(sensor, sensorOffsets.version,      nativeSensor.getVersion());
+        env->SetIntField(sensor, sensorOffsets.handle,       nativeSensor.getHandle());
+        env->SetFloatField(sensor, sensorOffsets.range,      nativeSensor.getMaxValue());
+        env->SetFloatField(sensor, sensorOffsets.resolution, nativeSensor.getResolution());
+        env->SetFloatField(sensor, sensorOffsets.power,      nativeSensor.getPowerUsage());
+        env->SetIntField(sensor, sensorOffsets.minDelay,     nativeSensor.getMinDelay());
+        env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
+                         nativeSensor.getFifoReservedEventCount());
+        env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
+                         nativeSensor.getFifoMaxEventCount());
+        env->SetObjectField(sensor, sensorOffsets.requiredPermission,
+                            requiredPermission);
+        env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
+        env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
+        if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
+                == JNI_FALSE) {
+            jstring stringType = getInternedString(env, &nativeSensor.getStringType());
+            env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
+        }
+    }
+    return sensor;
+}
+
 static jboolean
 nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
 {
@@ -180,6 +238,24 @@
     return true;
 }
 
+static void
+nativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
+
+    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
+    const ListOffsets& listOffsets(gListOffsets);
+
+    Vector<Sensor> nativeList;
+
+    mgr->getDynamicSensorList(nativeList);
+
+    ALOGI("DYNS native SensorManager.getDynamicSensorList return %d sensors", nativeList.size());
+    for (size_t i = 0; i < nativeList.size(); ++i) {
+        jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
+        // add to list
+        env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
+    }
+}
+
 static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
     return mgr->isDataInjectionEnabled();
@@ -191,21 +267,25 @@
     sp<SensorEventQueue> mSensorQueue;
     sp<MessageQueue> mMessageQueue;
     jobject mReceiverWeakGlobal;
-    jfloatArray mScratch;
+    jfloatArray mFloatScratch;
+    jintArray   mIntScratch;
 public:
     Receiver(const sp<SensorEventQueue>& sensorQueue,
             const sp<MessageQueue>& messageQueue,
-            jobject receiverWeak, jfloatArray scratch) {
+            jobject receiverWeak) {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
         mSensorQueue = sensorQueue;
         mMessageQueue = messageQueue;
         mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
-        mScratch = (jfloatArray)env->NewGlobalRef(scratch);
+
+        mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
+        mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
     }
     ~Receiver() {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
         env->DeleteGlobalRef(mReceiverWeakGlobal);
-        env->DeleteGlobalRef(mScratch);
+        env->DeleteGlobalRef(mFloatScratch);
+        env->DeleteGlobalRef(mIntScratch);
     }
     sp<SensorEventQueue> getSensorEventQueue() const {
         return mSensorQueue;
@@ -234,9 +314,19 @@
                 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
                     // step-counter returns a uint64, but the java API only deals with floats
                     float value = float(buffer[i].u64.step_counter);
-                    env->SetFloatArrayRegion(mScratch, 0, 1, &value);
+                    env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
+                } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
+                    float value[2];
+                    value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
+                    value[1] = float(buffer[i].dynamic_sensor_meta.handle);
+                    env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
+                } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
+                    env->SetIntArrayRegion(mIntScratch, 0, 14,
+                                           buffer[i].additional_info.data_int32);
+                    env->SetFloatArrayRegion(mFloatScratch, 0, 14,
+                                             buffer[i].additional_info.data_float);
                 } else {
-                    env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
+                    env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
                 }
 
                 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
@@ -247,7 +337,21 @@
                                             gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
                                             buffer[i].meta_data.sensor);
                     }
-                } else {
+                } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
+                    // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
+                    // method.
+                    if (receiverObj.get()) {
+                        int type = buffer[i].additional_info.type;
+                        int serial = buffer[i].additional_info.serial;
+                        env->CallVoidMethod(receiverObj.get(),
+                                            gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
+                                            buffer[i].sensor,
+                                            type, serial,
+                                            mFloatScratch,
+                                            mIntScratch,
+                                            buffer[i].timestamp);
+                    }
+                }else {
                     int8_t status;
                     switch (buffer[i].type) {
                     case SENSOR_TYPE_ORIENTATION:
@@ -269,7 +373,7 @@
                         env->CallVoidMethod(receiverObj.get(),
                                             gBaseEventQueueClassInfo.dispatchSensorEvent,
                                             buffer[i].sensor,
-                                            mScratch,
+                                            mFloatScratch,
                                             status,
                                             buffer[i].timestamp);
                     }
@@ -290,7 +394,7 @@
 };
 
 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
-        jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstring packageName, jint mode) {
+        jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
     ScopedUtfChars packageUtf(env, packageName);
     String8 clientName(packageUtf.c_str());
@@ -302,7 +406,7 @@
         return 0;
     }
 
-    sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak, scratch);
+    sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
     receiver->incStrong((void*)nativeInitSensorEventQueue);
     return jlong(receiver.get());
 }
@@ -355,6 +459,10 @@
             "(JLandroid/hardware/Sensor;I)Z",
             (void*)nativeGetSensorAtIndex },
 
+    {"nativeGetDynamicSensors",
+            "(JLjava/util/List;)V",
+            (void*)nativeGetDynamicSensors },
+
     {"nativeIsDataInjectionEnabled",
             "(J)Z",
             (void*)nativeIsDataInjectionEnabled},
@@ -362,7 +470,7 @@
 
 static const JNINativeMethod gBaseEventQueueMethods[] = {
     {"nativeInitBaseEventQueue",
-             "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;ILjava/lang/String;)J",
+             "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
              (void*)nativeInitSensorEventQueue },
 
     {"nativeEnableSensor",
@@ -407,5 +515,8 @@
     gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
             gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
 
+    gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
+            gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
+
     return 0;
 }
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index b977e37..d25da78 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -54,6 +54,10 @@
 };
 static audio_attributes_fields_t javaAudioAttrFields;
 static audio_record_fields_t     javaAudioRecordFields;
+static struct {
+    jfieldID  fieldFramePosition;     // AudioTimestamp.framePosition
+    jfieldID  fieldNanoTime;          // AudioTimestamp.nanoTime
+} javaAudioTimestampFields;
 
 struct audiorecord_callback_cookie {
     jclass      audioRecord_class;
@@ -678,7 +682,40 @@
     }
 }
 
+// ----------------------------------------------------------------------------
+static jint android_media_AudioRecord_get_timestamp(JNIEnv *env, jobject thiz,
+        jobject timestamp, jint timebase) {
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
 
+    if (lpRecorder == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioRecord pointer for getTimestamp()");
+        return (jint)AUDIO_JAVA_ERROR;
+    }
+
+    // TODO Enable.
+#if 0
+    // get the record timestamp
+    ExtendedTimestamp ts;
+    jint status = nativeToJavaStatus(lpRecorder->getExtendedTimestamp(&ts));
+
+    if (status == AUDIO_JAVA_SUCCESS) {
+        // set the data
+        int64_t position, time;
+
+        status = nativeToJavaStatus(ts.getBestTimestamp(&position, &time, timebase));
+        if (status == AUDIO_JAVA_SUCCESS) {
+            env->SetLongField(
+                    timestamp, javaAudioTimestampFields.fieldFramePosition, position);
+            env->SetLongField(
+                    timestamp, javaAudioTimestampFields.fieldNanoTime, time);
+        }
+    }
+    return status;
+#else
+    return (jint)AUDIO_JAVA_INVALID_OPERATION;
+#endif
+}
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
@@ -716,6 +753,8 @@
     {"native_enableDeviceCallback", "()V", (void *)android_media_AudioRecord_enableDeviceCallback},
     {"native_disableDeviceCallback", "()V",
                                         (void *)android_media_AudioRecord_disableDeviceCallback},
+    {"native_get_timestamp", "(Landroid/media/AudioTimestamp;I)I",
+                                       (void *)android_media_AudioRecord_get_timestamp},
 };
 
 // field names found in android/media/AudioRecord.java
@@ -758,6 +797,13 @@
     javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env,
             audioAttrClass, "mFormattedTags", "Ljava/lang/String;");
 
+    // Get the RecordTimestamp class and fields
+    jclass audioTimestampClass = FindClassOrDie(env, "android/media/AudioTimestamp");
+    javaAudioTimestampFields.fieldFramePosition =
+            GetFieldIDOrDie(env, audioTimestampClass, "framePosition", "J");
+    javaAudioTimestampFields.fieldNanoTime =
+            GetFieldIDOrDie(env, audioTimestampClass, "nanoTime", "J");
+
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_os_HardwarePropertiesManager.cpp b/core/jni/android_os_HardwarePropertiesManager.cpp
new file mode 100644
index 0000000..dc1ba48
--- /dev/null
+++ b/core/jni/android_os_HardwarePropertiesManager.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "HardwarePropertiesManager-JNI"
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+#include <stdlib.h>
+
+#include <hardware/hardware_properties.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <hardware_properties/HardwarePropertiesManager.h>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+static struct {
+    jclass clazz;
+    jmethodID initMethod;
+} gCpuUsageInfoClassInfo;
+
+static struct hardware_properties_module* gHardwarePropertiesModule;
+
+// ----------------------------------------------------------------------------
+
+static void nativeInit(JNIEnv* env, jobject obj) {
+    status_t err = hw_get_module(HARDWARE_PROPERTIES_HARDWARE_MODULE_ID,
+            (hw_module_t const**)&gHardwarePropertiesModule);
+    if (err) {
+        ALOGE("Couldn't load %s module (%s)", HARDWARE_PROPERTIES_HARDWARE_MODULE_ID,
+              strerror(-err));
+    }
+}
+
+static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
+    if (gHardwarePropertiesModule && gHardwarePropertiesModule->getFanSpeeds) {
+        float *speeds = nullptr;
+        ssize_t size = gHardwarePropertiesModule->getFanSpeeds(gHardwarePropertiesModule, &speeds);
+
+        if (speeds && size > 0) {
+            jfloatArray fanSpeeds = env->NewFloatArray(size);
+            env->SetFloatArrayRegion(fanSpeeds, 0, size, speeds);
+            free(speeds);
+            return fanSpeeds;
+        }
+
+        if (size < 0) {
+            ALOGE("Cloudn't get fan speeds because of HAL error");
+        }
+    }
+    return env->NewFloatArray(0);
+}
+
+static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type) {
+    if (gHardwarePropertiesModule) {
+        ssize_t size = 0;
+        float *temps = nullptr;
+        switch (type) {
+        case DEVICE_TEMPERATURE_CPU:
+            if (gHardwarePropertiesModule->getCpuTemperatures) {
+                size = gHardwarePropertiesModule->getCpuTemperatures(gHardwarePropertiesModule,
+                                                                     &temps);
+            }
+            break;
+        case DEVICE_TEMPERATURE_GPU:
+            if (gHardwarePropertiesModule->getGpuTemperatures) {
+                size = gHardwarePropertiesModule->getGpuTemperatures(gHardwarePropertiesModule,
+                                                                    &temps);
+            }
+            break;
+        case DEVICE_TEMPERATURE_BATTERY:
+            if (gHardwarePropertiesModule->getBatteryTemperatures) {
+                size = gHardwarePropertiesModule->getBatteryTemperatures(gHardwarePropertiesModule,
+                                                                        &temps);
+            }
+            break;
+        }
+        if (temps && size > 0) {
+            jfloatArray deviceTemps = env->NewFloatArray(size);
+            env->SetFloatArrayRegion(deviceTemps, 0, size, temps);
+            free(temps);
+            return deviceTemps;
+        }
+        if (size < 0) {
+            ALOGE("Couldn't get device temperatures type=%d because of HAL error", type);
+        }
+    }
+    return env->NewFloatArray(0);
+}
+
+static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
+    if (gHardwarePropertiesModule && gHardwarePropertiesModule->getCpuUsages
+        && gCpuUsageInfoClassInfo.initMethod) {
+        int64_t *active_times = nullptr;
+        int64_t *total_times = nullptr;
+        ssize_t size = gHardwarePropertiesModule->getCpuUsages(gHardwarePropertiesModule,
+                                                               &active_times, &total_times);
+        if (active_times && total_times && size > 0) {
+            jobjectArray cpuUsages = env->NewObjectArray(size, gCpuUsageInfoClassInfo.clazz,
+                                                         nullptr);
+            for (ssize_t i = 0; i < size; ++i) {
+                jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz,
+                                                  gCpuUsageInfoClassInfo.initMethod,
+                                                  active_times[i], total_times[i]);
+                env->SetObjectArrayElement(cpuUsages, i, cpuUsage);
+            }
+            free(active_times);
+            free(total_times);
+            return cpuUsages;
+        }
+
+        if (size < 0) {
+            ALOGE("Couldn't get CPU usages because of HAL error");
+        }
+    }
+    return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gHardwarePropertiesManagerMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeInit", "()V",
+            (void*) nativeInit },
+    { "nativeGetFanSpeeds", "()[F",
+            (void*) nativeGetFanSpeeds },
+    { "nativeGetDeviceTemperatures", "(I)[F",
+            (void*) nativeGetDeviceTemperatures },
+    { "nativeGetCpuUsages", "()[Landroid/os/CpuUsageInfo;",
+            (void*) nativeGetCpuUsages }
+};
+
+int register_android_os_HardwarePropertiesManager(JNIEnv* env) {
+    gHardwarePropertiesModule = nullptr;
+    int res = jniRegisterNativeMethods(env, "android/os/HardwarePropertiesManager",
+                                       gHardwarePropertiesManagerMethods,
+                                       NELEM(gHardwarePropertiesManagerMethods));
+    jclass clazz = env->FindClass("android/os/CpuUsageInfo");
+    gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
+    gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz,
+                                                         "<init>", "(JJ)V");
+    return res;
+}
+
+} /* namespace android */
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 041e693..4194aa4 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -608,7 +608,7 @@
     jlong capabilities = 0;
 
     // Grant CAP_WAKE_ALARM to the Bluetooth process.
-    if (uid == AID_BLUETOOTH) {
+    if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
       capabilities |= (1LL << CAP_WAKE_ALARM);
     }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 56c3fc8..1c3db10 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -420,6 +420,8 @@
     <protected-broadcast android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS" />
     <protected-broadcast android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS" />
 
+    <protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -1407,6 +1409,13 @@
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Must be required by a {@link android.telecom.CallScreeningService},
+         to ensure that only the system can bind to it.
+         <p>Protection level: signature|privileged
+    -->
+    <permission android:name="android.permission.BIND_SCREENING_SERVICE"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
          @deprecated {@link android.telecom.ConnectionService}s should require
@@ -2860,6 +2869,12 @@
     <permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- Must be required by system/priv apps when accessing the sound trigger
+         APIs given by {@link SoundTriggerManager}.
+         @hide <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
+        android:protectionLevel="signature|privileged" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/layout/app_error_dialog.xml b/core/res/res/layout/app_error_dialog.xml
index aaa2dbc..46a2b2a 100644
--- a/core/res/res/layout/app_error_dialog.xml
+++ b/core/res/res/layout/app_error_dialog.xml
@@ -26,7 +26,7 @@
 >
 
 
-    <TextView
+    <Button
             android:id="@+id/aerr_restart"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -34,7 +34,7 @@
             style="@style/aerr_list_item"
     />
 
-    <TextView
+    <Button
             android:id="@+id/aerr_reset"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -42,7 +42,7 @@
             style="@style/aerr_list_item"
     />
 
-    <TextView
+    <Button
             android:id="@+id/aerr_report"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -50,7 +50,7 @@
             style="@style/aerr_list_item"
     />
 
-    <TextView
+    <Button
             android:id="@+id/aerr_close"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -58,7 +58,7 @@
             style="@style/aerr_list_item"
     />
 
-    <TextView
+    <Button
             android:id="@+id/aerr_mute"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index e8ff186..aa78eff 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -16,17 +16,17 @@
   -->
 
 <!-- Layout for the expanded media notification -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.internal.widget.MediaNotificationView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
-    android:layout_height="128dp"
+    android:layout_height="126dp"
     android:background="#00000000"
     android:tag="bigMediaNarrow"
     >
     <include layout="@layout/notification_template_header"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="48dp"
-        android:layout_marginEnd="106dp"/>
+        android:layout_alignParentStart="true"/>
     <LinearLayout
         android:id="@+id/notification_main_column"
         android:layout_width="match_parent"
@@ -34,7 +34,7 @@
         android:layout_marginTop="@dimen/notification_content_margin_top"
         android:layout_marginStart="@dimen/notification_content_margin_start"
         android:layout_marginBottom="@dimen/notification_content_margin_bottom"
-        android:layout_marginEnd="24dp"
+        android:layout_marginEnd="@dimen/notification_content_margin_end"
         android:layout_toStartOf="@id/right_icon"
         android:minHeight="@dimen/notification_min_content_height"
         android:orientation="vertical"
@@ -57,12 +57,13 @@
     </LinearLayout>
 
     <ImageView android:id="@+id/right_icon"
-        android:layout_width="96dp"
-        android:layout_height="96dp"
+        android:layout_width="@dimen/media_notification_expanded_image_max_size"
+        android:layout_height="@dimen/media_notification_expanded_image_max_size"
+        android:minWidth="40dp"
         android:layout_marginEnd="16dp"
         android:layout_marginTop="16dp"
         android:layout_alignParentEnd="true"
         android:layout_alignParentTop="true"
         android:scaleType="centerCrop"
         />
-</RelativeLayout>
+</com.android.internal.widget.MediaNotificationView>
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 9fcd356..aea9b44 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -24,8 +24,7 @@
     >
     <include layout="@layout/notification_template_header"
         android:layout_width="fill_parent"
-        android:layout_height="48dp"
-        android:layout_marginEnd="106dp"/>
+        android:layout_height="48dp" />
     <LinearLayout
         android:id="@+id/notification_main_column"
         android:layout_width="match_parent"
@@ -34,7 +33,6 @@
         android:orientation="horizontal"
         android:layout_marginStart="@dimen/notification_content_margin_start"
         android:layout_marginTop="@dimen/notification_content_margin_top"
-        android:layout_marginEnd="72dp"
         android:tag="media"
         >
         <LinearLayout
diff --git a/core/res/res/layout/text_edit_suggestion_container.xml b/core/res/res/layout/text_edit_suggestion_container.xml
index fe02d4e..17e93d0 100644
--- a/core/res/res/layout/text_edit_suggestion_container.xml
+++ b/core/res/res/layout/text_edit_suggestion_container.xml
@@ -14,32 +14,41 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:background="@drawable/text_edit_suggestions_window"
-    android:dropDownSelector="@drawable/list_selector_background"
-    android:divider="@null">
-    <ListView
-        android:id="@+id/suggestionContainer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:divider="?android:attr/dividerHorizontal">
-        <!-- Suggestions will be added here. -->
-    </ListView>
-
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
     <LinearLayout
-        android:layout_width="match_parent"
+        android:id="@+id/suggestionWindowContainer"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:divider="?android:attr/dividerHorizontal"
-        android:showDividers="middle">
-        <TextView
-            style="@android:style/Widget.Holo.SuggestionButton"
-            android:id="@+id/addToDictionaryButton"
-            android:text="@string/addToDictionary" />
-        <TextView
-            style="@android:style/Widget.Holo.SuggestionButton"
-            android:id="@+id/deleteButton"
-            android:text="@string/deleteText" />
+        android:elevation="2dp"
+        android:layout_margin="20dp"
+        android:background="@drawable/text_edit_suggestions_window"
+        android:dropDownSelector="@drawable/list_selector_background"
+        android:divider="@null">
+        <ListView
+            android:id="@+id/suggestionContainer"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:divider="?android:attr/dividerHorizontal">
+            <!-- Suggestions will be added here. -->
+        </ListView>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:divider="?android:attr/dividerHorizontal"
+            android:showDividers="middle">
+            <TextView
+                style="@android:style/Widget.Holo.SuggestionButton"
+                android:id="@+id/addToDictionaryButton"
+                android:text="@string/addToDictionary" />
+            <TextView
+                style="@android:style/Widget.Holo.SuggestionButton"
+                android:id="@+id/deleteButton"
+                android:text="@string/deleteText" />
+        </LinearLayout>
     </LinearLayout>
-</LinearLayout>
+</RelativeLayout>
diff --git a/core/res/res/layout/text_edit_suggestion_container_material.xml b/core/res/res/layout/text_edit_suggestion_container_material.xml
index 62e315b4..7826803 100644
--- a/core/res/res/layout/text_edit_suggestion_container_material.xml
+++ b/core/res/res/layout/text_edit_suggestion_container_material.xml
@@ -16,29 +16,38 @@
 
 <!-- Background of the popup window is the same as the one of the floating toolbar.
      Use floating toolbar background style. -->
-<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:background="?android:attr/floatingToolbarPopupBackgroundDrawable"
-    android:divider="?android:attr/listDivider"
-    android:showDividers="middle" >
-    <ListView
-        android:id="@+id/suggestionContainer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="8dip"
-        android:paddingBottom="0dip"
-        android:divider="@null" />
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
     <LinearLayout
-        android:layout_width="match_parent"
+        android:id="@+id/suggestionWindowContainer"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:orientation="vertical">
-          <TextView
-              style="@android:style/Widget.Material.SuggestionButton"
-              android:id="@+id/addToDictionaryButton"
-              android:text="@string/addToDictionary" />
-          <TextView
-              style="@android:style/Widget.Material.SuggestionButton"
-              android:id="@+id/deleteButton"
-              android:text="@string/deleteText" />
+        android:background="?android:attr/floatingToolbarPopupBackgroundDrawable"
+        android:elevation="2dp"
+        android:layout_margin="20dp"
+        android:orientation="vertical"
+        android:divider="?android:attr/listDivider"
+        android:showDividers="middle">
+        <ListView
+            android:id="@+id/suggestionContainer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dp"
+            android:paddingBottom="0dp"
+            android:divider="@null" />
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+            <TextView
+                style="@android:style/Widget.Material.SuggestionButton"
+                android:id="@+id/addToDictionaryButton"
+                android:text="@string/addToDictionary" />
+            <TextView
+                style="@android:style/Widget.Material.SuggestionButton"
+                android:id="@+id/deleteButton"
+                android:text="@string/deleteText" />
+        </LinearLayout>
     </LinearLayout>
-</LinearLayout>
+</RelativeLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 713038b..1f7206e 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3727,7 +3727,7 @@
         <!-- Controls how the image should be resized or moved to match the size
              of this ImageView.  See {@link android.widget.ImageView.ScaleType} -->
         <attr name="scaleType">
-            <!-- Scale using the image matrix when drawing. See  
+            <!-- Scale using the image matrix when drawing. See
                  {@link android.widget.ImageView#setImageMatrix(Matrix)}. -->
             <enum name="matrix" value="0" />
             <!-- Scale the image using {@link android.graphics.Matrix.ScaleToFit#FILL}. -->
@@ -3740,7 +3740,7 @@
             <enum name="fitEnd" value="4" />
             <!-- Center the image in the view, but perform no scaling. -->
             <enum name="center" value="5" />
-            <!-- Scale the image uniformly (maintain the image's aspect ratio) so both dimensions 
+            <!-- Scale the image uniformly (maintain the image's aspect ratio) so both dimensions
                  (width and height) of the image will be equal to or larger than the corresponding
                  dimension of the view (minus padding). The image is then centered in the view. -->
             <enum name="centerCrop" value="6" />
@@ -8135,4 +8135,52 @@
         <attr name="entries" />
         <attr name="entryValues" />
     </declare-styleable>
+
+    <!-- Used to describe the gradient for fill or stroke in a path of VectorDrawable. -->
+    <declare-styleable name="GradientColor">
+        <!-- Start color of the gradient. -->
+        <attr name="startColor" />
+        <!-- Optional center color. -->
+        <attr name="centerColor" />
+        <!-- End color of the gradient. -->
+        <attr name="endColor" />
+        <!-- Type of gradient. The default type is linear. -->
+        <attr name="type" />
+
+        <!-- Only applied to RadialGradient-->
+        <!-- Radius of the gradient, used only with radial gradient. -->
+        <attr name="gradientRadius" />
+
+        <!-- Only applied to SweepGradient / RadialGradient-->
+        <!-- X coordinate of the center of the gradient within the path. -->
+        <attr name="centerX" />
+        <!-- Y coordinate of the center of the gradient within the path. -->
+        <attr name="centerY" />
+
+        <!-- LinearGradient specific -->
+        <!-- X coordinate of the start point origin of the gradient.
+             Defined in same coordinates as the path itself -->
+        <attr name="startX" format="float" />
+        <!-- Y coordinate of the start point of the gradient within the shape.
+             Defined in same coordinates as the path itself -->
+        <attr name="startY" format="float" />
+        <!-- X coordinate of the end point origin of the gradient.
+             Defined in same coordinates as the path itself -->
+        <attr name="endX" format="float" />
+        <!-- Y coordinate of the end point of the gradient within the shape.
+             Defined in same coordinates as the path itself -->
+        <attr name="endY" format="float" />
+
+    </declare-styleable>
+
+    <!-- Describes an item of a GradientColor. Minimally need 2 items to define the gradient
+         Colors defined in <item> override the simple color attributes such as
+         "startColor / centerColor / endColor" are ignored -->
+    <declare-styleable name="GradientColorItem">
+        <!-- The offset (or ratio) of this current color item inside the gradient.
+             The value is only meaningful when it is between 0 and 1. -->
+        <attr name="offset" format="float" />
+        <!-- The current color for the offset inside the gradient. -->
+        <attr name="color" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index f92e7f0..7c6f338 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -146,6 +146,9 @@
     <!-- The margin on the end of the content view with a picture.-->
     <dimen name="notification_content_picture_margin">56dp</dimen>
 
+    <!-- The margin on the end of the content view with a picture in the compact media.-->
+    <dimen name="notification_content_picture_margin_media">72dp</dimen>
+
     <!-- height of the content margin to accomodate for the header -->
     <dimen name="notification_content_margin_top">30dp</dimen>
 
@@ -169,6 +172,15 @@
     <!-- The minimum height of the content if there are at least two lines or a picture-->
     <dimen name="notification_min_content_height">41dp</dimen>
 
+    <!-- The maximum size of the image in the expanded media notification -->
+    <dimen name="media_notification_expanded_image_max_size">94dp</dimen>
+
+    <!-- The maximum size of the image in the expanded media notification -->
+    <dimen name="media_notification_expanded_image_margin_bottom">16dp</dimen>
+
+    <!-- The margin of the content to an image-->
+    <dimen name="notification_content_image_margin_end">8dp</dimen>
+
     <!-- Preferred width of the search view. -->
     <dimen name="search_view_preferred_width">320dip</dimen>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 57132ea..a2ad09b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2691,6 +2691,11 @@
     <public type="attr" name="canPerformGestures" />
     <public type="attr" name="externalService" />
     <public type="attr" name="supportsLocalInteraction" />
+    <public type="attr" name="startX" />
+    <public type="attr" name="startY" />
+    <public type="attr" name="endX" />
+    <public type="attr" name="endY" />
+    <public type="attr" name="offset" />
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a276854..26421fb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -559,6 +559,9 @@
     <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen -->
     <string name="notification_hidden_text">Contents hidden</string>
 
+    <!-- Text shown in place of notification contents when the notification is hidden by policy on a secure lockscreen -->
+    <string name="notification_hidden_by_policy_text">Contents hidden by policy</string>
+
     <!-- Displayed to the user to tell them that they have started up the phone in "safe mode" -->
     <string name="safeMode">Safe mode</string>
 
@@ -4149,14 +4152,10 @@
     <string name="importance_from_topic">You set the importance of these notifications.</string>
     <string name="importance_from_person">This is important because of the people involved.</string>
 
-    <!-- Message to user that app trying to create user is not allowed to due to restrictions. [CHAR LIMIT=none] -->
-    <string name="user_creation_cannot_add"><b><xliff:g id="app" example="Gmail">%1$s</xliff:g></b> is trying to add a new user, but is currently prohibited.</string>
-    <!-- Message to user that app trying to create user is not allowed to due to user limit being reached. [CHAR LIMIT=none] -->
-    <string name="user_creation_cannot_add_any_more"><b><xliff:g id="app" example="Gmail">%1$s</xliff:g></b> is trying to add a new user, but the user limit has been reached.</string>
     <!-- Message to user that app trying to create user for an account that already exists. [CHAR LIMIT=none] -->
-    <string name="user_creation_account_exists"><b><xliff:g id="app" example="Gmail">%1$s</xliff:g></b> is trying to add a new user, but the account <b><xliff:g id="account" example="foobar">%2$s</xliff:g></b> already exists on this device. Proceed anyway?</string>
+    <string name="user_creation_account_exists">Allow <xliff:g id="app" example="Gmail">%1$s</xliff:g> to create a new User with <xliff:g id="account" example="foobar@gmail.com">%2$s</xliff:g> ?</string>
     <!-- Message to user that app is trying to create user for a specified account. [CHAR LIMIT=none] -->
-    <string name="user_creation_adding"><b><xliff:g id="app" example="Gmail">%1$s</xliff:g></b> is trying to add a new user for the account <b><xliff:g id="account" example="foobar">%2$s</xliff:g></b>. Proceed?</string>
+    <string name="user_creation_adding">Allow <xliff:g id="app" example="Gmail">%1$s</xliff:g> to create a new User with <xliff:g id="account" example="foobar">%2$s</xliff:g> (a User with this account already exists) ?</string>
 
     <!-- Locale picker strings -->
 
@@ -4190,4 +4189,12 @@
     <string name="new_sms_notification_title">You have new messages</string>
     <!-- Notification content shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] -->
     <string name="new_sms_notification_content">Open SMS app to view</string>
+
+    <!-- Notification title shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
+    <string name="user_encrypted_title">Some functions might not be available</string>
+    <!-- Notification message shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
+    <string name="user_encrypted_message">Touch to continue</string>
+    <!-- Notification detail shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
+    <string name="user_encrypted_detail">User profile locked</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index b660277..f0960c7 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1398,7 +1398,7 @@
     </style>
 
     <!-- @hide -->
-    <style name="aerr_list_item" parent="Widget.Material.Light.TextView">
+    <style name="aerr_list_item" parent="Widget.Material.Light.Button.Borderless">
         <item name="minHeight">?attr/listPreferredItemHeightSmall</item>
         <item name="textAppearance">?attr/textAppearanceListItemSmall</item>
         <item name="textColor">?attr/textColorAlertDialogListItem</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 81705b4..74ca8a5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -937,8 +937,6 @@
   <java-symbol type="string" name="time_picker_increment_minute_button" />
   <java-symbol type="string" name="time_picker_increment_set_pm_button" />
   <java-symbol type="string" name="upload_file" />
-  <java-symbol type="string" name="user_creation_cannot_add" />
-  <java-symbol type="string" name="user_creation_cannot_add_any_more" />
   <java-symbol type="string" name="user_creation_account_exists" />
   <java-symbol type="string" name="user_creation_adding" />
   <java-symbol type="string" name="user_switched" />
@@ -2390,6 +2388,7 @@
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
 
   <!-- EditText suggestion popup. -->
+  <java-symbol type="id" name="suggestionWindowContainer" />
   <java-symbol type="id" name="suggestionContainer" />
   <java-symbol type="id" name="addToDictionaryButton" />
   <java-symbol type="id" name="deleteButton" />
@@ -2401,6 +2400,7 @@
 
   <java-symbol type="string" name="notification_children_count_bracketed" />
   <java-symbol type="string" name="notification_hidden_text" />
+  <java-symbol type="string" name="notification_hidden_by_policy_text" />
   <java-symbol type="id" name="app_name_text" />
   <java-symbol type="id" name="number_of_children" />
   <java-symbol type="id" name="header_sub_text" />
@@ -2504,5 +2504,16 @@
   <java-symbol type="string" name="new_sms_notification_title" />
   <java-symbol type="string" name="new_sms_notification_content" />
 
+  <java-symbol type="dimen" name="media_notification_expanded_image_max_size" />
+  <java-symbol type="dimen" name="media_notification_expanded_image_margin_bottom" />
+  <java-symbol type="dimen" name="notification_content_image_margin_end" />
+  <java-symbol type="dimen" name="notification_content_picture_margin_media" />
+
   <java-symbol type="bool" name="config_strongAuthRequiredOnBoot" />
+
+  <!-- Encryption notification while accounts are locked by credential encryption -->
+  <java-symbol type="string" name="user_encrypted_title" />
+  <java-symbol type="string" name="user_encrypted_message" />
+  <java-symbol type="string" name="user_encrypted_detail" />
+
 </resources>
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index ddd0ca2..76b5fe1 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -39,15 +39,27 @@
   <item name="dsp.video">0.1</item> <!-- ~50mA -->
   <item name="camera.flashlight">0.1</item> <!-- Avg. power for camera flash, ~160mA -->
   <item name="camera.avg">0.1</item> <!-- Avg. power use of camera in standard usecases, ~550mA -->
+  <item name="gps.on">0.1</item> <!-- ~50mA -->
+
+  <!-- Radio related values. For modems without energy reporting support in firmware, use
+       radio.active, radio.scanning, and radio.on. -->
   <item name="radio.active">0.1</item> <!-- ~200mA -->
   <item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA -->
-  <item name="gps.on">0.1</item> <!-- ~50mA -->
   <!-- Current consumed by the radio at different signal strengths, when paging -->
   <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
       <value>0.2</value> <!-- ~2mA -->
       <value>0.1</value> <!-- ~1mA -->
   </array>
 
+
+  <!-- Radio related values. For modems WITH energy reporting support in firmware, use
+       modem.controller.idle, modem.controller.tx, modem.controller.rx, modem.controller.voltage.
+       -->
+  <item name="modem.controller.idle">0</item>
+  <item name="modem.controller.rx">0</item>
+  <item name="modem.controller.tx">0</item>
+  <item name="modem.controller.voltage">0</item>
+
   <!-- A list of heterogeneous CPU clusters, where the value for each cluster represents the
        number of CPU cores for that cluster.
 
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 999d47b..d412d7c 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -136,6 +136,12 @@
     <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" />
     <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" />
 
+    <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="cameraserver" />
+    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="cameraserver" />
+    <assign-permission name="android.permission.WAKE_LOCK" uid="cameraserver" />
+    <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="cameraserver" />
+    <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="cameraserver" />
+
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
 
     <!-- This is a list of all the libraries available for application
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index adb282f..94983b3 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -117,7 +117,10 @@
         }
     }
 
-    /* package */ long getNativeInstance() {
+    /**
+     * @hide
+     */
+    public long getNativeInstance() {
         return native_instance;
     }
 
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 6526021..1fc1b83 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -17,6 +17,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.ColorStateList;
+import android.content.res.ComplexColor;
+import android.content.res.GradientColor;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
@@ -27,6 +29,7 @@
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.Shader;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -121,9 +124,9 @@
  * <dd>Defines path data using exactly same format as "d" attribute
  * in the SVG's path data. This is defined in the viewport space.</dd>
  * <dt><code>android:fillColor</code></dt>
- * <dd>Specifies the color used to fill the path. May be a color or (SDK 24+ only) a color state
- * list. If this property is animated, any value set by the animation will override the original
- * value. No path fill is drawn if this property is not specified.</dd>
+ * <dd>Specifies the color used to fill the path. May be a color, also may be a color state list or
+ * a gradient color for SDK 24+. If this property is animated, any value set by the animation will
+ * override the original value. No path fill is drawn if this property is not specified.</dd>
  * <dt><code>android:strokeColor</code></dt>
  * <dd>Specifies the color used to draw the path outline. May be a color or (SDK 24+ only) a color
  * state list. If this property is animated, any value set by the animation will override the
@@ -1276,8 +1279,9 @@
         /////////////////////////////////////////////////////
         // Variables below need to be copied (deep copy if applicable) for mutation.
         private int[] mThemeAttrs;
-        ColorStateList mStrokeColors = null;
-        ColorStateList mFillColors = null;
+
+        ComplexColor mStrokeColors = null;
+        ComplexColor mFillColors = null;
         private long mNativePtr = 0;
 
         public VFullPath() {
@@ -1297,23 +1301,25 @@
         public boolean onStateChange(int[] stateSet) {
             boolean changed = false;
 
-            if (mStrokeColors != null) {
+            if (mStrokeColors != null && mStrokeColors instanceof ColorStateList) {
                 final int oldStrokeColor = getStrokeColor();
-                final int newStrokeColor = mStrokeColors.getColorForState(stateSet, oldStrokeColor);
+                final int newStrokeColor =
+                        ((ColorStateList) mStrokeColors).getColorForState(stateSet, oldStrokeColor);
                 changed |= oldStrokeColor != newStrokeColor;
                 if (oldStrokeColor != newStrokeColor) {
                     nSetStrokeColor(mNativePtr, newStrokeColor);
                 }
             }
 
-            if (mFillColors != null) {
+            if (mFillColors != null && mFillColors instanceof ColorStateList) {
                 final int oldFillColor = getFillColor();
-                final int newFillColor = mFillColors.getColorForState(stateSet, oldFillColor);
+                final int newFillColor = ((ColorStateList) mFillColors).getColorForState(stateSet, oldFillColor);
                 changed |= oldFillColor != newFillColor;
                 if (oldFillColor != newFillColor) {
                     nSetFillColor(mNativePtr, newFillColor);
                 }
             }
+
             return changed;
         }
 
@@ -1372,7 +1378,8 @@
             int strokeLineCap =  properties.getInt(STROKE_LINE_CAP_INDEX * 4);
             int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4);
             float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4);
-
+            Shader fillGradient = null;
+            Shader strokeGradient = null;
             // Account for any configuration changes.
             mChangingConfigurations |= a.getChangingConfigurations();
 
@@ -1391,23 +1398,43 @@
                 nSetPathString(mNativePtr, pathString, pathString.length());
             }
 
-            final ColorStateList fillColors = a.getColorStateList(
+            final ComplexColor fillColors = a.getComplexColor(
                     R.styleable.VectorDrawablePath_fillColor);
             if (fillColors != null) {
-                // 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;
+                // If the colors is a gradient color, or the color state list is stateful, keep the
+                // colors information. Otherwise, discard the colors and keep the default color.
+                if (fillColors instanceof  GradientColor) {
+                    mFillColors = fillColors;
+                    fillGradient = ((GradientColor) fillColors).getShader();
+                } else if (fillColors.isStateful()) {
+                    mFillColors = fillColors;
+                } else {
+                    mFillColors = null;
+                }
                 fillColor = fillColors.getDefaultColor();
             }
 
-            final ColorStateList strokeColors = a.getColorStateList(
+            final ComplexColor strokeColors = a.getComplexColor(
                     R.styleable.VectorDrawablePath_strokeColor);
             if (strokeColors != null) {
-                // 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;
+                // If the colors is a gradient color, or the color state list is stateful, keep the
+                // colors information. Otherwise, discard the colors and keep the default color.
+                if (strokeColors instanceof GradientColor) {
+                    mStrokeColors = strokeColors;
+                    strokeGradient = ((GradientColor) strokeColors).getShader();
+                } else if (strokeColors.isStateful()) {
+                    mStrokeColors = strokeColors;
+                } else {
+                    mStrokeColors = null;
+                }
                 strokeColor = strokeColors.getDefaultColor();
             }
+            // Update the gradient info, even if the gradiet is null.
+            nUpdateFullPathFillGradient(mNativePtr,
+                    fillGradient != null ? fillGradient.getNativeInstance() : 0);
+            nUpdateFullPathStrokeGradient(mNativePtr,
+                    strokeGradient != null ? strokeGradient.getNativeInstance() : 0);
+
             fillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha, fillAlpha);
 
             strokeLineCap = a.getInt(
@@ -1434,18 +1461,44 @@
 
         @Override
         public boolean canApplyTheme() {
-            return mThemeAttrs != null;
+            if (mThemeAttrs != null) {
+                return true;
+            }
+            boolean fillCanApplyTheme = canGradientApplyTheme(mFillColors);
+            boolean strokeCanApplyTheme = canGradientApplyTheme(mStrokeColors);
+            if (fillCanApplyTheme || strokeCanApplyTheme) {
+                return true;
+            }
+            return false;
+
         }
 
         @Override
         public void applyTheme(Theme t) {
-            if (mThemeAttrs == null) {
-                return;
+            if (mThemeAttrs != null) {
+                final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
+                updateStateFromTypedArray(a);
+                a.recycle();
             }
 
-            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
-            updateStateFromTypedArray(a);
-            a.recycle();
+            boolean fillCanApplyTheme = canGradientApplyTheme(mFillColors);
+            boolean strokeCanApplyTheme = canGradientApplyTheme(mStrokeColors);
+            if (fillCanApplyTheme) {
+                mFillColors = mFillColors.obtainForTheme(t);
+                nUpdateFullPathFillGradient(mNativePtr,
+                        ((GradientColor)mFillColors).getShader().getNativeInstance());
+            }
+
+            if (strokeCanApplyTheme) {
+                mStrokeColors = mStrokeColors.obtainForTheme(t);
+                nUpdateFullPathStrokeGradient(mNativePtr,
+                        ((GradientColor)mStrokeColors).getShader().getNativeInstance());
+            }
+        }
+
+        private boolean canGradientApplyTheme(ComplexColor complexColor) {
+            return complexColor != null && complexColor.canApplyTheme()
+                    && complexColor instanceof GradientColor;
         }
 
         /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
@@ -1560,6 +1613,8 @@
             int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
             float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
             int strokeLineJoin);
+    private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr);
+    private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr);
 
     private static native long nCreateClipPath();
     private static native long nCreateClipPath(long clipPathPtr);
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 1d31c9e..1cf15ac 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -18,6 +18,7 @@
 
 #include "PathParser.h"
 #include "SkImageInfo.h"
+#include "SkShader.h"
 #include <utils/Log.h>
 #include "utils/Macros.h"
 #include "utils/VectorDrawableUtils.h"
@@ -49,7 +50,7 @@
 
     float minScale = fmin(scaleX, scaleY);
     float strokeScale = minScale * matrixScale;
-    drawPath(outCanvas, renderPath, strokeScale);
+    drawPath(outCanvas, renderPath, strokeScale, pathMatrix);
 }
 
 void Path::setPathData(const Data& data) {
@@ -148,6 +149,9 @@
     mStrokeMiterLimit = path.mStrokeMiterLimit;
     mStrokeLineCap = path.mStrokeLineCap;
     mStrokeLineJoin = path.mStrokeLineJoin;
+
+    SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient);
+    SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient);
 }
 
 const SkPath& FullPath::getUpdatedPath() {
@@ -186,22 +190,43 @@
     return SkColorSetA(color, alphaBytes * alpha);
 }
 
-void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale){
-    // Draw path's fill, if fill color isn't transparent.
-    if (mFillColor != SK_ColorTRANSPARENT) {
+void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale,
+                        const SkMatrix& matrix){
+    // Draw path's fill, if fill color or gradient is valid
+    bool needsFill = false;
+    if (mFillGradient != nullptr) {
+        mPaint.setColor(applyAlpha(SK_ColorBLACK, mFillAlpha));
+        SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix);
+        mPaint.setShader(newShader);
+        needsFill = true;
+    } else if (mFillColor != SK_ColorTRANSPARENT) {
+        mPaint.setColor(applyAlpha(mFillColor, mFillAlpha));
+        needsFill = true;
+    }
+
+    if (needsFill) {
         mPaint.setStyle(SkPaint::Style::kFill_Style);
         mPaint.setAntiAlias(true);
-        mPaint.setColor(applyAlpha(mFillColor, mFillAlpha));
         outCanvas->drawPath(renderPath, mPaint);
     }
-    // Draw path's stroke, if stroke color isn't transparent
-    if (mStrokeColor != SK_ColorTRANSPARENT) {
+
+    // Draw path's stroke, if stroke color or gradient is valid
+    bool needsStroke = false;
+    if (mStrokeGradient != nullptr) {
+        mPaint.setColor(applyAlpha(SK_ColorBLACK, mStrokeAlpha));
+        SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix);
+        mPaint.setShader(newShader);
+        needsStroke = true;
+    } else if (mStrokeColor != SK_ColorTRANSPARENT) {
+        mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha));
+        needsStroke = true;
+    }
+    if (needsStroke) {
         mPaint.setStyle(SkPaint::Style::kStroke_Style);
         mPaint.setAntiAlias(true);
         mPaint.setStrokeJoin(mStrokeLineJoin);
         mPaint.setStrokeCap(mStrokeLineCap);
         mPaint.setStrokeMiter(mStrokeMiterLimit);
-        mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha));
         mPaint.setStrokeWidth(mStrokeWidth * strokeScale);
         outCanvas->drawPath(renderPath, mPaint);
     }
@@ -288,7 +313,7 @@
 }
 
 void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
-        float strokeScale){
+        float strokeScale, const SkMatrix& matrix){
     outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
 }
 
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 5ae5f6a..09bdce5 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -26,6 +26,7 @@
 #include <SkPath.h>
 #include <SkPathMeasure.h>
 #include <SkRect.h>
+#include <SkShader.h>
 
 #include <cutils/compiler.h>
 #include <stddef.h>
@@ -95,7 +96,7 @@
 protected:
     virtual const SkPath& getUpdatedPath();
     virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
-            float strokeScale) = 0;
+            float strokeScale, const SkMatrix& matrix) = 0;
     Data mData;
     SkPath mSkPath;
     bool mSkPathDirty = true;
@@ -108,6 +109,11 @@
     FullPath() : Path() {}
     FullPath(const Data& nodes) : Path(nodes) {}
 
+    ~FullPath() {
+        SkSafeUnref(mFillGradient);
+        SkSafeUnref(mStrokeGradient);
+    }
+
     void updateProperties(float strokeWidth, SkColor strokeColor,
             float strokeAlpha, SkColor fillColor, float fillAlpha,
             float trimPathStart, float trimPathEnd, float trimPathOffset,
@@ -162,10 +168,18 @@
     }
     bool getProperties(int8_t* outProperties, int length);
 
+    void setFillGradient(SkShader* fillGradient) {
+        SkRefCnt_SafeAssign(mFillGradient, fillGradient);
+    };
+    void setStrokeGradient(SkShader* strokeGradient) {
+        SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient);
+    };
+
+
 protected:
     const SkPath& getUpdatedPath() override;
     void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
-            float strokeScale) override;
+            float strokeScale, const SkMatrix& matrix) override;
 
 private:
     // Applies trimming to the specified path.
@@ -174,6 +188,8 @@
     SkColor mStrokeColor = SK_ColorTRANSPARENT;
     float mStrokeAlpha = 1;
     SkColor mFillColor = SK_ColorTRANSPARENT;
+    SkShader* mStrokeGradient = nullptr;
+    SkShader* mFillGradient = nullptr;
     float mFillAlpha = 1;
     float mTrimPathStart = 0;
     float mTrimPathEnd = 1;
@@ -195,7 +211,7 @@
 
 protected:
     void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
-            float strokeScale) override;
+            float strokeScale, const SkMatrix& matrix) override;
 };
 
 class ANDROID_API Group: public Node {
diff --git a/location/java/android/location/GnssNmeaListener.java b/location/java/android/location/GnssNmeaListener.java
new file mode 100644
index 0000000..6c9b08a
--- /dev/null
+++ b/location/java/android/location/GnssNmeaListener.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+/**
+* Used for receiving NMEA sentences from the GNSS.
+* NMEA 0183 is a standard for communicating with marine electronic devices
+* and is a common method for receiving data from a GNSS, typically over a serial port.
+* See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
+* You can implement this interface and call {@link LocationManager#addNmeaListener}
+* to receive NMEA data from the GNSS engine.
+*/
+public interface GnssNmeaListener {
+    /** Called when an NMEA message is received. */
+    void onNmeaReceived(long timestamp, String nmea);
+}
\ No newline at end of file
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
new file mode 100644
index 0000000..77e8a5b
--- /dev/null
+++ b/location/java/android/location/GnssStatus.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+/**
+ * This class represents the current state of the GNSS engine.
+ * This class is used in conjunction with the {@link GnssStatusCallback}.
+ */
+public final class GnssStatus {
+    /** Unknown constellation type. */
+    public static final int CONSTELLATION_UNKNOWN = 0;
+    /** Constellation type constant for GPS. */
+    public static final int CONSTELLATION_GPS = 1;
+    /** Constellation type constant for SBAS. */
+    public static final int CONSTELLATION_SBAS = 2;
+    /** Constellation type constant for Glonass. */
+    public static final int CONSTELLATION_GLONASS = 3;
+    /** Constellation type constant for QZSS. */
+    public static final int CONSTELLATION_QZSS = 4;
+    /** Constellation type constant for Beidou. */
+    public static final int CONSTELLATION_BEIDOU = 5;
+    /** Constellation type constant for Galileo. */
+    public static final int CONSTELLATION_GALILEO = 6;
+
+    // these must match the definitions in gps.h
+    /** @hide */
+    public static final int GNSS_SV_FLAGS_NONE = 0;
+    /** @hide */
+    public static final int GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA = (1 << 0);
+    /** @hide */
+    public static final int GNSS_SV_FLAGS_HAS_ALMANAC_DATA = (1 << 1);
+    /** @hide */
+    public static final int GNSS_SV_FLAGS_USED_IN_FIX = (1 << 2);
+
+    /** @hide */
+    public static final int PRN_SHIFT_WIDTH = 3;
+
+    /* These package private values are modified by the LocationManager class */
+    /* package */ int[] mPrnWithFlags;
+    /* package */ float[] mSnrs;
+    /* package */ float[] mElevations;
+    /* package */ float[] mAzimuths;
+    /* package */ int[] mConstellationTypes;
+    /* package */ int mSvCount;
+
+    GnssStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations, float[] azimuths,
+            int[] constellationTypes) {
+        mSvCount = svCount;
+        mPrnWithFlags = prnWithFlags;
+        mSnrs = snrs;
+        mElevations = elevations;
+        mAzimuths = azimuths;
+        mConstellationTypes = constellationTypes;
+    }
+
+    /**
+     * Gets the total number of satellites in satellite list.
+     */
+    public int getNumSatellites() {
+        return mSvCount;
+    }
+
+    /**
+     * Retrieves the constellation type of the satellite at the specified position.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public int getConstellationType(int satIndex) {
+        return mConstellationTypes[satIndex];
+    }
+
+    /**
+     * Retrieves the pseudo-random number of the satellite at the specified position.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public int getPrn(int satIndex) {
+        return mPrnWithFlags[satIndex] >> PRN_SHIFT_WIDTH;
+    }
+
+    /**
+     * Retrieves the signal-noise ration of the satellite at the specified position.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public float getSnr(int satIndex) {
+        return mSnrs[satIndex];
+    }
+
+    /**
+     * Retrieves the elevation of the satellite at the specified position.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public float getElevation(int satIndex) {
+        return 0f;
+    }
+
+    /**
+     * Retrieves the azimuth the satellite at the specified position.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public float getAzimuth(int satIndex) {
+        return mAzimuths[satIndex];
+    }
+
+    /**
+     * Detects whether the satellite at the specified position has ephemeris data.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public boolean hasEphemeris(int satIndex) {
+        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+    }
+
+    /**
+     * Detects whether the satellite at the specified position has almanac data.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public boolean hasAlmanac(int satIndex) {
+        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
+    }
+
+    /**
+     * Detects whether the satellite at the specified position is used in fix.
+     * @param satIndex the index of the satellite in the list.
+     */
+    public boolean usedInFix(int satIndex) {
+        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_USED_IN_FIX) != 0;
+    }
+}
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
new file mode 100644
index 0000000..b86171b
--- /dev/null
+++ b/location/java/android/location/GnssStatusCallback.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+/**
+ * Used for receiving notifications when GNSS events happen.
+ */
+public abstract class GnssStatusCallback {
+    /**
+     * Called when GNSS system has started.
+     */
+    public void onStarted() {}
+
+    /**
+     * Called when GNSS system has stopped.
+     */
+    public void onStopped() {}
+
+    /**
+     * Called when the GNSS system has received its first fix since starting.
+     * @param ttff the time from start to first fix.
+     */
+    public void onFirstFix(int ttff) {}
+
+    /**
+     * Called periodically to report GNSS satellite status.
+     * @param status the current status of all satellites.
+     */
+    public void onSatelliteStatusChanged(GnssStatus status) {}
+}
\ No newline at end of file
diff --git a/location/java/android/location/GpsClock.java b/location/java/android/location/GpsClock.java
index 4135a1c..719e56f 100644
--- a/location/java/android/location/GpsClock.java
+++ b/location/java/android/location/GpsClock.java
@@ -16,36 +16,41 @@
 
 package android.location;
 
-import android.annotation.SystemApi;
+import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A class containing a GPS clock timestamp.
  * It represents a measurement of the GPS receiver's clock.
- *
- * @hide
  */
-@SystemApi
-public class GpsClock implements Parcelable {
+public final class GpsClock implements Parcelable {
 
     // The following enumerations must be in sync with the values declared in gps.h
 
+    /** The type of the GPS Clock. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({CLOCK_TYPE_UNKNOWN, CLOCK_TYPE_LOCAL_HW_TIME, CLOCK_TYPE_GPS_TIME})
+    public @interface GpsClockType {}
+
     /**
      * The type of the time stored is not available or it is unknown.
      */
-    public static final byte TYPE_UNKNOWN = 0;
+    public static final byte CLOCK_TYPE_UNKNOWN = 0;
 
     /**
      * The source of the time value reported by this class is the 'Local Hardware Clock'.
      */
-    public static final byte TYPE_LOCAL_HW_TIME = 1;
+    public static final byte CLOCK_TYPE_LOCAL_HW_TIME = 1;
 
     /**
      * The source of the time value reported by this class is the 'GPS time' derived from
      * satellites (epoch = Jan 6, 1980).
      */
-    public static final byte TYPE_GPS_TIME = 2;
+    public static final byte CLOCK_TYPE_GPS_TIME = 2;
 
     private static final short HAS_NO_FLAGS = 0;
     private static final short HAS_LEAP_SECOND = (1<<0);
@@ -68,6 +73,7 @@
     private double mBiasUncertaintyInNs;
     private double mDriftInNsPerSec;
     private double mDriftUncertaintyInNsPerSec;
+    private long mTimeOfLastHwClockDiscontinuityInNs;
 
     GpsClock() {
         initialize();
@@ -87,6 +93,7 @@
         mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
         mDriftInNsPerSec = clock.mDriftInNsPerSec;
         mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
+        mTimeOfLastHwClockDiscontinuityInNs = clock.mTimeOfLastHwClockDiscontinuityInNs;
     }
 
     /**
@@ -99,6 +106,7 @@
     /**
      * Gets the type of time reported by {@link #getTimeInNs()}.
      */
+    @GpsClockType
     public byte getType() {
         return mType;
     }
@@ -106,7 +114,7 @@
     /**
      * Sets the type of time reported.
      */
-    public void setType(byte value) {
+    public void setType(@GpsClockType byte value) {
         mType = value;
     }
 
@@ -116,11 +124,11 @@
      */
     private String getTypeString() {
         switch (mType) {
-            case TYPE_UNKNOWN:
+            case CLOCK_TYPE_UNKNOWN:
                 return "Unknown";
-            case TYPE_GPS_TIME:
+            case CLOCK_TYPE_GPS_TIME:
                 return "GpsTime";
-            case TYPE_LOCAL_HW_TIME:
+            case CLOCK_TYPE_LOCAL_HW_TIME:
                 return "LocalHwClock";
             default:
                 return "<Invalid:" + mType + ">";
@@ -163,8 +171,8 @@
 
     /**
      * Gets the GPS receiver internal clock value in nanoseconds.
-     * This can be either the 'local hardware clock' value ({@link #TYPE_LOCAL_HW_TIME}), or the
-     * current GPS time derived inside GPS receiver ({@link #TYPE_GPS_TIME}).
+     * This can be either the 'local hardware clock' value ({@link #CLOCK_TYPE_LOCAL_HW_TIME}), or the
+     * current GPS time derived inside GPS receiver ({@link #CLOCK_TYPE_GPS_TIME}).
      * {@link #getType()} defines the time reported.
      *
      * For 'local hardware clock' this value is expected to be monotonically increasing during the
@@ -223,7 +231,7 @@
     }
 
     /**
-     * Returns true if {@link @getFullBiasInNs()} is available, false otherwise.
+     * Returns true if {@link #getFullBiasInNs()} is available, false otherwise.
      */
     public boolean hasFullBiasInNs() {
         return isFlagSet(HAS_FULL_BIAS);
@@ -233,7 +241,7 @@
      * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
      * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
      *
-     * This value is available if {@link #TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
+     * This value is available if {@link #CLOCK_TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
      * the clock for GPS time.
      * {@link #getBiasUncertaintyInNs()} should be used for quality check.
      *
@@ -387,6 +395,20 @@
     }
 
     /**
+     * Gets time of last hardware clock discontinuity.
+     */
+    public long getTimeOfLastHwClockDiscontinuityInNs() {
+        return mTimeOfLastHwClockDiscontinuityInNs;
+    }
+
+    /**
+     * Sets time of last hardware clock discontinuity.
+     */
+    public void setTimeOfLastHwClockDiscontinuityInNs(long timeOfLastHwClockDiscontinuityInNs) {
+        mTimeOfLastHwClockDiscontinuityInNs = timeOfLastHwClockDiscontinuityInNs;
+    }
+
+    /**
      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
      */
     public void resetDriftUncertaintyInNsPerSec() {
@@ -409,6 +431,7 @@
             gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
             gpsClock.mDriftInNsPerSec = parcel.readDouble();
             gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
+            gpsClock.mTimeOfLastHwClockDiscontinuityInNs = parcel.readLong();
 
             return gpsClock;
         }
@@ -430,6 +453,7 @@
         parcel.writeDouble(mBiasUncertaintyInNs);
         parcel.writeDouble(mDriftInNsPerSec);
         parcel.writeDouble(mDriftUncertaintyInNsPerSec);
+        parcel.writeLong(mTimeOfLastHwClockDiscontinuityInNs);
     }
 
     @Override
@@ -473,13 +497,17 @@
                 "DriftUncertaintyInNsPerSec",
                 hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
 
+        builder.append(String.format(format, "TimeOfLastHwClockDiscontinuityInNs",
+                getType() == CLOCK_TYPE_LOCAL_HW_TIME
+                        ? mTimeOfLastHwClockDiscontinuityInNs : null));
+
         return builder.toString();
     }
 
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
         resetLeapSecond();
-        setType(TYPE_UNKNOWN);
+        setType(CLOCK_TYPE_UNKNOWN);
         setTimeInNs(Long.MIN_VALUE);
         resetTimeUncertaintyInNs();
         resetFullBiasInNs();
@@ -487,6 +515,7 @@
         resetBiasUncertaintyInNs();
         resetDriftInNsPerSec();
         resetDriftUncertaintyInNsPerSec();
+        setTimeOfLastHwClockDiscontinuityInNs(Long.MIN_VALUE);
     }
 
     private void setFlag(short flag) {
diff --git a/location/java/android/location/GpsMeasurement.java b/location/java/android/location/GpsMeasurement.java
index f13a440..366ad61 100644
--- a/location/java/android/location/GpsMeasurement.java
+++ b/location/java/android/location/GpsMeasurement.java
@@ -16,17 +16,17 @@
 
 package android.location;
 
-import android.annotation.SystemApi;
+import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A class representing a GPS satellite measurement, containing raw and computed information.
- *
- * @hide
  */
-@SystemApi
-public class GpsMeasurement implements Parcelable {
+public final class GpsMeasurement implements Parcelable {
     private int mFlags;
     private byte mPrn;
     private double mTimeOffsetInNs;
@@ -59,6 +59,8 @@
     private double mAzimuthInDeg;
     private double mAzimuthUncertaintyInDeg;
     private boolean mUsedInFix;
+    private double mPseudorangeRateCarrierInMetersPerSec;
+    private double mPseudorangeRateCarrierUncertaintyInMetersPerSec;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
@@ -83,6 +85,11 @@
     private static final int HAS_USED_IN_FIX = (1<<17);
     private static final int GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
 
+    /** The status of 'loss of lock'. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({LOSS_OF_LOCK_UNKNOWN, LOSS_OF_LOCK_OK, LOSS_OF_LOCK_CYCLE_SLIP})
+    public @interface LossOfLockStatus {}
+
     /**
      * The indicator is not available or it is unknown.
      */
@@ -98,6 +105,12 @@
      */
     public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
 
+    /** The status of multipath. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED,
+        MULTIPATH_INDICATOR_NOT_USED})
+    public @interface MultipathIndicator {}
+
     /**
      * The indicator is not available or it is unknown.
      */
@@ -218,6 +231,10 @@
         mAzimuthInDeg = measurement.mAzimuthInDeg;
         mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
         mUsedInFix = measurement.mUsedInFix;
+        mPseudorangeRateCarrierInMetersPerSec =
+                measurement.mPseudorangeRateCarrierInMetersPerSec;
+        mPseudorangeRateCarrierUncertaintyInMetersPerSec =
+                measurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec;
     }
 
     /**
@@ -776,6 +793,7 @@
     /**
      * Gets a value indicating the 'loss of lock' state of the event.
      */
+    @LossOfLockStatus
     public byte getLossOfLock() {
         return mLossOfLock;
     }
@@ -783,7 +801,7 @@
     /**
      * Sets the 'loss of lock' status.
      */
-    public void setLossOfLock(byte value) {
+    public void setLossOfLock(@LossOfLockStatus byte value) {
         mLossOfLock = value;
     }
 
@@ -941,6 +959,7 @@
     /**
      * Gets a value indicating the 'multipath' state of the event.
      */
+    @MultipathIndicator
     public byte getMultipathIndicator() {
         return mMultipathIndicator;
     }
@@ -948,7 +967,7 @@
     /**
      * Sets the 'multi-path' indicator.
      */
-    public void setMultipathIndicator(byte value) {
+    public void setMultipathIndicator(@MultipathIndicator byte value) {
         mMultipathIndicator = value;
     }
 
@@ -1157,6 +1176,34 @@
         mUsedInFix = value;
     }
 
+    /**
+     * Gets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
+     */
+    public double getPseudorangeRateCarrierInMetersPerSec() {
+        return mPseudorangeRateCarrierInMetersPerSec;
+    }
+
+    /**
+     * Sets pseudorange rate (based on carrier phase changes) at the timestamp in m/s.
+     */
+    public void setPseudorangeRateCarrierInMetersPerSec(double value) {
+        mPseudorangeRateCarrierInMetersPerSec = value;
+    }
+
+    /**
+     * Gets 1-Sigma uncertainty of the pseudorange rate carrier.
+     */
+    public double getPseudorangeRateCarrierUncertaintyInMetersPerSec() {
+        return mPseudorangeRateCarrierUncertaintyInMetersPerSec;
+    }
+
+    /**
+     * Sets 1-Sigma uncertainty of the pseudorange rate carrier.
+     */
+    public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double value) {
+        mPseudorangeRateCarrierUncertaintyInMetersPerSec = value;
+    }
+
     public static final Creator<GpsMeasurement> CREATOR = new Creator<GpsMeasurement>() {
         @Override
         public GpsMeasurement createFromParcel(Parcel parcel) {
@@ -1194,6 +1241,8 @@
             gpsMeasurement.mAzimuthInDeg = parcel.readDouble();
             gpsMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
             gpsMeasurement.mUsedInFix = parcel.readInt() != 0;
+            gpsMeasurement.mPseudorangeRateCarrierInMetersPerSec = parcel.readDouble();
+            gpsMeasurement.mPseudorangeRateCarrierUncertaintyInMetersPerSec = parcel.readDouble();
 
             return gpsMeasurement;
         }
@@ -1237,6 +1286,8 @@
         parcel.writeDouble(mAzimuthInDeg);
         parcel.writeDouble(mAzimuthUncertaintyInDeg);
         parcel.writeInt(mUsedInFix ? 1 : 0);
+        parcel.writeDouble(mPseudorangeRateCarrierInMetersPerSec);
+        parcel.writeDouble(mPseudorangeRateCarrierUncertaintyInMetersPerSec);
     }
 
     @Override
@@ -1361,6 +1412,11 @@
 
         builder.append(String.format(format, "UsedInFix", mUsedInFix));
 
+        builder.append(String.format(format, "PseudorangeRateCarrierInMetersPerSec",
+                    mPseudorangeRateCarrierInMetersPerSec));
+        builder.append(String.format(format, "PseudorangeRateCarrierUncertaintyInMetersPerSec",
+                    mPseudorangeRateCarrierUncertaintyInMetersPerSec));
+
         return builder.toString();
     }
 
@@ -1397,6 +1453,8 @@
         resetAzimuthInDeg();
         resetAzimuthUncertaintyInDeg();
         setUsedInFix(false);
+        setPseudorangeRateCarrierInMetersPerSec(Double.MIN_VALUE);
+        setPseudorangeRateCarrierUncertaintyInMetersPerSec(Double.MIN_VALUE);
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GpsMeasurementListenerTransport.java b/location/java/android/location/GpsMeasurementCallbackTransport.java
similarity index 68%
rename from location/java/android/location/GpsMeasurementListenerTransport.java
rename to location/java/android/location/GpsMeasurementCallbackTransport.java
index 610da96..02d9026 100644
--- a/location/java/android/location/GpsMeasurementListenerTransport.java
+++ b/location/java/android/location/GpsMeasurementCallbackTransport.java
@@ -20,17 +20,17 @@
 import android.os.RemoteException;
 
 /**
- * A handler class to manage transport listeners for {@link GpsMeasurementsEvent.Listener}.
+ * A handler class to manage transport callbacks for {@link GpsMeasurementsEvent.Callback}.
  *
  * @hide
  */
-class GpsMeasurementListenerTransport
-        extends LocalListenerHelper<GpsMeasurementsEvent.Listener> {
+class GpsMeasurementCallbackTransport
+        extends LocalListenerHelper<GpsMeasurementsEvent.Callback> {
     private final ILocationManager mLocationManager;
 
     private final IGpsMeasurementsListener mListenerTransport = new ListenerTransport();
 
-    public GpsMeasurementListenerTransport(Context context, ILocationManager locationManager) {
+    public GpsMeasurementCallbackTransport(Context context, ILocationManager locationManager) {
         super(context, "GpsMeasurementListenerTransport");
         mLocationManager = locationManager;
     }
@@ -50,11 +50,11 @@
     private class ListenerTransport extends IGpsMeasurementsListener.Stub {
         @Override
         public void onGpsMeasurementsReceived(final GpsMeasurementsEvent event) {
-            ListenerOperation<GpsMeasurementsEvent.Listener> operation =
-                    new ListenerOperation<GpsMeasurementsEvent.Listener>() {
+            ListenerOperation<GpsMeasurementsEvent.Callback> operation =
+                    new ListenerOperation<GpsMeasurementsEvent.Callback>() {
                 @Override
-                public void execute(GpsMeasurementsEvent.Listener listener) throws RemoteException {
-                    listener.onGpsMeasurementsReceived(event);
+                public void execute(GpsMeasurementsEvent.Callback callback) throws RemoteException {
+                    callback.onGpsMeasurementsReceived(event);
                 }
             };
             foreach(operation);
@@ -62,11 +62,11 @@
 
         @Override
         public void onStatusChanged(final int status) {
-            ListenerOperation<GpsMeasurementsEvent.Listener> operation =
-                    new ListenerOperation<GpsMeasurementsEvent.Listener>() {
+            ListenerOperation<GpsMeasurementsEvent.Callback> operation =
+                    new ListenerOperation<GpsMeasurementsEvent.Callback>() {
                 @Override
-                public void execute(GpsMeasurementsEvent.Listener listener) throws RemoteException {
-                    listener.onStatusChanged(status);
+                public void execute(GpsMeasurementsEvent.Callback callback) throws RemoteException {
+                    callback.onStatusChanged(status);
                 }
             };
             foreach(operation);
diff --git a/location/java/android/location/GpsMeasurementsEvent.java b/location/java/android/location/GpsMeasurementsEvent.java
index 1366873..ef9edeb 100644
--- a/location/java/android/location/GpsMeasurementsEvent.java
+++ b/location/java/android/location/GpsMeasurementsEvent.java
@@ -16,11 +16,13 @@
 
 package android.location;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.security.InvalidParameterException;
 import java.util.Arrays;
 import java.util.Collection;
@@ -28,12 +30,13 @@
 
 /**
  * A class implementing a container for data associated with a measurement event.
- * Events are delivered to registered instances of {@link Listener}.
- *
- * @hide
+ * Events are delivered to registered instances of {@link Callback}.
  */
-@SystemApi
-public class GpsMeasurementsEvent implements Parcelable {
+public final class GpsMeasurementsEvent implements Parcelable {
+    /** The status of GPS measurements event. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    public @interface GpsMeasurementsStatus {}
 
     /**
      * The system does not support tracking of GPS Measurements. This status will not change in the
@@ -58,22 +61,20 @@
     /**
      * Used for receiving GPS satellite measurements from the GPS engine.
      * Each measurement contains raw and computed data identifying a satellite.
-     * You can implement this interface and call {@link LocationManager#addGpsMeasurementListener}.
-     *
-     * @hide
+     * You can implement this interface and call
+     * {@link LocationManager#registerGpsMeasurementCallback}.
      */
-    @SystemApi
-    public interface Listener {
+    public static abstract class Callback {
 
         /**
          * Returns the latest collected GPS Measurements.
          */
-        void onGpsMeasurementsReceived(GpsMeasurementsEvent eventArgs);
+        public void onGpsMeasurementsReceived(GpsMeasurementsEvent eventArgs) {}
 
         /**
          * Returns the latest status of the GPS Measurements sub-system.
          */
-        void onStatusChanged(int status);
+        public void onStatusChanged(@GpsMeasurementsStatus int status) {}
     }
 
     public GpsMeasurementsEvent(GpsClock clock, GpsMeasurement[] measurements) {
diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java
index 5c3c710..d799572 100644
--- a/location/java/android/location/GpsNavigationMessage.java
+++ b/location/java/android/location/GpsNavigationMessage.java
@@ -16,49 +16,54 @@
 
 package android.location;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.security.InvalidParameterException;
 
 /**
  * A class containing a GPS satellite Navigation Message.
- *
- * @hide
  */
-@SystemApi
-public class GpsNavigationMessage implements Parcelable {
+public final class GpsNavigationMessage implements Parcelable {
 
     private static final byte[] EMPTY_ARRAY = new byte[0];
 
+    /** The type of the GPS Clock. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_L1CA, MESSAGE_TYPE_L2CNAV, MESSAGE_TYPE_L5CNAV,
+            MESSAGE_TYPE_CNAV2})
+    public @interface GpsNavigationMessageType {}
+
     // The following enumerations must be in sync with the values declared in gps.h
 
     /**
      * The type of the navigation message is not available or unknown.
      */
-    public static final byte TYPE_UNKNOWN = 0;
+    public static final byte MESSAGE_TYPE_UNKNOWN = 0;
 
     /**
      * The Navigation Message is of type L1 C/A.
      */
-    public static final byte TYPE_L1CA = 1;
+    public static final byte MESSAGE_TYPE_L1CA = 1;
 
     /**
      * The Navigation Message is of type L1-CNAV.
      */
-    public static final byte TYPE_L2CNAV = 2;
+    public static final byte MESSAGE_TYPE_L2CNAV = 2;
 
     /**
      * The Navigation Message is of type L5-CNAV.
      */
-    public static final byte TYPE_L5CNAV = 3;
+    public static final byte MESSAGE_TYPE_L5CNAV = 3;
 
     /**
      * The Navigation Message is of type CNAV-2.
      */
-    public static final byte TYPE_CNAV2 = 4;
+    public static final byte MESSAGE_TYPE_CNAV2 = 4;
 
     /**
      * The Navigation Message Status is 'unknown'.
@@ -111,6 +116,7 @@
     /**
      * Gets the type of the navigation message contained in the object.
      */
+    @GpsNavigationMessageType
     public byte getType() {
         return mType;
     }
@@ -118,7 +124,7 @@
     /**
      * Sets the type of the navigation message.
      */
-    public void setType(byte value) {
+    public void setType(@GpsNavigationMessageType byte value) {
         mType = value;
     }
 
@@ -128,15 +134,15 @@
      */
     private String getTypeString() {
         switch (mType) {
-            case TYPE_UNKNOWN:
+            case MESSAGE_TYPE_UNKNOWN:
                 return "Unknown";
-            case TYPE_L1CA:
+            case MESSAGE_TYPE_L1CA:
                 return "L1 C/A";
-            case TYPE_L2CNAV:
+            case MESSAGE_TYPE_L2CNAV:
                 return "L2-CNAV";
-            case TYPE_L5CNAV:
+            case MESSAGE_TYPE_L5CNAV:
                 return "L5-CNAV";
-            case TYPE_CNAV2:
+            case MESSAGE_TYPE_CNAV2:
                 return "CNAV-2";
             default:
                 return "<Invalid:" + mType + ">";
@@ -314,7 +320,7 @@
     }
 
     private void initialize() {
-        mType = TYPE_UNKNOWN;
+        mType = MESSAGE_TYPE_UNKNOWN;
         mPrn = 0;
         mMessageId = -1;
         mSubmessageId = -1;
diff --git a/location/java/android/location/GpsNavigationMessageListenerTransport.java b/location/java/android/location/GpsNavigationMessageCallbackTransport.java
similarity index 73%
rename from location/java/android/location/GpsNavigationMessageListenerTransport.java
rename to location/java/android/location/GpsNavigationMessageCallbackTransport.java
index f6ba407..155d96d 100644
--- a/location/java/android/location/GpsNavigationMessageListenerTransport.java
+++ b/location/java/android/location/GpsNavigationMessageCallbackTransport.java
@@ -20,20 +20,20 @@
 import android.os.RemoteException;
 
 /**
- * A handler class to manage transport listeners for {@link GpsNavigationMessageEvent.Listener}.
+ * A handler class to manage transport callback for {@link GpsNavigationMessageEvent.Callback}.
  *
  * @hide
  */
-class GpsNavigationMessageListenerTransport
-        extends LocalListenerHelper<GpsNavigationMessageEvent.Listener> {
+class GpsNavigationMessageCallbackTransport
+        extends LocalListenerHelper<GpsNavigationMessageEvent.Callback> {
     private final ILocationManager mLocationManager;
 
     private final IGpsNavigationMessageListener mListenerTransport = new ListenerTransport();
 
-    public GpsNavigationMessageListenerTransport(
+    public GpsNavigationMessageCallbackTransport(
             Context context,
             ILocationManager locationManager) {
-        super(context, "GpsNavigationMessageListenerTransport");
+        super(context, "GpsNavigationMessageCallbackTransport");
         mLocationManager = locationManager;
     }
 
@@ -52,12 +52,12 @@
     private class ListenerTransport extends IGpsNavigationMessageListener.Stub {
         @Override
         public void onGpsNavigationMessageReceived(final GpsNavigationMessageEvent event) {
-            ListenerOperation<GpsNavigationMessageEvent.Listener> operation =
-                    new ListenerOperation<GpsNavigationMessageEvent.Listener>() {
+            ListenerOperation<GpsNavigationMessageEvent.Callback> operation =
+                    new ListenerOperation<GpsNavigationMessageEvent.Callback>() {
                 @Override
-                public void execute(GpsNavigationMessageEvent.Listener listener)
+                public void execute(GpsNavigationMessageEvent.Callback callback)
                         throws RemoteException {
-                    listener.onGpsNavigationMessageReceived(event);
+                    callback.onGpsNavigationMessageReceived(event);
                 }
             };
             foreach(operation);
@@ -65,12 +65,12 @@
 
         @Override
         public void onStatusChanged(final int status) {
-            ListenerOperation<GpsNavigationMessageEvent.Listener> operation =
-                    new ListenerOperation<GpsNavigationMessageEvent.Listener>() {
+            ListenerOperation<GpsNavigationMessageEvent.Callback> operation =
+                    new ListenerOperation<GpsNavigationMessageEvent.Callback>() {
                 @Override
-                public void execute(GpsNavigationMessageEvent.Listener listener)
+                public void execute(GpsNavigationMessageEvent.Callback callback)
                         throws RemoteException {
-                    listener.onStatusChanged(status);
+                    callback.onStatusChanged(status);
                 }
             };
             foreach(operation);
diff --git a/location/java/android/location/GpsNavigationMessageEvent.java b/location/java/android/location/GpsNavigationMessageEvent.java
index bd6921c..b16a485 100644
--- a/location/java/android/location/GpsNavigationMessageEvent.java
+++ b/location/java/android/location/GpsNavigationMessageEvent.java
@@ -16,60 +16,60 @@
 
 package android.location;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.security.InvalidParameterException;
 
 /**
  * A class implementing a container for data associated with a navigation message event.
- * Events are delivered to registered instances of {@link Listener}.
- *
- * @hide
+ * Events are delivered to registered instances of {@link Callback}.
  */
-@SystemApi
-public class GpsNavigationMessageEvent implements Parcelable {
+public final class GpsNavigationMessageEvent implements Parcelable {
+    /** The status of GPS measurements event. */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    public @interface GpsNavigationMessageStatus {}
 
     /**
      * The system does not support tracking of GPS Navigation Messages. This status will not change
      * in the future.
      */
-    public static int STATUS_NOT_SUPPORTED = 0;
+    public static final int STATUS_NOT_SUPPORTED = 0;
 
     /**
      * GPS Navigation Messages are successfully being tracked, it will receive updates once they are
      * available.
      */
-    public static int STATUS_READY = 1;
+    public static final int STATUS_READY = 1;
 
     /**
      * GPS provider or Location is disabled, updated will not be received until they are enabled.
      */
-    public static int STATUS_GPS_LOCATION_DISABLED = 2;
+    public static final int STATUS_GPS_LOCATION_DISABLED = 2;
 
     private final GpsNavigationMessage mNavigationMessage;
 
     /**
      * Used for receiving GPS satellite Navigation Messages from the GPS engine.
      * You can implement this interface and call
-     * {@link LocationManager#addGpsNavigationMessageListener}.
-     *
-     * @hide
+     * {@link LocationManager#registerGpsNavigationMessageCallback}.
      */
-    @SystemApi
-    public interface Listener {
+    public static abstract class Callback {
 
         /**
          * Returns the latest collected GPS Navigation Message.
          */
-        void onGpsNavigationMessageReceived(GpsNavigationMessageEvent event);
+        public void onGpsNavigationMessageReceived(GpsNavigationMessageEvent event) {}
 
         /**
          * Returns the latest status of the GPS Navigation Messages sub-system.
          */
-        void onStatusChanged(int status);
+        public void onStatusChanged(@GpsNavigationMessageStatus int status) {}
     }
 
     public GpsNavigationMessageEvent(GpsNavigationMessage message) {
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 323f326..8d2f781 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -34,17 +34,15 @@
     private final SparseArray<GpsSatellite> mSatellites = new SparseArray<>();
 
     private final class SatelliteIterator implements Iterator<GpsSatellite> {
-
-        private final SparseArray<GpsSatellite> mSatellites;
         private final int mSatellitesCount;
 
         private int mIndex = 0;
 
-        SatelliteIterator(SparseArray<GpsSatellite> satellites) {
-            mSatellites = satellites;
-            mSatellitesCount = satellites.size();
+        SatelliteIterator() {
+            mSatellitesCount = mSatellites.size();
         }
 
+        @Override
         public boolean hasNext() {
             for (; mIndex < mSatellitesCount; ++mIndex) {
                 GpsSatellite satellite = mSatellites.valueAt(mIndex);
@@ -55,6 +53,7 @@
             return false;
         }
 
+        @Override
         public GpsSatellite next() {
             while (mIndex < mSatellitesCount) {
                 GpsSatellite satellite = mSatellites.valueAt(mIndex);
@@ -66,14 +65,16 @@
             throw new NoSuchElementException();
         }
 
+        @Override
         public void remove() {
             throw new UnsupportedOperationException();
         }
     }
 
     private Iterable<GpsSatellite> mSatelliteList = new Iterable<GpsSatellite>() {
+        @Override
         public Iterator<GpsSatellite> iterator() {
-            return new SatelliteIterator(mSatellites);
+            return new SatelliteIterator();
         }
     };
 
@@ -137,18 +138,15 @@
     // For API-compat a public ctor() is not available
     GpsStatus() {}
 
-    /**
-     * Used internally within {@link LocationManager} to copy GPS status
-     * data from the Location Manager Service to its cached GpsStatus instance.
-     * Is synchronized to ensure that GPS status updates are atomic.
-     */
-    synchronized void setStatus(int svCount, int[] prns, float[] snrs,
-            float[] elevations, float[] azimuths, int ephemerisMask,
-            int almanacMask, int usedInFixMask) {
+    private void setStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations,
+            float[] azimuths, int[] constellationTypes) { 
         clearSatellites();
         for (int i = 0; i < svCount; i++) {
-            int prn = prns[i];
-            int prnShift = (1 << (prn - 1));
+            // Skip all non-GPS satellites.
+            if (constellationTypes[i] != GnssStatus.CONSTELLATION_GPS) {
+                continue;
+            }
+            int prn = prnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH;
             if (prn > 0 && prn <= NUM_SATELLITES) {
                 GpsSatellite satellite = mSatellites.get(prn);
                 if (satellite == null) {
@@ -160,53 +158,26 @@
                 satellite.mSnr = snrs[i];
                 satellite.mElevation = elevations[i];
                 satellite.mAzimuth = azimuths[i];
-                satellite.mHasEphemeris = ((ephemerisMask & prnShift) != 0);
-                satellite.mHasAlmanac = ((almanacMask & prnShift) != 0);
-                satellite.mUsedInFix = ((usedInFixMask & prnShift) != 0);
+                satellite.mHasEphemeris =
+                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+                satellite.mHasAlmanac =
+                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
+                satellite.mUsedInFix =
+                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0;
             }
         }
     }
 
     /**
-     * Used by {@link LocationManager#getGpsStatus} to copy LocationManager's
-     * cached GpsStatus instance to the client's copy.
+     * Copies GPS satellites information from GnssStatus object.
      * Since this method is only used within {@link LocationManager#getGpsStatus},
      * it does not need to be synchronized.
+     * @hide
      */
-    void setStatus(GpsStatus status) {
-        mTimeToFirstFix = status.getTimeToFirstFix();
-        clearSatellites();
-
-        SparseArray<GpsSatellite> otherSatellites = status.mSatellites;
-        int otherSatellitesCount = otherSatellites.size();
-        int satelliteIndex = 0;
-        // merge both sparse arrays, note that we have already invalidated the elements in the
-        // receiver array
-        for (int i = 0; i < otherSatellitesCount; ++i) {
-            GpsSatellite otherSatellite = otherSatellites.valueAt(i);
-            int otherSatellitePrn = otherSatellite.getPrn();
-
-            int satellitesCount = mSatellites.size();
-            while (satelliteIndex < satellitesCount
-                    && mSatellites.valueAt(satelliteIndex).getPrn() < otherSatellitePrn) {
-                ++satelliteIndex;
-            }
-
-            if (satelliteIndex < mSatellites.size()) {
-                GpsSatellite satellite = mSatellites.valueAt(satelliteIndex);
-                if (satellite.getPrn() == otherSatellitePrn) {
-                    satellite.setStatus(otherSatellite);
-                } else {
-                    satellite = new GpsSatellite(otherSatellitePrn);
-                    satellite.setStatus(otherSatellite);
-                    mSatellites.put(otherSatellitePrn, satellite);
-                }
-            } else {
-                GpsSatellite satellite = new GpsSatellite(otherSatellitePrn);
-                satellite.setStatus(otherSatellite);
-                mSatellites.append(otherSatellitePrn, satellite);
-            }
-        }
+    void setStatus(GnssStatus status, int timeToFirstFix) {
+        mTimeToFirstFix = timeToFirstFix;
+        setStatus(status.mSvCount, status.mPrnWithFlags, status.mSnrs, status.mElevations,
+                status.mAzimuths, status.mConstellationTypes);
     }
 
     void setTimeToFirstFix(int ttff) {
diff --git a/location/java/android/location/IGpsStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl
similarity index 73%
rename from location/java/android/location/IGpsStatusListener.aidl
rename to location/java/android/location/IGnssStatusListener.aidl
index 62b1c6b..d1c6a85 100644
--- a/location/java/android/location/IGpsStatusListener.aidl
+++ b/location/java/android/location/IGnssStatusListener.aidl
@@ -21,13 +21,12 @@
 /**
  * {@hide}
  */
-oneway interface IGpsStatusListener
+oneway interface IGnssStatusListener
 {
-    void onGpsStarted();
-    void onGpsStopped();
+    void onGnssStarted();
+    void onGnssStopped();
     void onFirstFix(int ttff);
-    void onSvStatusChanged(int svCount, in int[] prns, in float[] snrs, 
-            in float[] elevations, in float[] azimuths, 
-            int ephemerisMask, int almanacMask, int usedInFixMask);
+    void onSvStatusChanged(int svCount, in int[] prnWithFlags, in float[] snrs,
+            in float[] elevations, in float[] azimuths, in int[] constellationTypes);
     void onNmeaReceived(long timestamp, String nmea);
 }
diff --git a/location/java/android/location/IGpsStatusProvider.aidl b/location/java/android/location/IGnssStatusProvider.aidl
similarity index 70%
rename from location/java/android/location/IGpsStatusProvider.aidl
rename to location/java/android/location/IGnssStatusProvider.aidl
index cf277c8..006b5d3 100644
--- a/location/java/android/location/IGpsStatusProvider.aidl
+++ b/location/java/android/location/IGnssStatusProvider.aidl
@@ -16,14 +16,14 @@
 
 package android.location;
 
-import android.location.IGpsStatusListener;
+import android.location.IGnssStatusListener;
 
 /**
- * An interface for location providers that provide GPS status information.
+ * An interface for location providers that provide GNSS status information.
  *
  * {@hide}
  */
-interface IGpsStatusProvider {
-    void addGpsStatusListener(IGpsStatusListener listener);
-    void removeGpsStatusListener(IGpsStatusListener listener);
+interface IGnssStatusProvider {
+    void registerGnssStatusCallback(IGnssStatusListener callback);
+    void unregisterGnssStatusCallback(IGnssStatusListener callback);
 }
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index f3d755c..49d841f 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -21,9 +21,9 @@
 import android.location.Criteria;
 import android.location.GeocoderParams;
 import android.location.Geofence;
+import android.location.IGnssStatusListener;
 import android.location.IGpsMeasurementsListener;
 import android.location.IGpsNavigationMessageListener;
-import android.location.IGpsStatusListener;
 import android.location.ILocationListener;
 import android.location.Location;
 import android.location.LocationRequest;
@@ -48,8 +48,8 @@
 
     Location getLastLocation(in LocationRequest request, String packageName);
 
-    boolean addGpsStatusListener(IGpsStatusListener listener, String packageName);
-    void removeGpsStatusListener(IGpsStatusListener listener);
+    boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName);
+    void unregisterGnssStatusCallback(IGnssStatusListener callback);
 
     boolean geocoderIsPresent();
     String getFromLocation(double latitude, double longitude, int maxResults,
@@ -69,6 +69,8 @@
             in String packageName);
     void removeGpsNavigationMessageListener(in IGpsNavigationMessageListener listener);
 
+    int getGpsYearOfHardware();
+
     // --- deprecated ---
     List<String> getAllProviders();
     List<String> getProviders(in Criteria criteria, boolean enabledOnly);
diff --git a/location/java/android/location/LocalListenerHelper.java b/location/java/android/location/LocalListenerHelper.java
index 458c451..d7d2c513 100644
--- a/location/java/android/location/LocalListenerHelper.java
+++ b/location/java/android/location/LocalListenerHelper.java
@@ -20,12 +20,14 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * A base handler class to manage transport and local listeners.
@@ -33,7 +35,7 @@
  * @hide
  */
 abstract class LocalListenerHelper<TListener> {
-    private final HashSet<TListener> mListeners = new HashSet<>();
+    private final HashMap<TListener, Handler> mListeners = new HashMap<>();
 
     private final String mTag;
     private final Context mContext;
@@ -44,7 +46,7 @@
         mTag = name;
     }
 
-    public boolean add(@NonNull TListener listener) {
+    public boolean add(@NonNull TListener listener, Handler handler) {
         Preconditions.checkNotNull(listener);
         synchronized (mListeners) {
             // we need to register with the service first, because we need to find out if the
@@ -62,17 +64,19 @@
                     return false;
                 }
             }
-            if (mListeners.contains(listener)) {
+            if (mListeners.containsKey(listener)) {
                 return true;
             }
-            return mListeners.add(listener);
+            mListeners.put(listener, handler);
+            return true;
         }
     }
 
     public void remove(@NonNull TListener listener) {
         Preconditions.checkNotNull(listener);
         synchronized (mListeners) {
-            boolean removed = mListeners.remove(listener);
+            boolean removed = mListeners.containsKey(listener);
+            mListeners.remove(listener);
             boolean isLastRemoved = removed && mListeners.isEmpty();
             if (isLastRemoved) {
                 try {
@@ -95,17 +99,30 @@
         return mContext;
     }
 
-    protected void foreach(ListenerOperation<TListener> operation) {
-        Collection<TListener> listeners;
-        synchronized (mListeners) {
-            listeners = new ArrayList<>(mListeners);
+    private void executeOperation(ListenerOperation<TListener> operation, TListener listener) {
+        try {
+            operation.execute(listener);
+        } catch (RemoteException e) {
+            Log.e(mTag, "Error in monitored listener.", e);
+            // don't return, give a fair chance to all listeners to receive the event
         }
-        for (TListener listener : listeners) {
-            try {
-                operation.execute(listener);
-            } catch (RemoteException e) {
-                Log.e(mTag, "Error in monitored listener.", e);
-                // don't return, give a fair chance to all listeners to receive the event
+    }
+
+    protected void foreach(final ListenerOperation<TListener> operation) {
+        Collection<Map.Entry<TListener, Handler>> listeners;
+        synchronized (mListeners) {
+            listeners = new ArrayList<>(mListeners.entrySet());
+        }
+        for (final Map.Entry<TListener, Handler> listener : listeners) {
+            if (listener.getValue() == null) {
+                executeOperation(operation, listener.getKey());
+            } else {
+                listener.getValue().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        executeOperation(operation, listener.getKey());
+                    }
+                });
             }
         }
     }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 2c19324..5447bb1 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,6 +20,7 @@
 
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -63,13 +64,18 @@
 
     private final Context mContext;
     private final ILocationManager mService;
-    private final GpsMeasurementListenerTransport mGpsMeasurementListenerTransport;
-    private final GpsNavigationMessageListenerTransport mGpsNavigationMessageListenerTransport;
-    private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
-            new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
-    private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
-            new HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport>();
-    private final GpsStatus mGpsStatus = new GpsStatus();
+    private final GpsMeasurementCallbackTransport mGpsMeasurementCallbackTransport;
+    private final GpsNavigationMessageCallbackTransport mGpsNavigationMessageCallbackTransport;
+    private final HashMap<GpsStatus.Listener, GnssStatusListenerTransport> mGpsStatusListeners =
+            new HashMap<>();
+    private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners =
+            new HashMap<>();
+    private final HashMap<GnssStatusCallback, GnssStatusListenerTransport> mGnssStatusListeners =
+            new HashMap<>();
+    private final HashMap<GnssNmeaListener, GnssStatusListenerTransport> mGnssNmeaListeners =
+            new HashMap<>();
+    private GnssStatus mGnssStatus;
+    private int mTimeToFirstFix;
 
     /**
      * Name of the network location provider.
@@ -315,9 +321,9 @@
     public LocationManager(Context context, ILocationManager service) {
         mService = service;
         mContext = context;
-        mGpsMeasurementListenerTransport = new GpsMeasurementListenerTransport(mContext, mService);
-        mGpsNavigationMessageListenerTransport =
-                new GpsNavigationMessageListenerTransport(mContext, mService);
+        mGpsMeasurementCallbackTransport = new GpsMeasurementCallbackTransport(mContext, mService);
+        mGpsNavigationMessageCallbackTransport =
+                new GpsNavigationMessageCallbackTransport(mContext, mService);
     }
 
     private LocationProvider createProvider(String name, ProviderProperties properties) {
@@ -1389,11 +1395,51 @@
 
     // --- GPS-specific support ---
 
-    // This class is used to send GPS status events to the client's main thread.
-    private class GpsStatusListenerTransport extends IGpsStatusListener.Stub {
+    // This class is used to send Gnss status events to the client's specific thread.
+    private class GnssStatusListenerTransport extends IGnssStatusListener.Stub {
 
-        private final GpsStatus.Listener mListener;
-        private final GpsStatus.NmeaListener mNmeaListener;
+        private final GpsStatus.Listener mGpsListener;
+        private final GpsStatus.NmeaListener mGpsNmeaListener;
+        private final GnssStatusCallback mGnssCallback;
+        private final GnssNmeaListener mGnssNmeaListener;
+
+        private class GnssHandler extends Handler {
+            public GnssHandler(Handler handler) {
+                super(handler != null ? handler.getLooper() : Looper.myLooper());
+            }
+
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case NMEA_RECEIVED:
+                        synchronized (mNmeaBuffer) {
+                            int length = mNmeaBuffer.size();
+                            for (int i = 0; i < length; i++) {
+                                Nmea nmea = mNmeaBuffer.get(i);
+                                mGnssNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea);
+                            }
+                            mNmeaBuffer.clear();
+                        }
+                        break;
+                    case GpsStatus.GPS_EVENT_STARTED:
+                        mGnssCallback.onStarted();
+                        break;
+                    case GpsStatus.GPS_EVENT_STOPPED:
+                        mGnssCallback.onStopped();
+                        break;
+                    case GpsStatus.GPS_EVENT_FIRST_FIX:
+                        mGnssCallback.onFirstFix(mTimeToFirstFix);
+                        break;
+                    case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
+                        mGnssCallback.onSatelliteStatusChanged(mGnssStatus);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        private final Handler mGnssHandler;
 
         // This must not equal any of the GpsStatus event IDs
         private static final int NMEA_RECEIVED = 1000;
@@ -1407,97 +1453,141 @@
                 mNmea = nmea;
             }
         }
-        private ArrayList<Nmea> mNmeaBuffer;
+        private final ArrayList<Nmea> mNmeaBuffer;
 
-        GpsStatusListenerTransport(GpsStatus.Listener listener) {
-            mListener = listener;
-            mNmeaListener = null;
+        GnssStatusListenerTransport(GpsStatus.Listener listener) {
+            this(listener, null);
         }
 
-        GpsStatusListenerTransport(GpsStatus.NmeaListener listener) {
-            mNmeaListener = listener;
-            mListener = null;
+        GnssStatusListenerTransport(GpsStatus.Listener listener, Handler handler) {
+            mGpsListener = listener;
+            mGnssHandler = new GnssHandler(handler);
+            mGpsNmeaListener = null;
+            mNmeaBuffer = null;
+            mGnssCallback = new GnssStatusCallback() {
+                @Override
+                public void onStarted() {
+                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED);
+                }
+
+                @Override
+                public void onStopped() {
+                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STOPPED);
+                }
+
+                @Override
+                public void onFirstFix(int ttff) {
+                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_FIRST_FIX);
+                }
+
+                @Override
+                public void onSatelliteStatusChanged(GnssStatus status) {
+                    mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
+                }
+            };
+            mGnssNmeaListener = null;
+        }
+
+        GnssStatusListenerTransport(GpsStatus.NmeaListener listener) {
+            this(listener, null);
+        }
+
+        GnssStatusListenerTransport(GpsStatus.NmeaListener listener, Handler handler) {
+            mGpsListener = null;
+            mGnssHandler = new GnssHandler(handler);
+            mGpsNmeaListener = listener;
+            mNmeaBuffer = new ArrayList<Nmea>();
+            mGnssCallback = null;
+            mGnssNmeaListener = new GnssNmeaListener() {
+                @Override
+                public void onNmeaReceived(long timestamp, String nmea) {
+                    mGpsNmeaListener.onNmeaReceived(timestamp, nmea);
+                }
+            };
+        }
+
+        GnssStatusListenerTransport(GnssStatusCallback callback) {
+            this(callback, null);
+        }
+
+        GnssStatusListenerTransport(GnssStatusCallback callback, Handler handler) {
+            mGnssCallback = callback;
+            mGnssHandler = new GnssHandler(handler);
+            mGnssNmeaListener = null;
+            mNmeaBuffer = null;
+            mGpsListener = null;
+            mGpsNmeaListener = null;
+        }
+
+        GnssStatusListenerTransport(GnssNmeaListener listener) {
+            this(listener, null);
+        }
+
+        GnssStatusListenerTransport(GnssNmeaListener listener, Handler handler) {
+            mGnssCallback = null;
+            mGnssHandler = new GnssHandler(handler);
+            mGnssNmeaListener = listener;
+            mGpsListener = null;
+            mGpsNmeaListener = null;
             mNmeaBuffer = new ArrayList<Nmea>();
         }
 
         @Override
-        public void onGpsStarted() {
-            if (mListener != null) {
+        public void onGnssStarted() {
+            if (mGpsListener != null) {
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_STARTED;
-                mGpsHandler.sendMessage(msg);
+                mGnssHandler.sendMessage(msg);
             }
         }
 
         @Override
-        public void onGpsStopped() {
-            if (mListener != null) {
+        public void onGnssStopped() {
+            if (mGpsListener != null) {
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_STOPPED;
-                mGpsHandler.sendMessage(msg);
+                mGnssHandler.sendMessage(msg);
             }
         }
 
         @Override
         public void onFirstFix(int ttff) {
-            if (mListener != null) {
-                mGpsStatus.setTimeToFirstFix(ttff);
+            if (mGpsListener != null) {
+                mTimeToFirstFix = ttff;
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_FIRST_FIX;
-                mGpsHandler.sendMessage(msg);
+                mGnssHandler.sendMessage(msg);
             }
         }
 
         @Override
-        public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
-                float[] elevations, float[] azimuths, int ephemerisMask,
-                int almanacMask, int usedInFixMask) {
-            if (mListener != null) {
-                mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths,
-                        ephemerisMask, almanacMask, usedInFixMask);
+        public void onSvStatusChanged(int svCount, int[] prnWithFlags,
+                float[] snrs, float[] elevations, float[] azimuths, int[] constellationTypes) {
+            if (mGnssCallback != null) {
+                mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths,
+                        constellationTypes);
 
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
                 // remove any SV status messages already in the queue
-                mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
-                mGpsHandler.sendMessage(msg);
+                mGnssHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
+                mGnssHandler.sendMessage(msg);
             }
         }
 
         @Override
         public void onNmeaReceived(long timestamp, String nmea) {
-            if (mNmeaListener != null) {
+            if (mGnssNmeaListener != null) {
                 synchronized (mNmeaBuffer) {
                     mNmeaBuffer.add(new Nmea(timestamp, nmea));
                 }
                 Message msg = Message.obtain();
                 msg.what = NMEA_RECEIVED;
                 // remove any NMEA_RECEIVED messages already in the queue
-                mGpsHandler.removeMessages(NMEA_RECEIVED);
-                mGpsHandler.sendMessage(msg);
+                mGnssHandler.removeMessages(NMEA_RECEIVED);
+                mGnssHandler.sendMessage(msg);
             }
         }
-
-        private final Handler mGpsHandler = new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                if (msg.what == NMEA_RECEIVED) {
-                    synchronized (mNmeaBuffer) {
-                        int length = mNmeaBuffer.size();
-                        for (int i = 0; i < length; i++) {
-                            Nmea nmea = mNmeaBuffer.get(i);
-                            mNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea);
-                        }
-                        mNmeaBuffer.clear();
-                    }
-                } else {
-                    // synchronize on mGpsStatus to ensure the data is copied atomically.
-                    synchronized(mGpsStatus) {
-                        mListener.onGpsStatusChanged(msg.what);
-                    }
-                }
-            }
-        };
     }
 
     /**
@@ -1508,7 +1598,9 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     * @deprecated use {@link #registerGnssStatusCallback(GnssStatusCallback)} instead.
      */
+    @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean addGpsStatusListener(GpsStatus.Listener listener) {
         boolean result;
@@ -1518,8 +1610,8 @@
             return true;
         }
         try {
-            GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
-            result = mService.addGpsStatusListener(transport, mContext.getPackageName());
+            GnssStatusListenerTransport transport = new GnssStatusListenerTransport(listener);
+            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
             if (result) {
                 mGpsStatusListeners.put(listener, transport);
             }
@@ -1536,17 +1628,81 @@
      *
      * @param listener GPS status listener object to remove
      */
+    @Deprecated
     public void removeGpsStatusListener(GpsStatus.Listener listener) {
         try {
-            GpsStatusListenerTransport transport = mGpsStatusListeners.remove(listener);
+            GnssStatusListenerTransport transport = mGpsStatusListeners.remove(listener);
             if (transport != null) {
-                mService.removeGpsStatusListener(transport);
+                mService.unregisterGnssStatusCallback(transport);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
         }
     }
 
+
+    /**
+     * Registers a GNSS status listener.
+     *
+     * @param callback GNSS status listener object to register
+     *
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGnssStatusCallback(GnssStatusCallback callback) {
+        return registerGnssStatusCallback(callback, null);
+    }
+
+    /**
+     * Registers a GNSS status listener.
+     *
+     * @param callback GNSS status listener object to register
+     * @param handler the handler that the callback runs on.
+     *
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGnssStatusCallback(GnssStatusCallback callback, Handler handler) {
+        boolean result;
+        if (mGnssStatusListeners.get(callback) != null) {
+            // listener is already registered
+            return true;
+        }
+        try {
+            GnssStatusListenerTransport transport =
+                    new GnssStatusListenerTransport(callback, handler);
+            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
+            if (result) {
+                mGnssStatusListeners.put(callback, transport);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e);
+            result = false;
+        }
+
+        return result;
+    }
+
+    /**
+     * Removes a GNSS status listener.
+     *
+     * @param callback GNSS status listener object to remove
+     */
+    public void unregisterGnssStatusCallback(GnssStatusCallback callback) {
+        try {
+            GnssStatusListenerTransport transport = mGnssStatusListeners.remove(callback);
+            if (transport != null) {
+                mService.unregisterGnssStatusCallback(transport);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e);
+        }
+    }
+
     /**
      * Adds an NMEA listener.
      *
@@ -1555,20 +1711,22 @@
      * @return true if the listener was successfully added
      *
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+     * @deprecated use {@link #addNmeaListener(GnssNmeaListener)} instead.
      */
+    @Deprecated
     @RequiresPermission(ACCESS_FINE_LOCATION)
     public boolean addNmeaListener(GpsStatus.NmeaListener listener) {
         boolean result;
 
-        if (mNmeaListeners.get(listener) != null) {
+        if (mGpsNmeaListeners.get(listener) != null) {
             // listener is already registered
             return true;
         }
         try {
-            GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
-            result = mService.addGpsStatusListener(transport, mContext.getPackageName());
+            GnssStatusListenerTransport transport = new GnssStatusListenerTransport(listener);
+            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
             if (result) {
-                mNmeaListeners.put(listener, transport);
+                mGpsNmeaListeners.put(listener, transport);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
@@ -1583,11 +1741,12 @@
      *
      * @param listener a {@link GpsStatus.NmeaListener} object to remove
      */
+    @Deprecated
     public void removeNmeaListener(GpsStatus.NmeaListener listener) {
         try {
-            GpsStatusListenerTransport transport = mNmeaListeners.remove(listener);
+            GnssStatusListenerTransport transport = mGpsNmeaListeners.remove(listener);
             if (transport != null) {
-                mService.removeGpsStatusListener(transport);
+                mService.unregisterGnssStatusCallback(transport);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
@@ -1595,54 +1754,133 @@
     }
 
     /**
-     * Adds a GPS Measurement listener.
+     * Adds an NMEA listener.
      *
-     * @param listener a {@link GpsMeasurementsEvent.Listener} object to register.
-     * @return {@code true} if the listener was added successfully, {@code false} otherwise.
+     * @param listener a {@link GnssNmeaListener} object to register
      *
-     * @hide
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
-    @SystemApi
-    public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
-        return mGpsMeasurementListenerTransport.add(listener);
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean addNmeaListener(GnssNmeaListener listener) {
+        return addNmeaListener(listener, null);
     }
 
     /**
-     * Removes a GPS Measurement listener.
+     * Adds an NMEA listener.
      *
-     * @param listener a {@link GpsMeasurementsEvent.Listener} object to remove.
+     * @param listener a {@link GnssNmeaListener} object to register
+     * @param handler the handler that the listener runs on.
      *
-     * @hide
+     * @return true if the listener was successfully added
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
-    @SystemApi
-    public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
-        mGpsMeasurementListenerTransport.remove(listener);
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean addNmeaListener(GnssNmeaListener listener, Handler handler) {
+        boolean result;
+
+        if (mGpsNmeaListeners.get(listener) != null) {
+            // listener is already registered
+            return true;
+        }
+        try {
+            GnssStatusListenerTransport transport =
+                    new GnssStatusListenerTransport(listener, handler);
+            result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
+            if (result) {
+                mGnssNmeaListeners.put(listener, transport);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in registerGnssStatusCallback: ", e);
+            result = false;
+        }
+
+        return result;
     }
 
     /**
-     * Adds a GPS Navigation Message listener.
+     * Removes an NMEA listener.
      *
-     * @param listener a {@link GpsNavigationMessageEvent.Listener} object to register.
-     * @return {@code true} if the listener was added successfully, {@code false} otherwise.
-     *
-     * @hide
+     * @param listener a {@link GnssNmeaListener} object to remove
      */
-    @SystemApi
-    public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
-        return mGpsNavigationMessageListenerTransport.add(listener);
+    public void removeNmeaListener(GnssNmeaListener listener) {
+        try {
+            GnssStatusListenerTransport transport = mGnssNmeaListeners.remove(listener);
+            if (transport != null) {
+                mService.unregisterGnssStatusCallback(transport);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in unregisterGnssStatusCallback: ", e);
+        }
     }
 
     /**
-     * Removes a GPS Navigation Message listener.
+     * Registers a GPS Measurement callback.
      *
-     * @param listener a {@link GpsNavigationMessageEvent.Listener} object to remove.
-     *
-     * @hide
+     * @param callback a {@link GpsMeasurementsEvent.Callback} object to register.
+     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
-    @SystemApi
-    public void removeGpsNavigationMessageListener(
-            GpsNavigationMessageEvent.Listener listener) {
-        mGpsNavigationMessageListenerTransport.remove(listener);
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGpsMeasurementCallback(GpsMeasurementsEvent.Callback callback) {
+        return registerGpsMeasurementCallback(callback, null);
+    }
+
+    /**
+     * Registers a GPS Measurement callback.
+     *
+     * @param callback a {@link GpsMeasurementsEvent.Callback} object to register.
+     * @param handler the handler that the callback runs on.
+     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGpsMeasurementCallback(GpsMeasurementsEvent.Callback callback,
+            Handler handler) {
+        return mGpsMeasurementCallbackTransport.add(callback, handler);
+    }
+
+    /**
+     * Unregisters a GPS Measurement callback.
+     *
+     * @param callback a {@link GpsMeasurementsEvent.Callback} object to remove.
+     */
+    public void unregisterGpsMeasurementCallback(GpsMeasurementsEvent.Callback callback) {
+        mGpsMeasurementCallbackTransport.remove(callback);
+    }
+
+    /**
+     * Registers a GPS Navigation Message callback.
+     *
+     * @param callback a {@link GpsNavigationMessageEvent.Callback} object to register.
+     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     */
+    public boolean registerGpsNavigationMessageCallback(
+            GpsNavigationMessageEvent.Callback callback) {
+        return registerGpsNavigationMessageCallback(callback, null);
+    }
+
+    /**
+     * Registers a GPS Navigation Message callback.
+     *
+     * @param callback a {@link GpsNavigationMessageEvent.Callback} object to register.
+     * @param handler the handler that the callback runs on.
+     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     */
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public boolean registerGpsNavigationMessageCallback(
+            GpsNavigationMessageEvent.Callback callback, Handler handler) {
+        return mGpsNavigationMessageCallbackTransport.add(callback, handler);
+    }
+
+    /**
+     * Unregisters a GPS Navigation Message callback.
+     *
+     * @param callback a {@link GpsNavigationMessageEvent.Callback} object to remove.
+     */
+    public void unregisterGpsNavigationMessageCallback(
+            GpsNavigationMessageEvent.Callback callback) {
+        mGpsNavigationMessageCallbackTransport.remove(callback);
     }
 
      /**
@@ -1656,15 +1894,36 @@
      * @param status object containing GPS status details, or null.
      * @return status object containing updated GPS status.
      */
+    @Deprecated
+    @RequiresPermission(ACCESS_FINE_LOCATION)
     public GpsStatus getGpsStatus(GpsStatus status) {
         if (status == null) {
             status = new GpsStatus();
         }
-        status.setStatus(mGpsStatus);
+        // When mGnssStatus is null, that means that this method is called outside
+        // onGpsStatusChanged().  Return an empty status  to maintain backwards compatibility.
+        if (mGnssStatus != null) {
+            status.setStatus(mGnssStatus, mTimeToFirstFix);
+        }
         return status;
     }
 
     /**
+     * Returns the system information of the GPS hardware.
+     * May return 0 if GPS hardware is earlier than 2016.
+     * @hide
+     */
+    @TestApi
+    public int getGpsYearOfHardware() {
+        try {
+            return mService.getGpsYearOfHardware();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getGpsSystemInfo: ", e);
+            return 0;
+        }
+    }
+
+    /**
      * Sends additional commands to a location provider.
      * Can be used to support provider specific extensions to the Location Manager API
      *
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 260f380..93e86af 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -62,7 +62,7 @@
     public static final String NI_INTENT_KEY_TIMEOUT = "timeout";
     public static final String NI_INTENT_KEY_DEFAULT_RESPONSE = "default_resp";
 
-    // the extra command to send NI response to GpsLocationProvider
+    // the extra command to send NI response to GnssLocationProvider
     public static final String NI_RESPONSE_EXTRA_CMD = "send_ni_response";
 
     // the extra command parameter names in the Bundle
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index efae628..c194711 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -224,7 +224,6 @@
     public final static int FLAG_BYPASS_MUTE = 0x1 << 7;
 
     /**
-     * @hide
      * Flag requesting a low latency path.
      * When using this flag, the sample rate must match the native sample rate
      * of the device. Effects processing is also unavailable.
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index bde3d19..000a56d 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -251,6 +251,10 @@
      * @hide
      * */
     public static final int ENCODING_AAC_HE_V2 = 12;
+    /** Audio data format: compressed audio wrapped in PCM for HDMI
+     * or S/PDIF passthrough.
+     */
+    public static final int ENCODING_IEC61937 = 13;
 
     /** Invalid audio channel configuration */
     /** @deprecated Use {@link #CHANNEL_INVALID} instead.  */
@@ -418,6 +422,7 @@
         case ENCODING_PCM_8BIT:
             return 1;
         case ENCODING_PCM_16BIT:
+        case ENCODING_IEC61937:
         case ENCODING_DEFAULT:
             return 2;
         case ENCODING_PCM_FLOAT:
@@ -443,6 +448,7 @@
         case ENCODING_AAC_LC:
         case ENCODING_AAC_HE_V1:
         case ENCODING_AAC_HE_V2:
+        case ENCODING_IEC61937:
             return true;
         default:
             return false;
@@ -460,6 +466,7 @@
         case ENCODING_E_AC3:
         case ENCODING_DTS:
         case ENCODING_DTS_HD:
+        case ENCODING_IEC61937:
             return true;
         default:
             return false;
@@ -483,6 +490,7 @@
         case ENCODING_AAC_LC:
         case ENCODING_AAC_HE_V1:
         case ENCODING_AAC_HE_V2:
+        case ENCODING_IEC61937: // wrapped in PCM but compressed
             return false;
         case ENCODING_INVALID:
         default:
@@ -490,6 +498,30 @@
         }
     }
 
+    /** @hide */
+    public static boolean isEncodingLinearFrames(int audioFormat)
+    {
+        switch (audioFormat) {
+        case ENCODING_PCM_8BIT:
+        case ENCODING_PCM_16BIT:
+        case ENCODING_PCM_FLOAT:
+        case ENCODING_IEC61937: // same size as stereo PCM
+        case ENCODING_DEFAULT:
+            return true;
+        case ENCODING_AC3:
+        case ENCODING_E_AC3:
+        case ENCODING_DTS:
+        case ENCODING_DTS_HD:
+        case ENCODING_MP3:
+        case ENCODING_AAC_LC:
+        case ENCODING_AAC_HE_V1:
+        case ENCODING_AAC_HE_V2:
+            return false;
+        case ENCODING_INVALID:
+        default:
+            throw new IllegalArgumentException("Bad audio format " + audioFormat);
+        }
+    }
     /**
      * Returns an array of public encoding values extracted from an array of
      * encoding values.
@@ -715,6 +747,7 @@
                 case ENCODING_E_AC3:
                 case ENCODING_DTS:
                 case ENCODING_DTS_HD:
+                case ENCODING_IEC61937:
                     mEncoding = encoding;
                     break;
                 case ENCODING_INVALID:
@@ -859,7 +892,8 @@
         ENCODING_AC3,
         ENCODING_E_AC3,
         ENCODING_DTS,
-        ENCODING_DTS_HD
+        ENCODING_DTS_HD,
+        ENCODING_IEC61937
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Encoding {}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 7c21893..800b914 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -826,6 +826,33 @@
     }
 
     /**
+     * Poll for an {@link AudioTimestamp} on demand.
+     * <p>
+     * The AudioTimestamp reflects the frame delivery information at
+     * the earliest point available in the capture pipeline.
+     * <p>
+     * Calling {@link #startRecording()} following a {@link #stop()} will reset
+     * the frame count to 0.
+     *
+     * @param timestamp a reference to a non-null AudioTimestamp instance.
+     * @param timebase one of
+     *        {@link AudioTimestamp#TIMEBASE_BOOTTIME AudioTimestamp.TIMEBASE_BOOTTIME} or
+     *        {@link AudioTimestamp#TIMEBASE_MONOTONIC AudioTimestamp.TIMEBASE_MONOTONIC}.
+     * @return {@link #SUCCESS} if a timestamp is available,
+     *         or {@link #ERROR_INVALID_OPERATION} if a timestamp not available.
+     */
+     public int getTimestamp(@NonNull AudioTimestamp timestamp,
+             @AudioTimestamp.Timebase int timebase)
+     {
+         if (timestamp == null ||
+                 (timebase != AudioTimestamp.TIMEBASE_BOOTTIME
+                 && timebase != AudioTimestamp.TIMEBASE_MONOTONIC)) {
+             throw new IllegalArgumentException();
+         }
+         return native_get_timestamp(timestamp, timebase);
+     }
+
+    /**
      * Returns the minimum buffer size required for the successful creation of an AudioRecord
      * object, in byte units.
      * Note that this size doesn't guarantee a smooth recording under load, and higher values
@@ -1709,6 +1736,9 @@
     private native final void native_enableDeviceCallback();
     private native final void native_disableDeviceCallback();
 
+    private native final int native_get_timestamp(@NonNull AudioTimestamp timestamp,
+            @AudioTimestamp.Timebase int timebase);
+
     //---------------------------------------------------------
     // Utility methods
     //------------------
diff --git a/media/java/android/media/AudioRecordConfiguration.java b/media/java/android/media/AudioRecordConfiguration.java
index c7d219d..69df88f 100644
--- a/media/java/android/media/AudioRecordConfiguration.java
+++ b/media/java/android/media/AudioRecordConfiguration.java
@@ -23,7 +23,7 @@
 
 /**
  * The AudioRecordConfiguration class collects the information describing an audio recording
- * session. This information is returned through the 
+ * session. This information is returned through the
  * {@link AudioManager#getActiveRecordConfigurations()} method.
  *
  */
@@ -33,12 +33,32 @@
 
     private final int mClientSource;
 
+    private final AudioFormat mDeviceFormat;
+    private final AudioFormat mClientFormat;
+
+    private final AudioDeviceInfo mRecDevice;
+
     /**
      * @hide
      */
     public AudioRecordConfiguration(int session, int source) {
         mSessionId = session;
         mClientSource = source;
+        mDeviceFormat = new AudioFormat.Builder().build();
+        mClientFormat = new AudioFormat.Builder().build();
+        mRecDevice = null;
+    }
+
+    /**
+     * @hide
+     */
+    public AudioRecordConfiguration(int session, int source, AudioFormat devFormat,
+            AudioFormat clientFormat, AudioDeviceInfo device) {
+        mSessionId = session;
+        mClientSource = source;
+        mDeviceFormat = devFormat;
+        mClientFormat = clientFormat;
+        mRecDevice = device;
     }
 
     /**
@@ -57,7 +77,28 @@
      * Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
      * @return the session number.
      */
-    public int getAudioSessionId() { return mSessionId; }
+    public int getClientAudioSessionId() { return mSessionId; }
+
+    /**
+     * Returns the audio format at which audio is recorded on this Android device.
+     * Note that it may differ from the client application recording format
+     * (see {@link #getClientFormat()}).
+     * @return the device recording format
+     */
+    public AudioFormat getFormat() { return mDeviceFormat; }
+
+    /**
+     * Returns the audio format at which the client application is recording audio.
+     * Note that it may differ from the actual recording format (see {@link #getFormat()}).
+     * @return the recording format
+     */
+    public AudioFormat getClientFormat() { return mClientFormat; }
+
+    /**
+     * Returns the audio input device used for this recording.
+     * @return the audio recording device
+     */
+    public AudioDeviceInfo getAudioDevice() { return mRecDevice; }
 
     public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR
             = new Parcelable.Creator<AudioRecordConfiguration>() {
@@ -93,6 +134,9 @@
     private AudioRecordConfiguration(Parcel in) {
         mSessionId = in.readInt();
         mClientSource = in.readInt();
+        mDeviceFormat = new AudioFormat.Builder().build();
+        mClientFormat = new AudioFormat.Builder().build();
+        mRecDevice = null;
     }
 
     @Override
diff --git a/media/java/android/media/AudioTimestamp.java b/media/java/android/media/AudioTimestamp.java
index 965ba85..be8ca15 100644
--- a/media/java/android/media/AudioTimestamp.java
+++ b/media/java/android/media/AudioTimestamp.java
@@ -16,29 +16,74 @@
 
 package android.media;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import android.annotation.IntDef;
+
 /**
  * Structure that groups a position in frame units relative to an assumed audio stream,
- * together with the estimated time when that frame was presented or is committed to be
- * presented.
- * In the case of audio output, "present" means that audio produced on device
- * is detectable by an external observer off device.
+ * together with the estimated time when that frame enters or leaves the audio
+ * processing pipeline on that device. This can be used to coordinate events
+ * and interactions with the external environment.
+ * <p>
  * The time is based on the implementation's best effort, using whatever knowledge
  * is available to the system, but cannot account for any delay unknown to the implementation.
  *
- * @see AudioTrack#getTimestamp
+ * @see AudioTrack#getTimestamp AudioTrack.getTimestamp(AudioTimestamp)
+ * @see AudioRecord#getTimestamp AudioRecord.getTimestamp(AudioTimestamp, int)
  */
 public final class AudioTimestamp
 {
     /**
+     * Clock monotonic or its equivalent on the system,
+     * in the same units and timebase as {@link java.lang.System#nanoTime}.
+     */
+    public static final int TIMEBASE_MONOTONIC = 0;
+
+    /**
+     * Clock monotonic including suspend time or its equivalent on the system,
+     * in the same units and timebase as {@link android.os.SystemClock#elapsedRealtimeNanos}.
+     */
+    public static final int TIMEBASE_BOOTTIME = 1;
+
+    /** @hide */
+    @IntDef({
+        TIMEBASE_MONOTONIC,
+        TIMEBASE_BOOTTIME,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Timebase {}
+
+    /**
      * Position in frames relative to start of an assumed audio stream.
-     * The low-order 32 bits of position is in wrapping frame units similar to
-     * {@link AudioTrack#getPlaybackHeadPosition}.
+     * <p>
+     * When obtained through
+     * {@link AudioRecord#getTimestamp AudioRecord.getTimestamp(AudioTimestamp, int)},
+     * all 64 bits of position are valid.
+     * <p>
+     * When obtained through
+     * {@link AudioTrack#getTimestamp AudioTrack.getTimestamp(AudioTimestamp)},
+     * the low-order 32 bits of position is in wrapping frame units similar to
+     * {@link AudioTrack#getPlaybackHeadPosition AudioTrack.getPlaybackHeadPosition()}.
      */
     public long framePosition;
 
     /**
-     * The estimated time when frame was presented or is committed to be presented,
-     * in the same units and timebase as {@link java.lang.System#nanoTime}.
+     * Time associated with the frame in the audio pipeline.
+     * <p>
+     * When obtained through
+     * {@link AudioRecord#getTimestamp AudioRecord.getTimestamp(AudioTimestamp, int)},
+     * this is the estimated time in nanoseconds when the frame referred to by
+     * {@link #framePosition} was captured. The timebase is either
+     * {@link #TIMEBASE_MONOTONIC} or {@link #TIMEBASE_BOOTTIME}, depending
+     * on the timebase parameter used in
+     * {@link AudioRecord#getTimestamp AudioRecord.getTimestamp(AudioTimestamp, int)}.
+     * <p>
+     * When obtained through
+     * {@link AudioTrack#getTimestamp AudioTrack.getTimestamp(AudioTimestamp)},
+     * this is the estimated time when the frame was presented or is committed to be presented,
+     * with a timebase of {@link #TIMEBASE_MONOTONIC}.
      */
     public long nanoTime;
 }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 4319840..3007d86 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1100,7 +1100,6 @@
      * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
      *    {@link #ERROR_INVALID_OPERATION}
      *  @throws IllegalStateException
-     * @hide
      */
     public int setBufferSizeInFrames(int bufferSizeInFrames) {
         if (mDataLoadMode == MODE_STATIC || mState == STATE_UNINITIALIZED) {
@@ -1130,7 +1129,6 @@
      *  {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}.
      *  @return maximum size in frames of the <code>AudioTrack</code> buffer.
      *  @throws IllegalStateException
-     * @hide
      */
     public int getBufferCapacityInFrames() {
         return native_get_buffer_capacity_frames();
@@ -1204,7 +1202,6 @@
      * This is a continuously advancing counter. It can wrap around to zero
      * if there are too many underruns. If there were, for example, 68 underruns per
      * second then the counter would wrap in 2 years.
-     * @hide
      */
     public int getUnderrunCount() {
         return native_get_underrun_count();
diff --git a/media/java/android/media/DrmInitData.java b/media/java/android/media/DrmInitData.java
new file mode 100644
index 0000000..06fe6ff
--- /dev/null
+++ b/media/java/android/media/DrmInitData.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+import android.media.MediaDrm;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Encapsulates initialization data required by a {@link MediaDrm} instance.
+ */
+public abstract class DrmInitData {
+
+    /**
+     * Retrieves initialization data for a given DRM scheme, specified by its UUID.
+     *
+     * @param schemeUuid The DRM scheme's UUID.
+     * @return The initialization data for the scheme, or null if the scheme is not supported.
+     */
+    public abstract SchemeInitData get(UUID schemeUuid);
+
+    /**
+     * Scheme initialization data.
+     */
+    public static final class SchemeInitData {
+
+        /**
+         * The mimeType of {@link #data}.
+         */
+        public final String mimeType;
+        /**
+         * The initialization data.
+         */
+        public final byte[] data;
+
+        /**
+         * @param mimeType The mimeType of the initialization data.
+         * @param data The initialization data.
+         *
+         * @hide
+         */
+        public SchemeInitData(String mimeType, byte[] data) {
+            this.mimeType = mimeType;
+            this.data = data;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof SchemeInitData)) {
+                return false;
+            }
+            if (obj == this) {
+                return true;
+            }
+
+            SchemeInitData other = (SchemeInitData) obj;
+            return mimeType.equals(other.mimeType) && Arrays.equals(data, other.data);
+        }
+
+        @Override
+        public int hashCode() {
+            return mimeType.hashCode() + 31 * Arrays.hashCode(data);
+        }
+
+    }
+
+}
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 0fba992..d9690f0 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -460,6 +460,11 @@
         public static final String FEATURE_TunneledPlayback       = "tunneled-playback";
 
         /**
+         * <b>video encoder only</b>: codec supports intra refresh.
+         */
+        public static final String FEATURE_IntraRefresh = "intra-refresh";
+
+        /**
          * Query codec feature capabilities.
          * <p>
          * These features are supported to be used by the codec.  These
@@ -486,6 +491,10 @@
             new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
         };
 
+        private static final Feature[] encoderFeatures = {
+            new Feature(FEATURE_IntraRefresh, (1 << 0), false),
+        };
+
         /** @hide */
         public String[] validFeatures() {
             Feature[] features = getValidFeatures();
@@ -500,7 +509,7 @@
             if (!isEncoder()) {
                 return decoderFeatures;
             }
-            return new Feature[] {};
+            return encoderFeatures;
         }
 
         private boolean checkFeature(String name, int flags) {
@@ -1726,7 +1735,7 @@
         }
 
         private void applyLevelLimits() {
-            int maxBlocksPerSecond = 0;
+            long maxBlocksPerSecond = 0;
             int maxBlocks = 0;
             int maxBps = 0;
             int maxDPBBlocks = 0;
@@ -2052,11 +2061,11 @@
                         16 /* blockWidth */, 16 /* blockHeight */,
                         1 /* widthAlignment */, 1 /* heightAlignment */);
                 mFrameRateRange = Range.create(1, maxRate);
-            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ||
-                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
-                maxBlocks = maxBlocksPerSecond = Integer.MAX_VALUE;
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8)) {
+                maxBlocks = Integer.MAX_VALUE;
+                maxBlocksPerSecond = Integer.MAX_VALUE;
 
-                // TODO: set to 100Mbps for now, need a number for VPX
+                // TODO: set to 100Mbps for now, need a number for VP8
                 maxBps = 100000000;
 
                 // profile levels are not indicative for VPx, but verify
@@ -2084,11 +2093,80 @@
                     errors &= ~ERROR_NONE_SUPPORTED;
                 }
 
-                final int blockSize =
-                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ? 16 : 8;
+                final int blockSize = 16;
                 applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
                         maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
                         1 /* widthAlignment */, 1 /* heightAlignment */);
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) {
+                maxBlocksPerSecond = 829440;
+                maxBlocks = 36864;
+                maxBps = 200000;
+
+                for (CodecProfileLevel profileLevel: profileLevels) {
+                    long SR = 0;
+                    int FS = 0;
+                    int BR = 0;
+                    switch (profileLevel.level) {
+                        case CodecProfileLevel.VP9Level1:
+                            SR =      829440; FS =    36864; BR =    200; break;
+                        case CodecProfileLevel.VP9Level11:
+                            SR =     2764800; FS =    73728; BR =    800; break;
+                        case CodecProfileLevel.VP9Level2:
+                            SR =     4608000; FS =   122880; BR =   1800; break;
+                        case CodecProfileLevel.VP9Level21:
+                            SR =     9216000; FS =   245760; BR =   3600; break;
+                        case CodecProfileLevel.VP9Level3:
+                            SR =    20736000; FS =   552960; BR =   7200; break;
+                        case CodecProfileLevel.VP9Level31:
+                            SR =    36864000; FS =   983040; BR =  12000; break;
+                        case CodecProfileLevel.VP9Level4:
+                            SR =    83558400; FS =  2228224; BR =  18000; break;
+                        case CodecProfileLevel.VP9Level41:
+                            SR =   160432128; FS =  2228224; BR =  30000; break;
+                        case CodecProfileLevel.VP9Level5:
+                            SR =   311951360; FS =  8912896; BR =  60000; break;
+                        case CodecProfileLevel.VP9Level51:
+                            SR =   588251136; FS =  8912896; BR = 120000; break;
+                        case CodecProfileLevel.VP9Level52:
+                            SR =  1176502272; FS =  8912896; BR = 180000; break;
+                        case CodecProfileLevel.VP9Level6:
+                            SR =  1176502272; FS = 35651584; BR = 180000; break;
+                        case CodecProfileLevel.VP9Level61:
+                            SR = 2353004544L; FS = 35651584; BR = 240000; break;
+                        case CodecProfileLevel.VP9Level62:
+                            SR = 4706009088L; FS = 35651584; BR = 480000; break;
+                        default:
+                            Log.w(TAG, "Unrecognized level "
+                                    + profileLevel.level + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    switch (profileLevel.profile) {
+                        case CodecProfileLevel.VP9Profile0:
+                        case CodecProfileLevel.VP9Profile1:
+                        case CodecProfileLevel.VP9Profile2:
+                        case CodecProfileLevel.VP9Profile3:
+                            break;
+                        default:
+                            Log.w(TAG, "Unrecognized profile "
+                                    + profileLevel.profile + " for " + mime);
+                            errors |= ERROR_UNRECOGNIZED;
+                    }
+                    errors &= ~ERROR_NONE_SUPPORTED;
+                    maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond);
+                    maxBlocks = Math.max(FS, maxBlocks);
+                    maxBps = Math.max(BR * 1000, maxBps);
+                }
+
+                final int blockSize = 8;
+                int maxLengthInBlocks = Utils.divUp(maxBlocks, blockSize);
+                maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize);
+                maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize);
+
+                applyMacroBlockLimits(
+                        maxLengthInBlocks, maxLengthInBlocks,
+                        maxBlocks, maxBlocksPerSecond,
+                        blockSize, blockSize,
+                        1 /* widthAlignment */, 1 /* heightAlignment */);
             } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
                 maxBlocks = 36864;
                 maxBlocksPerSecond = maxBlocks * 15;
@@ -2531,6 +2609,28 @@
         // from OMX_VIDEO_VP8PROFILETYPE
         public static final int VP8ProfileMain = 0x01;
 
+        // from OMX_VIDEO_VP9PROFILETYPE
+        public static final int VP9Profile0 = 0x00;
+        public static final int VP9Profile1 = 0x01;
+        public static final int VP9Profile2 = 0x02;
+        public static final int VP9Profile3 = 0x03;
+
+        // from OMX_VIDEO_VP9LEVELTYPE
+        public static final int VP9Level1  = 0x0;
+        public static final int VP9Level11 = 0x1;
+        public static final int VP9Level2  = 0x2;
+        public static final int VP9Level21 = 0x4;
+        public static final int VP9Level3  = 0x8;
+        public static final int VP9Level31 = 0x10;
+        public static final int VP9Level4  = 0x20;
+        public static final int VP9Level41 = 0x40;
+        public static final int VP9Level5  = 0x80;
+        public static final int VP9Level51 = 0x100;
+        public static final int VP9Level52 = 0x200;
+        public static final int VP9Level6  = 0x400;
+        public static final int VP9Level61 = 0x800;
+        public static final int VP9Level62 = 0x1000;
+
         // from OMX_VIDEO_HEVCPROFILETYPE
         public static final int HEVCProfileMain   = 0x01;
         public static final int HEVCProfileMain10 = 0x02;
@@ -2563,17 +2663,40 @@
         public static final int HEVCMainTierLevel62 = 0x1000000;
         public static final int HEVCHighTierLevel62 = 0x2000000;
 
+        // from OMX_VIDEO_DOLBYVISIONPROFILETYPE
+        public static final int DolbyVisionProfileDvavDer = 0x1;
+        public static final int DolbyVisionProfileDvavDen = 0x2;
+        public static final int DolbyVisionProfileDvheDer = 0x3;
+        public static final int DolbyVisionProfileDvheDen = 0x4;
+        public static final int DolbyVisionProfileDvheDtr = 0x5;
+        public static final int DolbyVisionProfileDvheStn = 0x6;
+
+        // from OMX_VIDEO_DOLBYVISIONLEVELTYPE
+        public static final int DolbyVisionLevelHd24    = 0x1;
+        public static final int DolbyVisionLevelHd30    = 0x2;
+        public static final int DolbyVisionLevelFhd24   = 0x4;
+        public static final int DolbyVisionLevelFhd30   = 0x8;
+        public static final int DolbyVisionLevelFhd60   = 0x10;
+        public static final int DolbyVisionLevelUhd24   = 0x20;
+        public static final int DolbyVisionLevelUhd30   = 0x40;
+        public static final int DolbyVisionLevelUhd48   = 0x80;
+        public static final int DolbyVisionLevelUhd60   = 0x100;
+
         /**
          * Defined in the OpenMAX IL specs, depending on the type of media
          * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
-         * OMX_VIDEO_MPEG4PROFILETYPE or OMX_VIDEO_VP8PROFILETYPE.
+         * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE.
          */
         public int profile;
 
         /**
          * Defined in the OpenMAX IL specs, depending on the type of media
          * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE
-         * OMX_VIDEO_MPEG4LEVELTYPE or OMX_VIDEO_VP8LEVELTYPE.
+         * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE.
+         *
+         * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may
+         * not advertise a profile level support. For those VP9 decoders, please use
+         * {@link VideoCapabilities} to determine the codec capabilities.
          */
         public int level;
     };
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 0bf995f..b339925 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -34,7 +34,9 @@
 import java.lang.annotation.RetentionPolicy;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
@@ -226,6 +228,46 @@
     public native final int getTrackCount();
 
     /**
+     * Extract DRM initialization data if it exists
+     *
+     * @return DRM initialization data in the content, or {@code null}
+     * if no recognizable DRM format is found;
+     * @see DrmInitData
+     */
+    public DrmInitData getDrmInitData() {
+        Map<String, Object> formatMap = getFileFormatNative();
+        if (formatMap == null) {
+            return null;
+        }
+        if (formatMap.containsKey("pssh")) {
+            Map<UUID, byte[]> psshMap = getPsshInfo();
+            final Map<UUID, DrmInitData.SchemeInitData> initDataMap =
+                new HashMap<UUID, DrmInitData.SchemeInitData>();
+            for (Map.Entry<UUID, byte[]> e: psshMap.entrySet()) {
+                UUID uuid = e.getKey();
+                byte[] data = e.getValue();
+                initDataMap.put(uuid, new DrmInitData.SchemeInitData("cenc", data));
+            }
+            return new DrmInitData() {
+                public SchemeInitData get(UUID schemeUuid) {
+                    return initDataMap.get(schemeUuid);
+                }
+            };
+        } else if (formatMap.containsKey("crypto-key")) {
+            ByteBuffer buf = (ByteBuffer) formatMap.get("crypto-key");
+            buf.rewind();
+            final byte[] data = new byte[buf.remaining()];
+            buf.get(data);
+            return new DrmInitData() {
+                public SchemeInitData get(UUID schemeUuid) {
+                    return new DrmInitData.SchemeInitData("webm", data);
+                }
+            };
+        }
+        return null;
+    }
+
+    /**
      * Get the PSSH info if present.
      * @return a map of uuid-to-bytes, with the uuid specifying
      * the crypto scheme, and the bytes being the data specific to that scheme.
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index abdf220..d06da97 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -44,7 +44,8 @@
  *         for encoders, readable in the output format of decoders</b></td></tr>
  * <tr><td>{@link #KEY_FRAME_RATE}</td><td>Integer or Float</td><td><b>encoder-only</b></td></tr>
  * <tr><td>{@link #KEY_CAPTURE_RATE}</td><td>Integer</td><td></td></tr>
-* <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
  * <tr><td>{@link #KEY_MAX_WIDTH}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution width</td></tr>
  * <tr><td>{@link #KEY_MAX_HEIGHT}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution height</td></tr>
  * <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>video encoder in surface-mode only</b></td></tr>
@@ -218,6 +219,20 @@
     public static final String KEY_I_FRAME_INTERVAL = "i-frame-interval";
 
     /**
+    * An optional key describing the period of intra refresh in frames. This is an
+    * optional parameter that applies only to video encoders. If encoder supports it
+    * ({@link MediaCodecInfo.CodecCapabilities#FEATURE_IntraRefresh}), the whole
+    * frame is completely refreshed after the specified period. Also for each frame,
+    * a fix subset of macroblocks must be intra coded which leads to more constant bitrate
+    * than inserting a key frame. This key is recommended for video streaming applications
+    * as it provides low-delay and good error-resilience. This key is ignored if the
+    * video encoder does not support the intra refresh feature. Use the output format to
+    * verify that this feature was enabled.
+    * The associated value is an integer.
+    */
+    public static final String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
+
+   /**
      * A key describing the temporal layering schema.  This is an optional parameter
      * that applies only to video encoders.  Use {@link MediaCodec#getInputFormat}
      * after {@link MediaCodec#configure configure} to query if the encoder supports
@@ -548,6 +563,66 @@
     /** @hide */
     public static final String KEY_IS_TIMED_TEXT = "is-timed-text";
 
+    // The following color aspect values must be in sync with the ones in HardwareAPI.h.
+    /*
+     * An optional key describing the color primaries, white point and
+     * luminance factors for video content.
+     *
+     * The associated value is an integer: 0 if unspecified, or one of the
+     * COLOR_STANDARD_ values.
+     */
+    public static final String KEY_COLOR_STANDARD = "color-standard";
+
+    /** BT.709 color chromacity coordinates with KR = 0.2126, KB = 0.0722. */
+    public static final int COLOR_STANDARD_BT709 = 1;
+
+    /** BT.601 625 color chromacity coordinates with KR = 0.299, KB = 0.114. */
+    public static final int COLOR_STANDARD_BT601_PAL = 2;
+
+    /** BT.601 525 color chromacity coordinates with KR = 0.299, KB = 0.114. */
+    public static final int COLOR_STANDARD_BT601_NTSC = 4;
+
+    /** BT.2020 color chromacity coordinates with KR = 0.2627, KB = 0.0593. */
+    public static final int COLOR_STANDARD_BT2020 = 6;
+
+    /**
+     * An optional key describing the opto-electronic transfer function used
+     * for the video content.
+     *
+     * The associated value is an integer: 0 if unspecified, or one of the
+     * COLOR_TRANSFER_ values.
+     */
+    public static final String KEY_COLOR_TRANSFER = "color-transfer";
+
+    /** Linear transfer characteristic curve. */
+    public static final int COLOR_TRANSFER_LINEAR = 1;
+
+    /** SMPTE 170M transfer characteristic curve used by BT.601/BT.709/BT.2020. This is the curve
+     *  used by most non-HDR video content. */
+    public static final int COLOR_TRANSFER_SDR_VIDEO = 3;
+
+    /** SMPTE ST 2084 transfer function. This is used by some HDR video content. */
+    public static final int COLOR_TRANSFER_ST2084 = 6;
+
+    /** ARIB STD-B67 hybrid-log-gamma transfer function. This is used by some HDR video content. */
+    public static final int COLOR_TRANSFER_HLG = 7;
+
+    /**
+     * An optional key describing the range of the component values of the video content.
+     *
+     * The associated value is an integer: 0 if unspecified, or one of the
+     * COLOR_RANGE_ values.
+     */
+    public static final String KEY_COLOR_RANGE = "color-range";
+
+    /** Limited range. Y component values range from 16 to 235 for 8-bit content.
+     *  Cr, Cy values range from 16 to 240 for 8-bit content.
+     *  This is the default for video content. */
+    public static final int COLOR_RANGE_LIMITED = 2;
+
+    /** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */
+    public static final int COLOR_RANGE_FULL = 1;
+
     /* package private */ MediaFormat(Map<String, Object> map) {
         mMap = map;
     }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 9517387..f09f654 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -822,7 +822,6 @@
      *
      * @throws IllegalStateException if it is called before start() or after
      * stop()
-     * {@hide}
      */
     public native void pause() throws IllegalStateException;
 
@@ -833,7 +832,6 @@
      * @throws IllegalStateException if it is called before start() or after
      * stop()
      * @see android.media.MediaRecorder#pause
-     * {@hide}
      */
     public native void resume() throws IllegalStateException;
 
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index 2cd3c43..35b083e 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -174,7 +174,7 @@
         return (num + den - 1) / den;
     }
 
-    private static long divUp(long num, long den) {
+    static long divUp(long num, long den) {
         return (num + den - 1) / den;
     }
 
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 02b03d2..b9fcba2 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.media.AudioAttributes;
 import android.os.Parcel;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -48,14 +49,27 @@
 
     /**
      * A rule requiring the usage information of the {@link AudioAttributes} to match.
+     * This mixing rule can be added with {@link Builder#addRule(AudioAttributes, int)} or
+     * {@link Builder#addMixRule(int, Object)} where the Object parameter is an instance of
+     * {@link AudioAttributes}.
      */
     @SystemApi
     public static final int RULE_MATCH_ATTRIBUTE_USAGE = 0x1;
     /**
      * A rule requiring the capture preset information of the {@link AudioAttributes} to match.
+     * This mixing rule can be added with {@link Builder#addRule(AudioAttributes, int)} or
+     * {@link Builder#addMixRule(int, Object)} where the Object parameter is an instance of
+     * {@link AudioAttributes}.
      */
     @SystemApi
     public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 0x1 << 1;
+    /**
+     * A rule requiring the UID of the audio stream to match that specified.
+     * This mixing rule can be added with {@link Builder#addMixRule(int, Object)} where the Object
+     * parameter is an instance of {@link java.lang.Integer}.
+     */
+    @SystemApi
+    public static final int RULE_MATCH_UID = 0x1 << 2;
 
     private final static int RULE_EXCLUSION_MASK = 0x8000;
     /**
@@ -70,29 +84,53 @@
      */
     public static final int RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET =
             RULE_EXCLUSION_MASK | RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET;
+    /**
+     * @hide
+     * A rule requiring the UID information to differ.
+     */
+    public static final int RULE_EXCLUDE_UID =
+            RULE_EXCLUSION_MASK | RULE_MATCH_UID;
 
     static final class AttributeMatchCriterion {
-        AudioAttributes mAttr;
-        int mRule;
+        final AudioAttributes mAttr;
+        final Integer mIntProp;
+        final int mRule;
 
         /** input parameters must be valid */
         AttributeMatchCriterion(AudioAttributes attributes, int rule) {
             mAttr = attributes;
+            mIntProp = null;
+            mRule = rule;
+        }
+        /** input parameters must be valid */
+        AttributeMatchCriterion(Integer intProp, int rule) {
+            mAttr = null;
+            mIntProp = intProp;
             mRule = rule;
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(mAttr, mRule);
+            return Objects.hash(mAttr, mIntProp, mRule);
         }
 
         void writeToParcel(Parcel dest) {
             dest.writeInt(mRule);
-            if ((mRule == RULE_MATCH_ATTRIBUTE_USAGE) || (mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) {
+            final int match_rule = mRule & ~RULE_EXCLUSION_MASK;
+            switch (match_rule) {
+            case RULE_MATCH_ATTRIBUTE_USAGE:
                 dest.writeInt(mAttr.getUsage());
-            } else {
-                // capture preset rule
+                break;
+            case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
                 dest.writeInt(mAttr.getCapturePreset());
+                break;
+            case RULE_MATCH_UID:
+                dest.writeInt(mIntProp.intValue());
+                break;
+            default:
+                Log.e("AttributeMatchCriterion", "Unknown match rule" + match_rule
+                        + " when writing to Parcel");
+                dest.writeInt(-1);
             }
         }
     }
@@ -111,18 +149,31 @@
         switch(rule) {
             case RULE_MATCH_ATTRIBUTE_USAGE:
             case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+            case RULE_MATCH_UID:
                 return true;
             default:
                 return false;
         }
     }
 
-    private static boolean isValidIntRule(int rule) {
+    private static boolean isValidAttributesSystemApiRule(int rule) {
+        switch(rule) {
+            case RULE_MATCH_ATTRIBUTE_USAGE:
+            case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private static boolean isValidRule(int rule) {
         switch(rule) {
             case RULE_MATCH_ATTRIBUTE_USAGE:
             case RULE_EXCLUDE_ATTRIBUTE_USAGE:
             case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
             case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
+            case RULE_MATCH_UID:
+            case RULE_EXCLUDE_UID:
                 return true;
             default:
                 return false;
@@ -130,8 +181,24 @@
     }
 
     private static boolean isPlayerRule(int rule) {
-        return ((rule == RULE_MATCH_ATTRIBUTE_USAGE)
-                || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE));
+        final int match_rule = rule & ~RULE_EXCLUSION_MASK;
+        switch (match_rule) {
+        case RULE_MATCH_ATTRIBUTE_USAGE:
+        case RULE_MATCH_UID:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    private static boolean isAudioAttributeRule(int match_rule) {
+        switch(match_rule) {
+            case RULE_MATCH_ATTRIBUTE_USAGE:
+            case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+                return true;
+            default:
+                return false;
+        }
     }
 
     /**
@@ -158,14 +225,15 @@
          *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}.
          * @return the same Builder instance.
          * @throws IllegalArgumentException
+         * @see {@link #excludeRule(AudioAttributes, int)}
          */
         @SystemApi
         public Builder addRule(AudioAttributes attrToMatch, int rule)
                 throws IllegalArgumentException {
-            if (!isValidSystemApiRule(rule)) {
+            if (!isValidAttributesSystemApiRule(rule)) {
                 throw new IllegalArgumentException("Illegal rule value " + rule);
             }
-            return addRuleInt(attrToMatch, rule);
+            return checkAddRuleObjInternal(rule, attrToMatch);
         }
 
         /**
@@ -186,33 +254,82 @@
          *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}.
          * @return the same Builder instance.
          * @throws IllegalArgumentException
+         * @see {@link #addRule(AudioAttributes, int)}
          */
         @SystemApi
         public Builder excludeRule(AudioAttributes attrToMatch, int rule)
                 throws IllegalArgumentException {
+            if (!isValidAttributesSystemApiRule(rule)) {
+                throw new IllegalArgumentException("Illegal rule value " + rule);
+            }
+            return checkAddRuleObjInternal(rule | RULE_EXCLUSION_MASK, attrToMatch);
+        }
+
+        /**
+         * Add a rule for the selection of which streams are mixed together.
+         * The rule defines what the matching will be made on. It also determines the type of the
+         * property to match against.
+         * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE},
+         *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or
+         *     {@link AudioMixingRule#RULE_MATCH_UID}.
+         * @param property see the definition of each rule for the type to use (either an
+         *     {@link AudioAttributes} or an {@link java.lang.Integer}).
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         * @see {@link #excludeMixRule(int, Object)}
+         */
+        @SystemApi
+        public Builder addMixRule(int rule, Object property) throws IllegalArgumentException {
             if (!isValidSystemApiRule(rule)) {
                 throw new IllegalArgumentException("Illegal rule value " + rule);
             }
-            return addRuleInt(attrToMatch, rule | RULE_EXCLUSION_MASK);
+            return checkAddRuleObjInternal(rule, property);
+        }
+
+        /**
+         * Add a rule by exclusion for the selection of which streams are mixed together.
+         * <br>For instance the following code
+         * <br><pre>
+         * AudioAttributes mediaAttr = new AudioAttributes.Builder()
+         *         .setUsage(AudioAttributes.USAGE_MEDIA)
+         *         .build();
+         * AudioMixingRule noMediaRule = new AudioMixingRule.Builder()
+         *         .addMixRule(AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE, mediaAttr)
+         *         .excludeMixRule(AudioMixingRule.RULE_MATCH_UID, new Integer(uidToExclude)
+         *         .build();
+         * </pre>
+         * <br>will create a rule which maps to usage USAGE_MEDIA, but excludes any stream
+         * coming from the specified UID.
+         * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE},
+         *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or
+         *     {@link AudioMixingRule#RULE_MATCH_UID}.
+         * @param property see the definition of each rule for the type to use (either an
+         *     {@link AudioAttributes} or an {@link java.lang.Integer}).
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        @SystemApi
+        public Builder excludeMixRule(int rule, Object property) throws IllegalArgumentException {
+            if (!isValidSystemApiRule(rule)) {
+                throw new IllegalArgumentException("Illegal rule value " + rule);
+            }
+            return checkAddRuleObjInternal(rule | RULE_EXCLUSION_MASK, property);
         }
 
         /**
          * Add or exclude a rule for the selection of which streams are mixed together.
-         * @param attrToMatch a non-null AudioAttributes instance for which a contradictory
-         *     rule hasn't been set yet.
-         * @param rule one of {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_USAGE},
-         *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE},
-         *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or
-         *     {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}.
+         * Does error checking on the parameters.
+         * @param rule
+         * @param property
          * @return the same Builder instance.
          * @throws IllegalArgumentException
          */
-        Builder addRuleInt(AudioAttributes attrToMatch, int rule)
+        private Builder checkAddRuleObjInternal(int rule, Object property)
                 throws IllegalArgumentException {
-            if (attrToMatch == null) {
-                throw new IllegalArgumentException("Illegal null AudioAttributes argument");
+            if (property == null) {
+                throw new IllegalArgumentException("Illegal null Object argument");
             }
-            if (!isValidIntRule(rule)) {
+            if (!isValidRule(rule)) {
                 throw new IllegalArgumentException("Illegal rule value " + rule);
             } else {
                 // as rules are added to the Builder, we verify they are consistent with the type
@@ -229,36 +346,87 @@
                     throw new IllegalArgumentException("Incompatible rule for mix");
                 }
             }
+            final int match_rule = rule & ~RULE_EXCLUSION_MASK;
+            if (isAudioAttributeRule(match_rule)) {
+                if (!(property instanceof AudioAttributes)) {
+                    throw new IllegalArgumentException("Invalid AudioAttributes argument");
+                }
+                return addRuleInternal((AudioAttributes) property, null, rule);
+            } else {
+                // implies integer match rule
+                if (!(property instanceof Integer)) {
+                    throw new IllegalArgumentException("Invalid Integer argument");
+                }
+                return addRuleInternal(null, (Integer) property, rule);
+            }
+        }
+
+        /**
+         * Add or exclude a rule on AudioAttributes or integer property for the selection of which
+         * streams are mixed together.
+         * No rule-to-parameter type check, all done in {@link #checkAddRuleObjInternal(int, Object)}.
+         * Exceptions are thrown only when incompatible rules are added.
+         * @param attrToMatch a non-null AudioAttributes instance for which a contradictory
+         *     rule hasn't been set yet, null if not used.
+         * @param intProp an integer property to match or exclude, null if not used.
+         * @param rule one of {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_USAGE},
+         *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE},
+         *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or
+         *     {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET},
+         *     {@link AudioMixingRule#RULE_MATCH_UID}, {@link AudioMixingRule#RULE_EXCLUDE_UID}.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException
+         */
+        private Builder addRuleInternal(AudioAttributes attrToMatch, Integer intProp, int rule)
+                throws IllegalArgumentException {
             synchronized (mCriteria) {
                 Iterator<AttributeMatchCriterion> crIterator = mCriteria.iterator();
+                final int match_rule = rule & ~RULE_EXCLUSION_MASK;
                 while (crIterator.hasNext()) {
                     final AttributeMatchCriterion criterion = crIterator.next();
-                    if ((rule == RULE_MATCH_ATTRIBUTE_USAGE)
-                            || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) {
-                        // "usage"-based rule
-                        if (criterion.mAttr.getUsage() == attrToMatch.getUsage()) {
-                            if (criterion.mRule == rule) {
-                                // rule already exists, we're done
-                                return this;
-                            } else {
-                                // criterion already exists with a another rule, it is incompatible
-                                throw new IllegalArgumentException("Contradictory rule exists for "
-                                        + attrToMatch);
+                    switch (match_rule) {
+                        case RULE_MATCH_ATTRIBUTE_USAGE:
+                            // "usage"-based rule
+                            if (criterion.mAttr.getUsage() == attrToMatch.getUsage()) {
+                                if (criterion.mRule == rule) {
+                                    // rule already exists, we're done
+                                    return this;
+                                } else {
+                                    // criterion already exists with a another rule,
+                                    // it is incompatible
+                                    throw new IllegalArgumentException("Contradictory rule exists"
+                                            + " for " + attrToMatch);
+                                }
                             }
-                        }
-                    } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET)
-                            || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) {
-                        // "capture preset"-base rule
-                        if (criterion.mAttr.getCapturePreset() == attrToMatch.getCapturePreset()) {
-                            if (criterion.mRule == rule) {
-                             // rule already exists, we're done
-                                return this;
-                            } else {
-                                // criterion already exists with a another rule, it is incompatible
-                                throw new IllegalArgumentException("Contradictory rule exists for "
-                                        + attrToMatch);
+                            break;
+                        case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+                            // "capture preset"-base rule
+                            if (criterion.mAttr.getCapturePreset() == attrToMatch.getCapturePreset()) {
+                                if (criterion.mRule == rule) {
+                                    // rule already exists, we're done
+                                    return this;
+                                } else {
+                                    // criterion already exists with a another rule,
+                                    // it is incompatible
+                                    throw new IllegalArgumentException("Contradictory rule exists"
+                                            + " for " + attrToMatch);
+                                }
                             }
-                        }
+                            break;
+                        case RULE_MATCH_UID:
+                            // "usage"-based rule
+                            if (criterion.mIntProp.intValue() == intProp.intValue()) {
+                                if (criterion.mRule == rule) {
+                                    // rule already exists, we're done
+                                    return this;
+                                } else {
+                                    // criterion already exists with a another rule,
+                                    // it is incompatible
+                                    throw new IllegalArgumentException("Contradictory rule exists"
+                                            + " for UID " + intProp);
+                                }
+                            }
+                            break;
                     }
                 }
                 // rule didn't exist, add it
@@ -268,22 +436,30 @@
         }
 
         Builder addRuleFromParcel(Parcel in) throws IllegalArgumentException {
-            int rule = in.readInt();
-            AudioAttributes attr;
-            if ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) {
-                int usage = in.readInt();
-                attr = new AudioAttributes.Builder()
-                        .setUsage(usage).build();
-            } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET)
-                    || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) {
-                int preset = in.readInt();
-                attr = new AudioAttributes.Builder()
-                        .setInternalCapturePreset(preset).build();
-            } else {
-                in.readInt(); // assume there was in int value to read as for now they come in pair
-                throw new IllegalArgumentException("Illegal rule value " + rule + " in parcel");
+            final int rule = in.readInt();
+            final int match_rule = rule & ~RULE_EXCLUSION_MASK;
+            AudioAttributes attr = null;
+            Integer intProp = null;
+            switch (match_rule) {
+                case RULE_MATCH_ATTRIBUTE_USAGE:
+                    int usage = in.readInt();
+                    attr = new AudioAttributes.Builder()
+                            .setUsage(usage).build();
+                    break;
+                case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+                    int preset = in.readInt();
+                    attr = new AudioAttributes.Builder()
+                            .setInternalCapturePreset(preset).build();
+                    break;
+                case RULE_MATCH_UID:
+                    intProp = new Integer(in.readInt());
+                    break;
+                default:
+                    // assume there was in int value to read as for now they come in pair
+                    in.readInt();
+                    throw new IllegalArgumentException("Illegal rule value " + rule + " in parcel");
             }
-            return addRuleInt(attr, rule);
+            return addRuleInternal(attr, intProp, rule);
         }
 
         /**
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 252f5f4..5ad6126 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -169,6 +169,14 @@
                         textDump += "  match capture preset ";
                         textDump += criterion.mAttr.getCapturePreset();
                         break;
+                    case AudioMixingRule.RULE_MATCH_UID:
+                        textDump += "  match UID ";
+                        textDump += criterion.mIntProp.toString();
+                        break;
+                    case AudioMixingRule.RULE_EXCLUDE_UID:
+                        textDump += "  exclude UID ";
+                        textDump += criterion.mIntProp.toString();
+                        break;
                     default:
                         textDump += "invalid rule!";
                 }
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 869512d..93e6dac 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -473,8 +473,9 @@
         // the service will be told when we connect.
         if (mState == CONNECT_STATE_CONNECTED) {
             try {
-                // NOTE: In order not to break the behavior of the support library, call
-                // addSubscription instead of addSubscriptionWithOptions when the options are null.
+                // NOTE: Do not call addSubscriptionWithOptions when options are null. Otherwise,
+                // it will break the action of support library which expects addSubscription will
+                // be called when options are null.
                 if (options == null) {
                     mServiceBinder.addSubscription(parentId, mServiceCallbacks);
                 } else {
@@ -500,9 +501,9 @@
         // Tell the service if necessary.
         if (sub != null && sub.remove(options) && mState == CONNECT_STATE_CONNECTED) {
             try {
-                // NOTE: In order not to break the behavior of the support library, call
-                // removeSubscription instead of removeSubscriptionWithOptions when the options
-                // are null.
+                // NOTE: Do not call removeSubscriptionWithOptions when options are null. Otherwise,
+                // it will break the action of support library which expects removeSubscription will
+                // be called when options are null.
                 if (options == null) {
                     mServiceBinder.removeSubscription(parentId, mServiceCallbacks);
                 } else {
@@ -572,9 +573,9 @@
                     Subscription sub = subscriptionEntry.getValue();
                     for (Bundle options : sub.getOptionsList()) {
                         try {
-                            // NOTE: In order not to break the behavior of the support library,
-                            // call addSubscription instead of addSubscriptionWithOptions when
-                            // the options are null.
+                            // NOTE: Do not call addSubscriptionWithOptions when options are null.
+                            // Otherwise, it will break the action of support library which expects
+                            // addSubscription will be called when options are null.
                             if (options == null) {
                                 mServiceBinder.addSubscription(id, mServiceCallbacks);
                             } else {
@@ -1034,7 +1035,7 @@
          * are the initial data as requested.
          */
         @Override
-        public void onConnect(final String root, final MediaSession.Token session,
+        public void onConnect(String root, MediaSession.Token session,
                 final Bundle extras) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
@@ -1054,7 +1055,12 @@
         }
 
         @Override
-        public void onLoadChildren(final String parentId, final ParceledListSlice list,
+        public void onLoadChildren(String parentId, ParceledListSlice list) {
+            onLoadChildrenWithOptions(parentId, list, null);
+        }
+
+        @Override
+        public void onLoadChildrenWithOptions(String parentId, ParceledListSlice list,
                 final Bundle options) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index b1a51a56..3d9b60d 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -605,6 +605,7 @@
         /**
          * Request that the player start playback for a specific media id.
          *
+         * @see PlaybackState#EXTRA_PREPARE_ONLY
          * @param mediaId The id of the requested media.
          * @param extras Optional extras that can include extra information about the media item
          *               to be played.
@@ -626,6 +627,7 @@
          * An empty or null query should be treated as a request to play any
          * music.
          *
+         * @see PlaybackState#EXTRA_PREPARE_ONLY
          * @param query The search query.
          * @param extras Optional extras that can include extra information
          *            about the query.
@@ -646,6 +648,7 @@
         /**
          * Request that the player start playback for a specific {@link Uri}.
          *
+         * @see PlaybackState#EXTRA_PREPARE_ONLY
          * @param uri  The URI of the requested media.
          * @param extras Optional extras that can include extra information about the media item
          *               to be played.
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e1e9b79..8c5b19c 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -87,6 +87,12 @@
     public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
 
     /**
+     * Set this flag on the session to indicate that it can handle
+     * the {@link PlaybackState#EXTRA_PREPARE_ONLY} field.
+     */
+    public static final int FLAG_HANDLES_PREPARE_ONLY = 1 << 2;
+
+    /**
      * System only flag for a session that needs to have priority over all other
      * sessions. This flag ensures this session will receive media button events
      * regardless of the current ordering in the system.
@@ -100,6 +106,7 @@
     @IntDef(flag = true, value = {
             FLAG_HANDLES_MEDIA_BUTTONS,
             FLAG_HANDLES_TRANSPORT_CONTROLS,
+            FLAG_HANDLES_PREPARE_ONLY,
             FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
     public @interface SessionFlags { }
 
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index bbe04b5..1079a1f 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -133,6 +133,21 @@
     public static final long ACTION_PLAY_FROM_URI = 1 << 13;
 
     /**
+     * Used as an optional boolean extra field in
+     * {@link MediaController.TransportControls#playFromMediaId},
+     * {@link MediaController.TransportControls#playFromSearch}, and
+     * {@link MediaController.TransportControls#playFromUri}. Value of {@code true} overrides
+     * the default behavior of starting the playback after preparing. Check
+     * {@link MediaSession#FLAG_HANDLES_PREPARE_ONLY} to see if the media session supports this.
+     *
+     * @see MediaSession#FLAG_HANDLES_PREPARE_ONLY
+     * @see MediaController.TransportControls#playFromMediaId
+     * @see MediaController.TransportControls#playFromSearch
+     * @see MediaController.TransportControls#playFromUri
+     */
+    public static final String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
+
+    /**
      * This is the default playback state and indicates that no media has been
      * added yet, or the performer has been reset and has no content to play.
      *
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
new file mode 100644
index 0000000..707db06
--- /dev/null
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -0,0 +1,184 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.soundtrigger;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.os.Handler;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.io.PrintWriter;
+import java.util.UUID;
+
+/**
+ * A class that allows interaction with the actual sound trigger detection on the system.
+ * Sound trigger detection refers to a detectors that match generic sound patterns that are
+ * not voice-based. The voice-based recognition models should utilize the {@link
+ * VoiceInteractionService} instead. Access to this class is protected by a permission
+ * granted only to system or privileged apps.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoundTriggerDetector {
+    private static final boolean DBG = false;
+    private static final String TAG = "SoundTriggerDetector";
+
+    private final Object mLock = new Object();
+
+    private final ISoundTriggerService mSoundTriggerService;
+    private final UUID mSoundModelId;
+    private final Callback mCallback;
+    private final Handler mHandler;
+    private final RecognitionCallback mRecognitionCallback;
+
+    public abstract class Callback {
+        /**
+         * Called when the availability of the sound model changes.
+         */
+        public abstract void onAvailabilityChanged(int status);
+
+        /**
+         * Called when the sound model has triggered (such as when it matched a
+         * given sound pattern).
+         */
+        public abstract void onDetected();
+
+        /**
+         *  Called when the detection fails due to an error.
+         */
+        public abstract void onError();
+
+        /**
+         * Called when the recognition is paused temporarily for some reason.
+         * This is an informational callback, and the clients shouldn't be doing anything here
+         * except showing an indication on their UI if they have to.
+         */
+        public abstract void onRecognitionPaused();
+
+        /**
+         * Called when the recognition is resumed after it was temporarily paused.
+         * This is an informational callback, and the clients shouldn't be doing anything here
+         * except showing an indication on their UI if they have to.
+         */
+        public abstract void onRecognitionResumed();
+    }
+
+    /**
+     * This class should be constructed by the {@link SoundTriggerManager}.
+     * @hide
+     */
+    SoundTriggerDetector(ISoundTriggerService soundTriggerService, UUID soundModelId,
+            @NonNull Callback callback, @Nullable Handler handler) {
+        mSoundTriggerService = soundTriggerService;
+        mSoundModelId = soundModelId;
+        mCallback = callback;
+        if (handler == null) {
+            mHandler = new Handler();
+        } else {
+            mHandler = handler;
+        }
+        mRecognitionCallback = new RecognitionCallback();
+    }
+
+    /**
+     * Starts recognition on the associated sound model. Result is indicated via the
+     * {@link Callback}.
+     * @return Indicates whether the call succeeded or not.
+     */
+    public boolean startRecognition() {
+        if (DBG) {
+            Slog.d(TAG, "startRecognition()");
+        }
+        try {
+            mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
+                    mRecognitionCallback);
+        } catch (RemoteException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Stops recognition for the associated model.
+     */
+    public boolean stopRecognition() {
+        try {
+            mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
+                    mRecognitionCallback);
+        } catch (RemoteException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @hide
+     */
+    public void dump(String prefix, PrintWriter pw) {
+        synchronized (mLock) {
+            // TODO: Dump useful debug information.
+        }
+    }
+
+    /**
+     * Callback that handles events from the lower sound trigger layer.
+     * @hide
+     */
+    private static class RecognitionCallback extends
+            IRecognitionStatusCallback.Stub {
+
+        /**
+         * @hide
+         */
+        @Override
+        public void onDetected(SoundTrigger.RecognitionEvent event) {
+            Slog.e(TAG, "onDetected()" + event);
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public void onError(int status) {
+            Slog.e(TAG, "onError()" + status);
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public void onRecognitionPaused() {
+            Slog.e(TAG, "onRecognitionPaused()");
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public void onRecognitionResumed() {
+            Slog.e(TAG, "onRecognitionResumed()");
+        }
+    }
+}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
new file mode 100644
index 0000000..4fd3310
--- /dev/null
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.soundtrigger;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.os.Handler;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+/**
+ * This class provides management of non-voice (general sound trigger) based sound recognition
+ * models. Usage of this class is restricted to system or signature applications only. This allows
+ * OEMs to write apps that can manage non-voice based sound trigger models.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoundTriggerManager {
+    private static final boolean DBG = false;
+    private static final String TAG = "SoundTriggerManager";
+
+    private final Context mContext;
+    private final ISoundTriggerService mSoundTriggerService;
+
+    // Stores a mapping from the sound model UUID to the SoundTriggerInstance created by
+    // the createSoundTriggerDetector() call.
+    private final HashMap<UUID, SoundTriggerDetector> mReceiverInstanceMap;
+
+    /**
+     * @hide
+     */
+    public SoundTriggerManager(Context context, ISoundTriggerService soundTriggerService ) {
+        if (DBG) {
+            Slog.i(TAG, "SoundTriggerManager created.");
+        }
+        mSoundTriggerService = soundTriggerService;
+        mContext = context;
+        mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>();
+    }
+
+    /**
+     * Updates the given sound trigger model.
+     */
+    public void updateModel(Model model) {
+        try {
+            mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Returns the sound trigger model represented by the given UUID. An instance of {@link Model}
+     * is returned.
+     */
+    public Model getModel(UUID soundModelId) {
+        try {
+            return new Model(mSoundTriggerService.getSoundModel(
+                    new ParcelUuid(soundModelId)));
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Deletes the sound model represented by the provided UUID.
+     */
+    public void deleteModel(UUID soundModelId) {
+        try {
+            mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Creates an instance of {@link SoundTriggerDetector} which can be used to start/stop
+     * recognition on the model and register for triggers from the model. Note that this call
+     * invalidates any previously returned instances for the same sound model Uuid.
+     *
+     * @param soundModelId UUID of the sound model to create the receiver object for.
+     * @param callback Instance of the {@link SoundTriggerDetector#Callback} object for the
+     * callbacks for the given sound model.
+     * @param handler The Handler to use for the callback operations. A null value will use the
+     * current thread's Looper.
+     * @return Instance of {@link SoundTriggerDetector} or null on error.
+     */
+    @Nullable
+    public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
+            @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
+        if (soundModelId == null) {
+            return null;
+        }
+
+        SoundTriggerDetector oldInstance = mReceiverInstanceMap.get(soundModelId);
+        if (oldInstance != null) {
+            // Shutdown old instance.
+        }
+        SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerService,
+                soundModelId, callback, handler);
+        mReceiverInstanceMap.put(soundModelId, newInstance);
+        return newInstance;
+    }
+
+    /**
+     * Class captures the data and fields that represent a non-keyphrase sound model. Use the
+     * factory constructor {@link Model#create()} to create an instance.
+     */
+    // We use encapsulation to expose the SoundTrigger.GenericSoundModel as a SystemApi. This
+    // prevents us from exposing SoundTrigger.GenericSoundModel as an Api.
+    public static class Model {
+
+        private SoundTrigger.GenericSoundModel mGenericSoundModel;
+
+        /**
+         * @hide
+         */
+        Model(SoundTrigger.GenericSoundModel soundTriggerModel) {
+            mGenericSoundModel = soundTriggerModel;
+        }
+
+        /**
+         * Factory constructor to create a SoundModel instance for use with methods in this
+         * class.
+         */
+        public static Model create(UUID modelUuid, UUID vendorUuid, byte[] data) {
+            return new Model(new SoundTrigger.GenericSoundModel(modelUuid,
+                        vendorUuid, data));
+        }
+
+        public UUID getModelUuid() {
+            return mGenericSoundModel.uuid;
+        }
+
+        public UUID getVendorUuid() {
+            return mGenericSoundModel.vendorUuid;
+        }
+
+        public byte[] getModelData() {
+            return mGenericSoundModel.data;
+        }
+
+        /**
+         * @hide
+         */
+        SoundTrigger.GenericSoundModel getGenericSoundModel() {
+            return mGenericSoundModel;
+        }
+    }
+}
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 0febc16..d189333 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -41,6 +41,7 @@
 interface ITvInputManager {
     List<TvInputInfo> getTvInputList(int userId);
     TvInputInfo getTvInputInfo(in String inputId, int userId);
+    void setTvInputInfo(in TvInputInfo inputInfo, int userId);
     int getTvInputState(in String inputId, int userId);
 
     List<TvContentRatingSystemInfo> getTvContentRatingSystemList(int userId);
diff --git a/media/java/android/media/tv/ITvInputManagerCallback.aidl b/media/java/android/media/tv/ITvInputManagerCallback.aidl
index 3bf415b..395c9f3 100644
--- a/media/java/android/media/tv/ITvInputManagerCallback.aidl
+++ b/media/java/android/media/tv/ITvInputManagerCallback.aidl
@@ -29,5 +29,5 @@
 
     void onInputStateChanged(in String inputId, int state);
 
-    void onTvInputInfoChanged(in String inputId, in TvInputInfo TvInputInfo);
+    void onTvInputInfoChanged(in TvInputInfo TvInputInfo);
 }
diff --git a/media/java/android/media/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index 9f13882..74ab562 100644
--- a/media/java/android/media/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -27,6 +27,4 @@
     void addHardwareTvInput(in int deviceId, in TvInputInfo inputInfo);
     void addHdmiTvInput(in int id, in TvInputInfo inputInfo);
     void removeTvInput(in String inputId);
-
-    void setTvInputInfo(in String inputId, in TvInputInfo inputInfo);
 }
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 671a86f..20491e4 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -107,15 +107,6 @@
      */
     public static final String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID";
 
-    private static final SparseIntArray sHardwareTypeToTvInputType = new SparseIntArray();
-
-    private static final String XML_START_TAG_NAME = "tv-input";
-    private static final String DELIMITER_INFO_IN_ID = "/";
-    private static final String PREFIX_HDMI_DEVICE = "HDMI";
-    private static final String PREFIX_HARDWARE_DEVICE = "HW";
-    private static final int LENGTH_HDMI_PHYSICAL_ADDRESS = 4;
-    private static final int LENGTH_HDMI_DEVICE_ID = 2;
-
     private final ResolveInfo mService;
     private final String mId;
     private final String mParentId;
@@ -137,21 +128,6 @@
     private Uri mIconUri;
     private boolean mIsConnectedToHdmiSwitch;
 
-    static {
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_OTHER_HARDWARE,
-                TYPE_OTHER);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_TUNER, TYPE_TUNER);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_COMPOSITE, TYPE_COMPOSITE);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_SVIDEO, TYPE_SVIDEO);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_SCART, TYPE_SCART);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_COMPONENT, TYPE_COMPONENT);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_VGA, TYPE_VGA);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_DVI, TYPE_DVI);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_HDMI, TYPE_HDMI);
-        sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_DISPLAY_PORT,
-                TYPE_DISPLAY_PORT);
-    }
-
     /**
      * Create a new instance of the TvInputInfo class, instantiating it from the given Context,
      * ResolveInfo, and HdmiDeviceInfo.
@@ -260,93 +236,6 @@
                 .build();
     }
 
-    static TvInputInfo createTvInputInfo(Context context, ResolveInfo resolveInfo, Icon icon,
-            int labelResId, int tunerCount, boolean canRecord, HdmiDeviceInfo hdmiDeviceInfo,
-            String parentId, TvInputHardwareInfo tvInputHardwareInfo)
-            throws IOException, XmlPullParserException {
-        ComponentName componentName = new ComponentName(resolveInfo.serviceInfo.packageName,
-                resolveInfo.serviceInfo.name);
-        String id;
-        int type;
-        boolean isHardwareInput = false;
-        boolean isConnectedToHdmiSwitch = false;
-
-        if (hdmiDeviceInfo != null) {
-            id = generateInputIdForHdmiDevice(componentName, hdmiDeviceInfo);
-            type = TYPE_HDMI;
-            isHardwareInput = true;
-            isConnectedToHdmiSwitch = (hdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
-            tunerCount = 0;
-        } else if (tvInputHardwareInfo != null) {
-            id = generateInputIdForHardware(componentName, tvInputHardwareInfo);
-            type = sHardwareTypeToTvInputType.get(tvInputHardwareInfo.getType(), TYPE_TUNER);
-            isHardwareInput = true;
-            tunerCount = 0;
-        } else {
-            id = generateInputIdForComponentName(componentName);
-            type = TYPE_TUNER;
-        }
-
-        TvInputInfo info = new TvInputInfo(resolveInfo, id, parentId, type, isHardwareInput,
-                isConnectedToHdmiSwitch, tunerCount, canRecord);
-        return parseServiceMetadata(context, resolveInfo, type, info);
-    }
-
-    private static TvInputInfo parseServiceMetadata(
-            Context context, ResolveInfo service, int inputType, TvInputInfo input)
-            throws XmlPullParserException, IOException {
-        ServiceInfo si = service.serviceInfo;
-        PackageManager pm = context.getPackageManager();
-        XmlResourceParser parser = null;
-        try {
-            parser = si.loadXmlMetaData(pm, TvInputService.SERVICE_META_DATA);
-            if (parser == null) {
-                throw new XmlPullParserException("No " + TvInputService.SERVICE_META_DATA
-                        + " meta-data for " + si.name);
-            }
-
-            Resources res = pm.getResourcesForApplication(si.applicationInfo);
-            AttributeSet attrs = Xml.asAttributeSet(parser);
-
-            int type;
-            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                    && type != XmlPullParser.START_TAG) {
-            }
-
-            String nodeName = parser.getName();
-            if (!XML_START_TAG_NAME.equals(nodeName)) {
-                throw new XmlPullParserException(
-                        "Meta-data does not start with tv-input-service tag in " + si.name);
-            }
-
-            TypedArray sa = res.obtainAttributes(attrs,
-                    com.android.internal.R.styleable.TvInputService);
-            input.mSetupActivity = sa.getString(
-                    com.android.internal.R.styleable.TvInputService_setupActivity);
-            if (DEBUG) {
-                Log.d(TAG, "Setup activity loaded. [" + input.mSetupActivity + "] for " + si.name);
-            }
-            if (inputType == TYPE_TUNER && TextUtils.isEmpty(input.mSetupActivity)) {
-                throw new XmlPullParserException("Setup activity not found in " + si.name);
-            }
-            input.mSettingsActivity = sa.getString(
-                    com.android.internal.R.styleable.TvInputService_settingsActivity);
-            if (DEBUG) {
-                Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
-                        + si.name);
-            }
-            sa.recycle();
-
-        } catch (NameNotFoundException e) {
-            throw new XmlPullParserException("Unable to create context for: " + si.packageName);
-        } finally {
-            if (parser != null) {
-                parser.close();
-            }
-        }
-        return input;
-    }
-
     /**
      * Constructor.
      *
@@ -645,46 +534,6 @@
         return mService.serviceInfo.loadIcon(context.getPackageManager());
     }
 
-    /**
-     * Used to generate an input id from a ComponentName.
-     *
-     * @param name the component name for generating an input id.
-     * @return the generated input id for the given {@code name}.
-     */
-    private static String generateInputIdForComponentName(ComponentName name) {
-        return name.flattenToShortString();
-    }
-
-    /**
-     * Used to generate an input id from a ComponentName and HdmiDeviceInfo.
-     *
-     * @param name the component name for generating an input id.
-     * @param deviceInfo HdmiDeviceInfo describing this TV input.
-     * @return the generated input id for the given {@code name} and {@code deviceInfo}.
-     */
-    private static String generateInputIdForHdmiDevice(
-            ComponentName name, HdmiDeviceInfo deviceInfo) {
-        // Example of the format : "/HDMI%04X%02X"
-        String format = DELIMITER_INFO_IN_ID + PREFIX_HDMI_DEVICE
-                + "%0" + LENGTH_HDMI_PHYSICAL_ADDRESS + "X"
-                + "%0" + LENGTH_HDMI_DEVICE_ID + "X";
-        return name.flattenToShortString() + String.format(Locale.ENGLISH, format,
-                deviceInfo.getPhysicalAddress(), deviceInfo.getId());
-    }
-
-    /**
-     * Used to generate an input id from a ComponentName and TvInputHardwareInfo
-     *
-     * @param name the component name for generating an input id.
-     * @param hardwareInfo TvInputHardwareInfo describing this TV input.
-     * @return the generated input id for the given {@code name} and {@code hardwareInfo}.
-     */
-    private static String generateInputIdForHardware(
-            ComponentName name, TvInputHardwareInfo hardwareInfo) {
-        return name.flattenToShortString() + DELIMITER_INFO_IN_ID + PREFIX_HARDWARE_DEVICE
-                + hardwareInfo.getDeviceId();
-    }
-
     public static final Parcelable.Creator<TvInputInfo> CREATOR =
             new Parcelable.Creator<TvInputInfo>() {
         @Override
@@ -720,6 +569,32 @@
      * A convenience builder for creating {@link TvInputInfo} objects.
      */
     public static final class Builder {
+        private static final int LENGTH_HDMI_PHYSICAL_ADDRESS = 4;
+        private static final int LENGTH_HDMI_DEVICE_ID = 2;
+
+        private static final String XML_START_TAG_NAME = "tv-input";
+        private static final String DELIMITER_INFO_IN_ID = "/";
+        private static final String PREFIX_HDMI_DEVICE = "HDMI";
+        private static final String PREFIX_HARDWARE_DEVICE = "HW";
+
+        private static final SparseIntArray sHardwareTypeToTvInputType = new SparseIntArray();
+        static {
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_OTHER_HARDWARE,
+                    TYPE_OTHER);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_TUNER, TYPE_TUNER);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_COMPOSITE,
+                    TYPE_COMPOSITE);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_SVIDEO, TYPE_SVIDEO);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_SCART, TYPE_SCART);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_COMPONENT,
+                    TYPE_COMPONENT);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_VGA, TYPE_VGA);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_DVI, TYPE_DVI);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_HDMI, TYPE_HDMI);
+            sHardwareTypeToTvInputType.put(TvInputHardwareInfo.TV_INPUT_TYPE_DISPLAY_PORT,
+                    TYPE_DISPLAY_PORT);
+        }
+
         private final Context mContext;
         private final ResolveInfo mResolveInfo;
         private Icon mIcon;
@@ -864,11 +739,102 @@
          * @return TvInputInfo containing information about this TV input.
          * @throws IOException If there was an I/O error.
          * @throws XmlPullParserException If there was an XML parsing error.
-         *
          */
         public TvInputInfo build() throws IOException, XmlPullParserException {
-            return createTvInputInfo(mContext, mResolveInfo, mIcon, mLabelResId, mTunerCount,
-                    mCanRecord, mHdmiDeviceInfo, mParentId, mTvInputHardwareInfo);
+            ComponentName componentName = new ComponentName(mResolveInfo.serviceInfo.packageName,
+                    mResolveInfo.serviceInfo.name);
+            String id;
+            int type;
+            boolean isHardwareInput = false;
+            boolean isConnectedToHdmiSwitch = false;
+
+            if (mHdmiDeviceInfo != null) {
+                id = generateInputId(componentName, mHdmiDeviceInfo);
+                type = TYPE_HDMI;
+                isHardwareInput = true;
+                isConnectedToHdmiSwitch = (mHdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
+                mTunerCount = 0;
+            } else if (mTvInputHardwareInfo != null) {
+                id = generateInputId(componentName, mTvInputHardwareInfo);
+                type = sHardwareTypeToTvInputType.get(mTvInputHardwareInfo.getType(), TYPE_TUNER);
+                isHardwareInput = true;
+                mTunerCount = 0;
+            } else {
+                id = generateInputId(componentName);
+                type = TYPE_TUNER;
+            }
+
+            TvInputInfo info = new TvInputInfo(mResolveInfo, id, mParentId, type, isHardwareInput,
+                    isConnectedToHdmiSwitch, mTunerCount, mCanRecord);
+            return parseServiceMetadata(type, info);
+        }
+
+        private static String generateInputId(ComponentName name) {
+            return name.flattenToShortString();
+        }
+
+        private static String generateInputId(ComponentName name, HdmiDeviceInfo hdmiDeviceInfo) {
+            // Example of the format : "/HDMI%04X%02X"
+            String format = DELIMITER_INFO_IN_ID + PREFIX_HDMI_DEVICE
+                    + "%0" + LENGTH_HDMI_PHYSICAL_ADDRESS + "X"
+                    + "%0" + LENGTH_HDMI_DEVICE_ID + "X";
+            return name.flattenToShortString() + String.format(Locale.ENGLISH, format,
+                    hdmiDeviceInfo.getPhysicalAddress(), hdmiDeviceInfo.getId());
+        }
+
+        private static String generateInputId(ComponentName name,
+                TvInputHardwareInfo tvInputHardwareInfo) {
+            return name.flattenToShortString() + DELIMITER_INFO_IN_ID + PREFIX_HARDWARE_DEVICE
+                    + tvInputHardwareInfo.getDeviceId();
+        }
+
+        private TvInputInfo parseServiceMetadata(int inputType, TvInputInfo info)
+                throws XmlPullParserException, IOException {
+            ServiceInfo si = mResolveInfo.serviceInfo;
+            PackageManager pm = mContext.getPackageManager();
+            try (XmlResourceParser parser =
+                         si.loadXmlMetaData(pm, TvInputService.SERVICE_META_DATA)) {
+                if (parser == null) {
+                    throw new XmlPullParserException("No " + TvInputService.SERVICE_META_DATA
+                            + " meta-data for " + si.name);
+                }
+
+                Resources res = pm.getResourcesForApplication(si.applicationInfo);
+                AttributeSet attrs = Xml.asAttributeSet(parser);
+
+                int type;
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && type != XmlPullParser.START_TAG) {
+                }
+
+                String nodeName = parser.getName();
+                if (!XML_START_TAG_NAME.equals(nodeName)) {
+                    throw new XmlPullParserException(
+                            "Meta-data does not start with tv-input-service tag in " + si.name);
+                }
+
+                TypedArray sa = res.obtainAttributes(attrs,
+                        com.android.internal.R.styleable.TvInputService);
+                info.mSetupActivity = sa.getString(
+                        com.android.internal.R.styleable.TvInputService_setupActivity);
+                if (DEBUG) {
+                    Log.d(TAG, "Setup activity loaded. [" + info.mSetupActivity + "] for "
+                            + si.name);
+                }
+                if (inputType == TYPE_TUNER && TextUtils.isEmpty(info.mSetupActivity)) {
+                    throw new XmlPullParserException("Setup activity not found in " + si.name);
+                }
+                info.mSettingsActivity = sa.getString(
+                        com.android.internal.R.styleable.TvInputService_settingsActivity);
+                if (DEBUG) {
+                    Log.d(TAG, "Settings activity loaded. [" + info.mSettingsActivity + "] for "
+                            + si.name);
+                }
+                sa.recycle();
+            } catch (NameNotFoundException e) {
+                throw new XmlPullParserException("Unable to create context for: " + si.packageName);
+            }
+            return info;
         }
     }
 
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f1de8fd..86bded9 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -726,12 +726,11 @@
         }
 
         /**
-         * This is called when the information about a given TV input is changed.
+         * This is called when the information about a given TV input has been changed.
          *
-         * @param inputId The ID of the TV input.
          * @param inputInfo TvInputInfo object that contains the information about the TV input.
          */
-        public void onTvInputInfoChanged(String inputId, TvInputInfo inputInfo) {
+        public void onTvInputInfoChanged(TvInputInfo inputInfo) {
         }
     }
 
@@ -784,11 +783,11 @@
             });
         }
 
-        public void postTvInputInfoChanged(final String inputId, final TvInputInfo inputInfo) {
+        public void postTvInputInfoChanged(final TvInputInfo inputInfo) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mCallback.onTvInputInfoChanged(inputId, inputInfo);
+                    mCallback.onTvInputInfoChanged(inputInfo);
                 }
             });
         }
@@ -1089,10 +1088,10 @@
             }
 
             @Override
-            public void onTvInputInfoChanged(String inputId, TvInputInfo inputInfo) {
+            public void onTvInputInfoChanged(TvInputInfo inputInfo) {
                 synchronized (mLock) {
                     for (TvInputCallbackRecord record : mCallbackRecords) {
-                        record.postTvInputInfoChanged(inputId, inputInfo);
+                        record.postTvInputInfoChanged(inputInfo);
                     }
                 }
             }
@@ -1143,6 +1142,23 @@
     }
 
     /**
+     * Sets a new TvInputInfo object for a given input.
+     *
+     * <p>This is called internally only by {@link TvInputService}.
+     *
+     * @param inputInfo The TvInputInfo object to set.
+     * @throws IllegalArgumentException if the argument is {@code null}.
+     */
+    void setTvInputInfo(@NonNull TvInputInfo inputInfo) {
+        Preconditions.checkNotNull(inputInfo);
+        try {
+            mService.setTvInputInfo(inputInfo, mUserId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Error trying to set " + inputInfo, e);
+        }
+    }
+
+    /**
      * Returns the state of a given TV input.
      *
      * <p>The state is one of the following:
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index f74ae66..77e81dc 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -262,16 +262,16 @@
      * <p>The system service automatically creates the TvInputInfo for each TV input based on
      * information collected from the AndroidManifest.xml, thus it is not necessary to call this
      * method unless the TV input has additional information to pass such as ability to record and
-     * tuner count.
+     * tuner count. Attempting to change information about a TV input that the calling package does
+     * not own does nothing.
      *
-     * @param inputId The ID of the TV input.
+     * @param context The application context.
      * @param inputInfo The TvInputInfo object that contains that new information.
      */
-    public final void setTvInputInfo(String inputId, TvInputInfo inputInfo) {
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = inputId;
-        args.arg2 = inputInfo;
-        mServiceHandler.obtainMessage(ServiceHandler.DO_SET_TV_INPUT_INFO, args).sendToTarget();
+    public static final void setTvInputInfo(Context context, TvInputInfo inputInfo) {
+        TvInputManager manager = (TvInputManager) context.getSystemService(
+                Context.TV_INPUT_SERVICE);
+        manager.setTvInputInfo(inputInfo);
     }
 
     private boolean isPassthroughInput(String inputId) {
@@ -525,7 +525,7 @@
         public void notifyVideoUnavailable(final int reason) {
             if (reason < TvInputManager.VIDEO_UNAVAILABLE_REASON_START
                     || reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) {
-                throw new IllegalArgumentException("Unknown reason: " + reason);
+                Log.e(TAG, "notifyVideoUnavailable - unknown reason: " + reason);
             }
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
@@ -1938,7 +1938,6 @@
         private static final int DO_REMOVE_HARDWARE_TV_INPUT = 5;
         private static final int DO_ADD_HDMI_TV_INPUT = 6;
         private static final int DO_REMOVE_HDMI_TV_INPUT = 7;
-        private static final int DO_SET_TV_INPUT_INFO = 8;
 
         private void broadcastAddHardwareTvInput(int deviceId, TvInputInfo inputInfo) {
             int n = mCallbacks.beginBroadcast();
@@ -1976,18 +1975,6 @@
             mCallbacks.finishBroadcast();
         }
 
-        private void broadcastSetTvInputInfo(String inputId, TvInputInfo inputInfo) {
-            int n = mCallbacks.beginBroadcast();
-            for (int i = 0; i < n; ++i) {
-                try {
-                    mCallbacks.getBroadcastItem(i).setTvInputInfo(inputId, inputInfo);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "error in broadcastSetTvInputInfo", e);
-                }
-            }
-            mCallbacks.finishBroadcast();
-        }
-
         @Override
         public final void handleMessage(Message msg) {
             switch (msg.what) {
@@ -2120,16 +2107,6 @@
                     }
                     return;
                 }
-                case DO_SET_TV_INPUT_INFO: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    String inputId = (String) args.arg1;
-                    TvInputInfo inputInfo = (TvInputInfo) args.arg2;
-                    if (inputInfo != null) {
-                        broadcastSetTvInputInfo(inputId, inputInfo);
-                    }
-                    args.recycle();
-                    return;
-                }
                 default: {
                     Log.w(TAG, "Unhandled message code: " + msg.what);
                     return;
diff --git a/media/java/android/mtp/MtpConstants.java b/media/java/android/mtp/MtpConstants.java
index ef2cf2b..0dcc718 100644
--- a/media/java/android/mtp/MtpConstants.java
+++ b/media/java/android/mtp/MtpConstants.java
@@ -690,4 +690,6 @@
     public static final int OPERATION_SET_OBJECT_REFERENCES = 0x9811;
     /** Operation code for Skip */
     public static final int OPERATION_SKIP = 0x9820;
+    /** Operation code for GetPartialObject64 */
+    public static final int OPERATION_GET_PARTIAL_OBJECT_64 = 0x95C1;
 }
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index 4379a99..0e7013c 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -153,10 +153,11 @@
      *
      * @param objectHandle handle of the object to read
      * @param objectSize the size of the object (this should match
-     *      {@link MtpObjectInfo#getCompressedSize}
+     *      {@link MtpObjectInfo#getCompressedSize})
      * @return the object's data, or null if reading fails
      */
     public byte[] getObject(int objectHandle, int objectSize) {
+        Preconditions.checkArgumentNonnegative(objectSize, "objectSize should not be negative");
         return native_get_object(objectHandle, objectSize);
     }
 
@@ -179,6 +180,27 @@
     }
 
     /**
+     * Obtains object bytes in the specified range and writes it to an array.
+     * This call may block for an arbitrary amount of time depending on the size
+     * of the data and speed of the devices.
+     *
+     * This is a vender-extended operation supported by Android that enables us to pass
+     * unsigned 64-bit offset. Check if the MTP device supports the operation by using
+     * {@link MtpDeviceInfo#getOperationsSupported()}.
+     *
+     * @param objectHandle handle of the object to read
+     * @param offset Start index of reading range. It must be a non-negative value.
+     * @param size Size of reading range. It must be a non-negative value at most 0xffffffff.
+     * @param buffer Array to write data.
+     * @return Size of bytes that are actually read.
+     * @see MtpConstants#OPERATION_GET_PARTIAL_OBJECT_64
+     */
+    public long getPartialObject64(int objectHandle, long offset, long size, byte[] buffer)
+            throws IOException {
+        return native_get_partial_object_64(objectHandle, offset, size, buffer);
+    }
+
+    /**
      * Returns the thumbnail data for an object as a byte array.
      * The size and format of the thumbnail data can be determined via
      * {@link MtpObjectInfo#getThumbCompressedSize} and
@@ -284,7 +306,7 @@
      * @param descriptor file descriptor to read the data from.
      * @return true if the file transfer succeeds
      */
-    public boolean sendObject(int objectHandle, int size, ParcelFileDescriptor descriptor) {
+    public boolean sendObject(int objectHandle, long size, ParcelFileDescriptor descriptor) {
         return native_send_object(objectHandle, size, descriptor.getFd());
     }
 
@@ -343,16 +365,18 @@
     private native MtpStorageInfo native_get_storage_info(int storageId);
     private native int[] native_get_object_handles(int storageId, int format, int objectHandle);
     private native MtpObjectInfo native_get_object_info(int objectHandle);
-    private native byte[] native_get_object(int objectHandle, int objectSize);
+    private native byte[] native_get_object(int objectHandle, long objectSize);
     private native long native_get_partial_object(
             int objectHandle, long offset, long objectSize, byte[] buffer) throws IOException;
+    private native int native_get_partial_object_64(
+            int objectHandle, long offset, long objectSize, byte[] buffer) throws IOException;
     private native byte[] native_get_thumbnail(int objectHandle);
     private native boolean native_delete_object(int objectHandle);
-    private native long native_get_parent(int objectHandle);
-    private native long native_get_storage_id(int objectHandle);
+    private native int native_get_parent(int objectHandle);
+    private native int native_get_storage_id(int objectHandle);
     private native boolean native_import_file(int objectHandle, String destPath);
     private native boolean native_import_file(int objectHandle, int fd);
-    private native boolean native_send_object(int objectHandle, int size, int fd);
+    private native boolean native_send_object(int objectHandle, long size, int fd);
     private native MtpObjectInfo native_send_object_info(MtpObjectInfo info);
     private native int native_submit_event_request();
     private native MtpEvent native_reap_event_request(int handle);
diff --git a/media/java/android/mtp/MtpObjectInfo.java b/media/java/android/mtp/MtpObjectInfo.java
index 64aa997..02092b1 100644
--- a/media/java/android/mtp/MtpObjectInfo.java
+++ b/media/java/android/mtp/MtpObjectInfo.java
@@ -16,6 +16,8 @@
 
 package android.mtp;
 
+import com.android.internal.util.Preconditions;
+
 /**
  * This class encapsulates information about an object on an MTP device.
  * This corresponds to the ObjectInfo Dataset described in
@@ -96,10 +98,20 @@
      * @return the object size
      */
     public final int getCompressedSize() {
+        Preconditions.checkState(mCompressedSize >= 0);
         return mCompressedSize;
     }
 
     /**
+     * Returns the size of the MTP object
+     *
+     * @return the object size
+     */
+    public final long getCompressedSizeLong() {
+        return uint32ToLong(mCompressedSize);
+    }
+
+    /**
      * Returns the format code for the MTP object's thumbnail
      * Will be zero for objects with no thumbnail
      *
@@ -116,60 +128,126 @@
      * @return the thumbnail size
      */
     public final int getThumbCompressedSize() {
+        Preconditions.checkState(mThumbCompressedSize >= 0);
         return mThumbCompressedSize;
     }
 
     /**
+     * Returns the size of the MTP object's thumbnail
+     * Will be zero for objects with no thumbnail
+     *
+     * @return the thumbnail size
+     */
+    public final long getThumbCompressedSizeLong() {
+        return uint32ToLong(mThumbCompressedSize);
+    }
+
+    /**
      * Returns the width of the MTP object's thumbnail in pixels
      * Will be zero for objects with no thumbnail
      *
      * @return the thumbnail width
      */
     public final int getThumbPixWidth() {
+        Preconditions.checkState(mThumbPixWidth >= 0);
         return mThumbPixWidth;
     }
 
     /**
+     * Returns the width of the MTP object's thumbnail in pixels
+     * Will be zero for objects with no thumbnail
+     *
+     * @return the thumbnail width
+     */
+    public final long getThumbPixWidthLong() {
+        return uint32ToLong(mThumbPixWidth);
+    }
+
+    /**
      * Returns the height of the MTP object's thumbnail in pixels
      * Will be zero for objects with no thumbnail
      *
      * @return the thumbnail height
      */
     public final int getThumbPixHeight() {
+        Preconditions.checkState(mThumbPixHeight >= 0);
         return mThumbPixHeight;
     }
 
     /**
+     * Returns the height of the MTP object's thumbnail in pixels
+     * Will be zero for objects with no thumbnail
+     *
+     * @return the thumbnail height
+     */
+    public final long getThumbPixHeightLong() {
+        return uint32ToLong(mThumbPixHeight);
+    }
+
+    /**
      * Returns the width of the MTP object in pixels
      * Will be zero for non-image objects
      *
      * @return the image width
      */
     public final int getImagePixWidth() {
+        Preconditions.checkState(mImagePixWidth >= 0);
         return mImagePixWidth;
     }
 
     /**
+     * Returns the width of the MTP object in pixels
+     * Will be zero for non-image objects
+     *
+     * @return the image width
+     */
+    public final long getImagePixWidthLong() {
+        return uint32ToLong(mImagePixWidth);
+    }
+
+    /**
      * Returns the height of the MTP object in pixels
      * Will be zero for non-image objects
      *
      * @return the image height
      */
     public final int getImagePixHeight() {
+        Preconditions.checkState(mImagePixHeight >= 0);
         return mImagePixHeight;
     }
 
     /**
+     * Returns the height of the MTP object in pixels
+     * Will be zero for non-image objects
+     *
+     * @return the image height
+     */
+    public final long getImagePixHeightLong() {
+        return uint32ToLong(mImagePixHeight);
+    }
+
+    /**
      * Returns the depth of the MTP object in bits per pixel
      * Will be zero for non-image objects
      *
      * @return the image depth
      */
     public final int getImagePixDepth() {
+        Preconditions.checkState(mImagePixDepth >= 0);
         return mImagePixDepth;
     }
 
     /**
+     * Returns the depth of the MTP object in bits per pixel
+     * Will be zero for non-image objects
+     *
+     * @return the image depth
+     */
+    public final long getImagePixDepthLong() {
+        return uint32ToLong(mImagePixDepth);
+    }
+
+    /**
      * Returns the object handle for the object's parent
      * Will be zero for the root directory of a storage unit
      *
@@ -203,7 +281,7 @@
         return mAssociationDesc;
     }
 
-   /**
+    /**
      * Returns the sequence number for the MTP object
      * This field is typically not used for MTP devices,
      * but is sometimes used to define a sequence of photos
@@ -212,9 +290,22 @@
      * @return the object's sequence number
      */
     public final int getSequenceNumber() {
+        Preconditions.checkState(mSequenceNumber >= 0);
         return mSequenceNumber;
     }
 
+    /**
+     * Returns the sequence number for the MTP object
+     * This field is typically not used for MTP devices,
+     * but is sometimes used to define a sequence of photos
+     * on PTP cameras.
+     *
+     * @return the object's sequence number
+     */
+    public final long getSequenceNumberLong() {
+        return uint32ToLong(mSequenceNumber);
+    }
+
    /**
      * Returns the name of the MTP object
      *
@@ -309,8 +400,8 @@
             return this;
         }
 
-        public Builder setCompressedSize(int value) {
-            mObjectInfo.mCompressedSize = value;
+        public Builder setCompressedSize(long value) {
+            mObjectInfo.mCompressedSize = longToUint32(value, "value");
             return this;
         }
 
@@ -329,18 +420,18 @@
             return this;
         }
 
-        public Builder setImagePixDepth(int value) {
-            mObjectInfo.mImagePixDepth = value;
+        public Builder setImagePixDepth(long value) {
+            mObjectInfo.mImagePixDepth = longToUint32(value, "value");
             return this;
         }
 
-        public Builder setImagePixHeight(int value) {
-            mObjectInfo.mImagePixHeight = value;
+        public Builder setImagePixHeight(long value) {
+            mObjectInfo.mImagePixHeight = longToUint32(value, "value");
             return this;
         }
 
-        public Builder setImagePixWidth(int value) {
-            mObjectInfo.mImagePixWidth = value;
+        public Builder setImagePixWidth(long value) {
+            mObjectInfo.mImagePixWidth = longToUint32(value, "value");
             return this;
         }
 
@@ -364,8 +455,8 @@
             return this;
         }
 
-        public Builder setSequenceNumber(int value) {
-            mObjectInfo.mSequenceNumber = value;
+        public Builder setSequenceNumber(long value) {
+            mObjectInfo.mSequenceNumber = longToUint32(value, "value");
             return this;
         }
 
@@ -374,8 +465,8 @@
             return this;
         }
 
-        public Builder setThumbCompressedSize(int value) {
-            mObjectInfo.mThumbCompressedSize = value;
+        public Builder setThumbCompressedSize(long value) {
+            mObjectInfo.mThumbCompressedSize = longToUint32(value, "value");
             return this;
         }
 
@@ -384,13 +475,13 @@
             return this;
         }
 
-        public Builder setThumbPixHeight(int value) {
-            mObjectInfo.mThumbPixHeight = value;
+        public Builder setThumbPixHeight(long value) {
+            mObjectInfo.mThumbPixHeight = longToUint32(value, "value");
             return this;
         }
 
-        public Builder setThumbPixWidth(int value) {
-            mObjectInfo.mThumbPixWidth = value;
+        public Builder setThumbPixWidth(long value) {
+            mObjectInfo.mThumbPixWidth = longToUint32(value, "value");
             return this;
         }
 
@@ -407,4 +498,13 @@
             return result;
         }
     }
+
+    private static long uint32ToLong(int value) {
+        return value < 0 ? 0x100000000L + value : value;
+    }
+
+    private static int longToUint32(long value, String valueName) {
+        Preconditions.checkArgumentInRange(value, 0, 0xffffffffL, valueName);
+        return (int) value;
+    }
 }
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index fe7ebfa..6ca5ac5 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -16,7 +16,7 @@
 oneway interface IMediaBrowserService {
 
     // Warning: DO NOT CHANGE the methods signature and order of methods.
-    // The change of the order or the method signatures could break the support library.
+    // A change of the order or the method signatures could break the support library.
 
     void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
     void disconnect(IMediaBrowserServiceCallbacks callbacks);
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index dadb025..e6b0e8c 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -13,6 +13,10 @@
  * @hide
  */
 oneway interface IMediaBrowserServiceCallbacks {
+
+    // Warning: DO NOT CHANGE the methods signature and order of methods.
+    // A change of the order or the method signatures could break the support library.
+
     /**
      * Invoked when the connected has been established.
      * @param root The root media id for browsing.
@@ -22,5 +26,6 @@
      */
     void onConnect(String root, in MediaSession.Token session, in Bundle extras);
     void onConnectFailed();
-    void onLoadChildren(String mediaId, in ParceledListSlice list, in Bundle options);
+    void onLoadChildren(String mediaId, in ParceledListSlice list);
+    void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list, in Bundle options);
 }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 6cf90d5..299b770 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -589,7 +589,14 @@
                 final ParceledListSlice<MediaBrowser.MediaItem> pls =
                         filteredList == null ? null : new ParceledListSlice<>(filteredList);
                 try {
-                    connection.callbacks.onLoadChildren(parentId, pls, options);
+                    // NOTE: Do not call onLoadChildrenWithOptions when options are null. Otherwise,
+                    // it will break the action of support library which expects onLoadChildren will
+                    // be called when options are null.
+                    if (options == null) {
+                        connection.callbacks.onLoadChildren(parentId, pls);
+                    } else {
+                        connection.callbacks.onLoadChildrenWithOptions(parentId, pls, options);
+                    }
                 } catch (RemoteException ex) {
                     // The other side is in the process of crashing.
                     Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
diff --git a/media/jni/android_media_ExifInterface.cpp b/media/jni/android_media_ExifInterface.cpp
index 42deab4..ba38569 100644
--- a/media/jni/android_media_ExifInterface.cpp
+++ b/media/jni/android_media_ExifInterface.cpp
@@ -238,7 +238,7 @@
             map.add(
                     String8("GPSTimeStamp"),
                     String8::format(
-                            "%2u:%2u:%2u",
+                            "%02u:%02u:%02u",
                             image_data.gps.time_stamp[0].numerator
                             / image_data.gps.time_stamp[0].denominator,
                             image_data.gps.time_stamp[1].numerator
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index 025133f..3b892cb 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -150,4 +150,8 @@
     mJavaObjStatus = UNKNOWN_ERROR;
 }
 
+uint32_t JMediaDataSource::getFlags() {
+    return 0;
+}
+
 }  // namespace android
diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h
index 2bc237e..34624eb 100644
--- a/media/jni/android_media_MediaDataSource.h
+++ b/media/jni/android_media_MediaDataSource.h
@@ -45,6 +45,7 @@
     virtual ssize_t readAt(off64_t offset, size_t size);
     virtual status_t getSize(off64_t* size);
     virtual void close();
+    virtual uint32_t getFlags();
 
 private:
     // Protect all member variables with mLock because this object will be
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index a5d0303..c08a5e3 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -80,9 +80,9 @@
 }
 
 bool GetExifFromRawImage(
-        FileStream::FileStream* stream, const String8& filename,
-        piex::PreviewImageData& image_data) {
-    memset(&image_data, 0, sizeof(image_data));
+        FileStream* stream, const String8& filename, piex::PreviewImageData& image_data) {
+    // Reset the PreviewImageData to its default.
+    image_data = piex::PreviewImageData();
 
     if (!stream->exists()) {
         // File is not exists.
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 8b7a926..0ecb750 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -26,6 +26,7 @@
 #include <fcntl.h>
 
 #include <memory>
+#include <string>
 
 #include "jni.h"
 #include "JNIHelp.h"
@@ -370,9 +371,26 @@
     return info;
 }
 
+bool check_uint32_arg(JNIEnv *env, const char* name, jlong value, uint32_t* out) {
+    if (value < 0 || 0xffffffff < value) {
+        jniThrowException(
+                env,
+                "java/lang/IllegalArgumentException",
+                (std::string("argument must be a 32-bit unsigned integer: ") + name).c_str());
+        return false;
+    }
+    *out = static_cast<uint32_t>(value);
+    return true;
+}
+
 static jbyteArray
-android_mtp_MtpDevice_get_object(JNIEnv *env, jobject thiz, jint objectID, jint objectSize)
+android_mtp_MtpDevice_get_object(JNIEnv *env, jobject thiz, jint objectID, jlong objectSizeLong)
 {
+    uint32_t objectSize;
+    if (!check_uint32_arg(env, "objectSize", objectSizeLong, &objectSize)) {
+        return nullptr;
+    }
+
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device) {
         return nullptr;
@@ -396,8 +414,8 @@
 android_mtp_MtpDevice_get_partial_object(JNIEnv *env,
                                          jobject thiz,
                                          jint objectID,
-                                         jlong offset,
-                                         jlong size,
+                                         jlong offsetLong,
+                                         jlong sizeLong,
                                          jbyteArray array)
 {
     if (!array) {
@@ -405,19 +423,10 @@
         return -1;
     }
 
-    if (offset < 0 || 0xffffffffL < offset) {
-        jniThrowException(
-                env,
-                "java/lang/IllegalArgumentException",
-                "Offset argument must be a 32-bit unsigned integer.");
-        return -1;
-    }
-
-    if (size < 0 || 0xffffffffL < size) {
-        jniThrowException(
-                env,
-                "java/lang/IllegalArgumentException",
-                "Size argument must be a 32-bit unsigned integer.");
+    uint32_t offset;
+    uint32_t size;
+    if (!check_uint32_arg(env, "offset", offsetLong, &offset) ||
+            !check_uint32_arg(env, "size", sizeLong, &size)) {
         return -1;
     }
 
@@ -438,6 +447,60 @@
     return static_cast<jlong>(written_size);
 }
 
+static jint
+android_mtp_MtpDevice_get_partial_object_64(JNIEnv *env,
+                                            jobject thiz,
+                                            jint objectID,
+                                            jlong offset,
+                                            jlong size,
+                                            jbyteArray array) {
+    if (!array) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Array must not be null.");
+        return -1;
+    }
+
+    if (offset < 0) {
+        jniThrowException(
+                env,
+                "java/lang/IllegalArgumentException",
+                "Offset argument must not be a negative value.");
+        return -1;
+    }
+
+    if (size < 0 || 0xffffffffL < size) {
+        jniThrowException(
+                env,
+                "java/lang/IllegalArgumentException",
+                "Size argument must be a 32-bit unsigned integer.");
+        return -1;
+    }
+
+    MtpDevice* const device = get_device_from_object(env, thiz);
+    if (!device) {
+        jniThrowException(env, "java/io/IOException", "Failed to obtain MtpDevice.");
+        return -1;
+    }
+
+    const uint32_t native_object_handle = static_cast<uint32_t>(objectID);
+    const uint64_t native_offset = static_cast<uint64_t>(offset);
+    const uint32_t native_size = static_cast<uint32_t>(size);
+
+    JavaArrayWriter writer(env, array);
+    uint32_t written_size;
+    const bool success = device->readPartialObject64(
+            native_object_handle,
+            native_offset,
+            native_size,
+            &written_size,
+            JavaArrayWriter::writeTo,
+            &writer);
+    if (!success) {
+        jniThrowException(env, "java/io/IOException", "Failed to read data.");
+        return -1;
+    }
+    return static_cast<jint>(written_size);
+}
+
 static jbyteArray
 android_mtp_MtpDevice_get_thumbnail(JNIEnv *env, jobject thiz, jint objectID)
 {
@@ -467,22 +530,22 @@
     }
 }
 
-static jlong
+static jint
 android_mtp_MtpDevice_get_parent(JNIEnv *env, jobject thiz, jint object_id)
 {
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device)
-        return (jlong)device->getParent(object_id);
+        return static_cast<jint>(device->getParent(object_id));
     else
         return -1;
 }
 
-static jlong
+static jint
 android_mtp_MtpDevice_get_storage_id(JNIEnv *env, jobject thiz, jint object_id)
 {
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device)
-        return (jlong)device->getStorageID(object_id);
+        return static_cast<jint>(device->getStorageID(object_id));
     else
         return -1;
 }
@@ -516,8 +579,13 @@
 }
 
 static jboolean
-android_mtp_MtpDevice_send_object(JNIEnv *env, jobject thiz, jint object_id, jint size, jint fd)
+android_mtp_MtpDevice_send_object(
+        JNIEnv *env, jobject thiz, jint object_id, jlong sizeLong, jint fd)
 {
+    uint32_t size;
+    if (!check_uint32_arg(env, "size", sizeLong, &size))
+        return JNI_FALSE;
+
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return JNI_FALSE;
@@ -647,16 +715,18 @@
                                         (void *)android_mtp_MtpDevice_get_object_handles},
     {"native_get_object_info",  "(I)Landroid/mtp/MtpObjectInfo;",
                                         (void *)android_mtp_MtpDevice_get_object_info},
-    {"native_get_object",       "(II)[B",(void *)android_mtp_MtpDevice_get_object},
+    {"native_get_object",       "(IJ)[B",(void *)android_mtp_MtpDevice_get_object},
     {"native_get_partial_object", "(IJJ[B)J", (void *)android_mtp_MtpDevice_get_partial_object},
+    {"native_get_partial_object_64", "(IJJ[B)I",
+                                        (void *)android_mtp_MtpDevice_get_partial_object_64},
     {"native_get_thumbnail",    "(I)[B",(void *)android_mtp_MtpDevice_get_thumbnail},
     {"native_delete_object",    "(I)Z", (void *)android_mtp_MtpDevice_delete_object},
-    {"native_get_parent",       "(I)J", (void *)android_mtp_MtpDevice_get_parent},
-    {"native_get_storage_id",   "(I)J", (void *)android_mtp_MtpDevice_get_storage_id},
+    {"native_get_parent",       "(I)I", (void *)android_mtp_MtpDevice_get_parent},
+    {"native_get_storage_id",   "(I)I", (void *)android_mtp_MtpDevice_get_storage_id},
     {"native_import_file",      "(ILjava/lang/String;)Z",
                                         (void *)android_mtp_MtpDevice_import_file},
     {"native_import_file",      "(II)Z",(void *)android_mtp_MtpDevice_import_file_to_fd},
-    {"native_send_object",      "(III)Z",(void *)android_mtp_MtpDevice_send_object},
+    {"native_send_object",      "(IJI)Z",(void *)android_mtp_MtpDevice_send_object},
     {"native_send_object_info", "(Landroid/mtp/MtpObjectInfo;)Landroid/mtp/MtpObjectInfo;",
                                         (void *)android_mtp_MtpDevice_send_object_info},
     {"native_submit_event_request",  "()I", (void *)android_mtp_MtpDevice_submit_event_request},
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 6beef44..fa9ff01 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -54,8 +54,7 @@
             android:name=".LauncherActivity"
             android:theme="@android:style/Theme.NoDisplay"
             android:icon="@drawable/ic_files_app"
-            android:label="@string/files_label"
-            android:enabled="@bool/productivity_device">
+            android:label="@string/files_label">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -78,6 +77,16 @@
             </intent-filter>
         </activity>
 
+        <activity
+            android:name=".OpenExternalDirectoryActivity"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.OPEN_EXTERNAL_DIRECTORY" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="file" />
+            </intent-filter>
+        </activity>
+
         <provider
             android:name=".RecentsProvider"
             android:authorities="com.android.documentsui.recents"
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index 97fef4f..9931a6b 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Toestelle"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Nog programme"</string>
     <string name="empty" msgid="7858882803708117596">"Geen items nie"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Geen passings in %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Kan lêer nie oopmaak nie"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Kan sommige dokumente nie uitvee nie"</string>
     <string name="share_via" msgid="8966594246261344259">"Deel via"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Kon <xliff:g id="COUNT_1">%1$d</xliff:g> lêers nie uitvee nie</item>
       <item quantity="one">Kon <xliff:g id="COUNT_0">%1$d</xliff:g> lêer nie uitvee nie</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tik om besonderhede te bekyk"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Herprobeer"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Hierdie lêers is nie gekopieer nie: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Hierdie lêers is nie geskuif nie: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Het <xliff:g id="COUNT_0">%1$d</xliff:g> lêer na die knipbord gekopieer.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Kan nie die geselekteerde lêers in hierdie ligging plak nie."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Hernoem"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Kon nie dokument hernoem nie"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index c4bf922..cccaf51 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎችን መሰረዝ አልተቻለም።</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"ዝርዝሮችን ለመመልከት መታ ያድርጉ"</string>
-    <string name="retry" msgid="7564024179122207376">"እንደገና ይሞክሩ"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"እነዚህ ፋይሎች አልተቀዱም፦ <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"እነዚህ ፋይሎች አልተወሰዱም፦ <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index dc8cdaf..1177de7 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -123,7 +123,8 @@
       <item quantity="one">تعذر حذف <xliff:g id="COUNT_0">%1$d</xliff:g> ملف</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"انقر لعرض التفاصيل."</string>
-    <string name="retry" msgid="7564024179122207376">"إعادة المحاولة"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"لم يتم نسخ هذه الملفات: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"لم يتم نقل الملفات التالية: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index bd6fe01..2482ff0 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> fayl silinmədi</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Detallara baxmaq üçün basın"</string>
-    <string name="retry" msgid="7564024179122207376">"Yenidən cəhd edin"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Bu fayllar kopyalanmadı: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Bu fayllar köçürülmədi: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index e6ce761..28a35c7 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Uređaji"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Još aplikacija"</string>
     <string name="empty" msgid="7858882803708117596">"Nema stavki"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Nema podudaranja u %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Nije moguće otvoriti datoteku"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nije moguće izbrisati neke dokumente"</string>
     <string name="share_via" msgid="8966594246261344259">"Delite preko"</string>
@@ -105,9 +104,9 @@
       <item quantity="few">Brisanje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke nije uspelo</item>
       <item quantity="other">Brisanje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka nije uspelo</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Dodirnite da biste prikazali detalje"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Pokušaj ponovo"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Sledeće datoteke nisu kopirane: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Ove datoteke nisu premeštene: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -116,8 +115,6 @@
       <item quantity="other">Kopirali ste <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka u privremenu memoriju.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Izabrane datoteke ne mogu da se nalepe na ovoj lokaciji."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Preimenovanje dokumenta nije uspelo"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index b72412d..bdebffb 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файл не можа да бъде изтрит</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Докоснете, за да видите подробности"</string>
-    <string name="retry" msgid="7564024179122207376">"Нов опит"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Следните файлове не бяха копирани: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Следните файлове не бяха преместени: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 503d78a..0ede613 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মোছা গেল না</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"বিশদ বিবরণ দেখতে আলতো চাপুন"</string>
-    <string name="retry" msgid="7564024179122207376">"পুনরায় চেষ্টা করুন"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"এই ফাইলগুলির প্রতিলিপি করা হয় নি: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"এই ফাইলগুলি সরানো হয়নি: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index c94f5cd..bba1053 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -110,8 +110,7 @@
     <skip />
     <!-- no translation found for empty (7858882803708117596) -->
     <skip />
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Nema utakmica u %1$s"</string>
     <!-- no translation found for toast_no_application (1339885974067891667) -->
     <skip />
     <!-- no translation found for toast_failed_delete (2180678019407244069) -->
@@ -141,9 +140,8 @@
       <item quantity="few">Nije bilo moguće izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke</item>
       <item quantity="other">Nije bilo moguće izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
-    <skip />
-    <!-- no translation found for retry (7564024179122207376) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Dodirnite za prikaz detalja"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
     <!-- no translation found for copy_failure_alert_content (3715575000297709082) -->
     <skip />
@@ -152,8 +150,6 @@
     <!-- no translation found for clipboard_files_clipped (855459017537058539) -->
     <!-- no translation found for clipboard_files_cannot_paste (2878324825602325706) -->
     <skip />
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Nije uspjelo preimenovanje dokumenta"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 177a4d6..93e92cc 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">No s\'ha pogut suprimir <xliff:g id="COUNT_0">%1$d</xliff:g> fitxer</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Toca per veure\'n els detalls"</string>
-    <string name="retry" msgid="7564024179122207376">"Torna-ho a provar"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Aquests fitxers no s\'han copiat: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Aquests fitxers no s\'han mogut: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index 1430b70..ef2b554 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Zařízení"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Další aplikace"</string>
     <string name="empty" msgid="7858882803708117596">"Žádné položky"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s – žádné shody"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Soubor nelze otevřít"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Některé dokumenty nelze smazat"</string>
     <string name="share_via" msgid="8966594246261344259">"Sdílet pomocí"</string>
@@ -111,9 +110,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> souborů se smazat nepodařilo</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> soubor se smazat nepodařilo</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Klepnutím zobrazíte podrobnosti"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Opakovat"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Tyto soubory nebyly zkopírovány: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Následující soubory nebyly přesunuty: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -123,8 +122,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> soubor byl zkopírován do schránky.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Vybrané soubory nelze vložit do tohoto umístění."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Přejmenovat"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Dokument se nepodařilo přejmenovat."</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index 527b598..b80ec57 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> filer kunne ikke slettes</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Tryk for at se oplysninger"</string>
-    <string name="retry" msgid="7564024179122207376">"Prøv igen"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Disse filer blev ikke kopieret: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Følgende filer blev ikke flyttet: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index e40c15e..1363428 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Geräte"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Weitere Apps"</string>
     <string name="empty" msgid="7858882803708117596">"Keine Dokumente"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Keine Übereinstimmungen in %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Datei kann nicht geöffnet werden."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Einige Dokumente konnten nicht gelöscht werden."</string>
     <string name="share_via" msgid="8966594246261344259">"Teilen über"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> Dateien konnten nicht gelöscht werden</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> Datei konnte nicht gelöscht werden</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Zum Ansehen der Details tippen"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Erneut versuchen"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Diese Dateien wurden nicht kopiert: <xliff:g id="LIST">%1$s</xliff:g>."</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Diese Dateien wurden nicht verschoben: <xliff:g id="LIST">%1$s</xliff:g>."</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> Datei wurde in die Zwischenablage kopiert.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Die ausgewählten Dateien können an diesem Ort nicht eingefügt werden."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Umbenennen"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Dokument konnte nicht umbenannt werden"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 8a0db57..a1d28f5 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">Δεν ήταν δυνατή η διαγραφή <xliff:g id="COUNT_0">%1$d</xliff:g> αρχείου</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Πατήστε για προβολή λεπτομερειών"</string>
-    <string name="retry" msgid="7564024179122207376">"Επανάληψη"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Αυτά τα αρχεία δεν αντιγράφηκαν: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Αυτά τα αρχεία δεν μετακινήθηκαν: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index f75f322..ad4fafd 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Devices"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"More apps"</string>
     <string name="empty" msgid="7858882803708117596">"No items"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"No matches in %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Cannot open file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unable to delete some documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Couldn\'t delete <xliff:g id="COUNT_1">%1$d</xliff:g> files</item>
       <item quantity="one">Couldn\'t delete <xliff:g id="COUNT_0">%1$d</xliff:g> file</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tap to view details"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Retry"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"These files weren\'t copied: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"These files weren\'t moved: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Copied <xliff:g id="COUNT_0">%1$d</xliff:g> file to clipboard.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Cannot paste the selected files in this location."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"rename"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index f75f322..ad4fafd 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Devices"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"More apps"</string>
     <string name="empty" msgid="7858882803708117596">"No items"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"No matches in %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Cannot open file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unable to delete some documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Couldn\'t delete <xliff:g id="COUNT_1">%1$d</xliff:g> files</item>
       <item quantity="one">Couldn\'t delete <xliff:g id="COUNT_0">%1$d</xliff:g> file</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tap to view details"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Retry"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"These files weren\'t copied: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"These files weren\'t moved: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Copied <xliff:g id="COUNT_0">%1$d</xliff:g> file to clipboard.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Cannot paste the selected files in this location."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"rename"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index f75f322..ad4fafd 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Devices"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"More apps"</string>
     <string name="empty" msgid="7858882803708117596">"No items"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"No matches in %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Cannot open file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unable to delete some documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Share via"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Couldn\'t delete <xliff:g id="COUNT_1">%1$d</xliff:g> files</item>
       <item quantity="one">Couldn\'t delete <xliff:g id="COUNT_0">%1$d</xliff:g> file</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tap to view details"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Retry"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"These files weren\'t copied: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"These files weren\'t moved: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Copied <xliff:g id="COUNT_0">%1$d</xliff:g> file to clipboard.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Cannot paste the selected files in this location."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"rename"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index f85f991..53daa40 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Dispositivos"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Más aplicaciones"</string>
     <string name="empty" msgid="7858882803708117596">"Sin elementos"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"No hay coincidencias en %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"No se puede abrir el archivo."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"No es posible eliminar algunos documentos."</string>
     <string name="share_via" msgid="8966594246261344259">"Compartir mediante"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">No se pudieron borrar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos</item>
       <item quantity="one">No se pudo borrar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Presiona para ver los detalles"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Reintentar"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"No se copiaron estos archivos: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"No se movieron los siguientes archivos: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Se copió <xliff:g id="COUNT_0">%1$d</xliff:g> archivo al portapapeles.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"No se pueden pegar los archivos seleccionados en esta ubicación."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Cambiar nombre"</string>
+    <string name="rename_error" msgid="4203041674883412606">"No se pudo cambiar el nombre del documento"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 5ca8902..d55220c 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">No se ha podido eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Toca para ver detalles"</string>
-    <string name="retry" msgid="7564024179122207376">"Volver a intentar"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Archivos que no se han copiado: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Archivos que no se han movido: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 4594571..580e203 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> faili ei õnnestunud kustutada</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Puudutage üksikasjade vaatamiseks"</string>
-    <string name="retry" msgid="7564024179122207376">"Proovi uuesti"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Neid faile ei kopeeritud: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Neid faile ei teisaldatud: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index b8ed348..2dab78b 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">Ezin izan da ezabatu <xliff:g id="COUNT_0">%1$d</xliff:g> fitxategi</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Sakatu xehetasunak ikusteko"</string>
-    <string name="retry" msgid="7564024179122207376">"Saiatu berriro"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Ez dira kopiatu fitxategi hauek: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Ez dira mugitu fitxategi hauek: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index 778942b..2cfea03 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فایل حذف نشد</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"برای مشاهده جزئیات ضربه بزنید"</string>
-    <string name="retry" msgid="7564024179122207376">"امتحان مجدد"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"این فایل‌ها کپی نشدند: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"این فایل‌ها منتقل نشدند: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index e159bd8..b4ed0fd 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Laitteet"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Lisää sovelluksia"</string>
     <string name="empty" msgid="7858882803708117596">"Ei kohteita"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Ei osumia kohteessa %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Tiedostoa ei voi avata"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Joitakin asiakirjoja ei voi poistaa"</string>
     <string name="share_via" msgid="8966594246261344259">"Jaa sovelluksessa"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> tiedoston poistaminen epäonnistui</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> tiedoston poistaminen epäonnistui</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tarkastele tietoja napauttamalla"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Yritä uudelleen"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Seuraavia tiedostoja ei kopioitu: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Näitä tiedostoja ei siirretty: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> tiedosto kopioitiin leikepöydälle.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Valittuja tiedostoja ei voi liittää tähän sijaintiin."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Nimeä uudelleen"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Dokumentin nimen muuttaminen epäonnistui."</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index f2b515c..5bbc884 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Appareils"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Plus d\'applications"</string>
     <string name="empty" msgid="7858882803708117596">"Aucun élément"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Aucune correspondance dans %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Impossible d\'ouvrir le fichier"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Impossible de supprimer certains documents"</string>
     <string name="share_via" msgid="8966594246261344259">"Partager par"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Impossible de supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> dossier</item>
       <item quantity="other">Impossible de supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> dossiers</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Touchez pour afficher les détails"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Réessayer"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Ces fichiers ne ont pas été copiés : <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Ces fichiers n\'ont pas été déplacés : <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fichiers ont été copiés dans le presse-papiers.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Impossible de coller les fichiers sélectionnés à cet endroit."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Renommer"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Impossible de renommer le document"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index ad7b801..2e06b74 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Appareils"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Autres applications"</string>
     <string name="empty" msgid="7858882803708117596">"Aucun élément"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Aucune correspondance dans %1$s."</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Impossible d\'ouvrir le fichier."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Impossible de supprimer certains documents."</string>
     <string name="share_via" msgid="8966594246261344259">"Partager via"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Impossible de supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier</item>
       <item quantity="other">Impossible de supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Appuyez pour afficher plus d\'informations."</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Réessayer"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Les fichiers suivants n\'ont pas été copiés : <xliff:g id="LIST">%1$s</xliff:g>."</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Les fichiers suivants n\'ont pas été déplacés : <xliff:g id="LIST">%1$s</xliff:g>."</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fichiers ont bien été copiés dans le Presse-papiers.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Impossible de coller les fichiers sélectionnés à cet endroit."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Renommer"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Échec du changement de nom du document."</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index 7358860..5997e3d 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Dispositivos"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Máis aplicacións"</string>
     <string name="empty" msgid="7858882803708117596">"Ningún elemento"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Non hai coincidencias en %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Non se pode abrir o ficheiro"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Non se poden eliminar algúns documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Non se puideron eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros</item>
       <item quantity="one">Non se puido eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Toca para ver detalles"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Tentar de novo"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Non se copiaron estes ficheiros: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Non se moveron estes ficheiros: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Copiouse <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro no portapapeis.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Non se poden pegar os ficheiros seleccionados nesta localización."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Cambiar nome"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Non se puido cambiar o nome do documento"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index cc1d71c..f013e0f 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલ કાઢી નાખી શક્યાં નથી</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"વિગતો જોવા માટે ટૅપ કરો"</string>
-    <string name="retry" msgid="7564024179122207376">"ફરી પ્રયાસ કરો"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"આ ફાઇલો કૉપિ કરી નહોતી: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"આ ફાઇલો ખસેડી નહોતી: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index d20d1c1..008995e 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फ़ाइलें हटाई नहीं जा सकीं</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"विवरणों को देखने के लिए टैप करें"</string>
-    <string name="retry" msgid="7564024179122207376">"पुन: प्रयास करें"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"इन फ़ाइलों की कॉपी नहीं बनाई गई: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ये फ़ाइलें नहीं ले जाई गईं: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index 8ed0aa3..d6110a5 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Uređaji"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Više aplikacija"</string>
     <string name="empty" msgid="7858882803708117596">"Nema stavki"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s ne sadrži podudaranja"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Datoteku nije moguće otvoriti"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nije moguće izbrisati neke dokumente"</string>
     <string name="share_via" msgid="8966594246261344259">"Dijeli putem"</string>
@@ -105,9 +104,9 @@
       <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> datoteke nisu izbrisane</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> datoteka nije izbrisano</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Dodirnite da biste vidjeli pojedinosti"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Pokušaj ponovo"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Ove datoteke nisu kopirane: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Ove datoteke nisu premještene: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -116,8 +115,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> datoteka kopirano je u međuspremnik.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Nije moguće zalijepiti odabrane datoteke na ovu lokaciju."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Promijeni naziv"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Naziv dokumenta nije promijenjen"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index 8c1388c..139b834 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> fájlt nem sikerült törölni</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Koppintson rá a részletek megtekintéséhez"</string>
-    <string name="retry" msgid="7564024179122207376">"Újra"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"A következő fájlokat nem sikerült átmásolni: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"A következő fájlok nem lettek áthelyezve: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index cf9455f..8fc7e09 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Սարքեր"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Հավելյալ ծրագրեր"</string>
     <string name="empty" msgid="7858882803708117596">"Տարրեր չկան"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s-ում համընկնումներ չկան"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Հնարավոր չէ բացել ֆայլը"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Անհնար է ջնջել որոշ փաստաթղթեր"</string>
     <string name="share_via" msgid="8966594246261344259">"Տարածել"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Չհաջողվեց ջնջել <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ</item>
       <item quantity="other">Չհաջողվեց ջնջել <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Հպեք՝ մանրամասները դիտելու համար"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Կրկնել"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Հետևյալ ֆայլերը չեն պատճենվել՝ <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Հետևյալ ֆայլերը չեն տեղափոխվել՝ <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ պատճենվեց սեղմատախտակին:</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Հնարավոր չէ տեղադրել ընտրված ֆայլերը այս տեղադրությունում:"</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Վերանվանել"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Չհաջողվեց վերանվանել փաստաթուղթը"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 7c75e9c..0cb438a 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">Tidak dapat menghapus <xliff:g id="COUNT_0">%1$d</xliff:g> file</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Ketuk untuk melihat detail"</string>
-    <string name="retry" msgid="7564024179122207376">"Coba lagi"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Semua file ini tidak disalin: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Semua file ini tidak dipindahkan: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index a1962f6..efd3f7b 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Tæki"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Fleiri forrit"</string>
     <string name="empty" msgid="7858882803708117596">"Engin atriði"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Engar samsvarandi niðurstöður í %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Ekki er hægt að opna skrána"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Ekki er hægt að eyða einhverjum skjölum"</string>
     <string name="share_via" msgid="8966594246261344259">"Deila í gegnum"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Ekki tókst að eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrá</item>
       <item quantity="other">Ekki tókst að eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrám</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Ýttu til að skoða frekari upplýsingar"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Reyna aftur"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Þessar skrár voru ekki afritaðar: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Þessar skrár voru ekki færðar: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> skrár afritaðar á klippiborð.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Ekki er hægt að vista valdar skrár á þessum stað."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Endurnefna"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Ekki tókst að endurnefna skjalið"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 3f1d383..1b7506d 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">Impossibile eliminare <xliff:g id="COUNT_0">%1$d</xliff:g> file</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Tocca per vedere i dettagli"</string>
-    <string name="retry" msgid="7564024179122207376">"Riprova"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"I seguenti file non sono stati copiati: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"I seguenti file non sono stati spostati: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index b6e4170..ef966f4 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"מכשירים"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"עוד אפליקציות"</string>
     <string name="empty" msgid="7858882803708117596">"אין פריטים"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"‏אין התאמות ב-%1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"לא ניתן לפתוח את הקובץ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"לא ניתן למחוק חלק מהמסמכים"</string>
     <string name="share_via" msgid="8966594246261344259">"שתף באמצעות"</string>
@@ -111,9 +110,9 @@
       <item quantity="other">לא ניתן היה למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים</item>
       <item quantity="one">לא ניתן היה למחוק קובץ <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"הקש כדי להציג פרטים"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"נסה שוב"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"הקבצים הבאים לא הועתקו: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"הקבצים הבאים לא הועברו: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -123,8 +122,6 @@
       <item quantity="one">קובץ <xliff:g id="COUNT_0">%1$d</xliff:g> הועתק אל הלוח.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"לא ניתן להדביק את הקבצים הנבחרים במיקום הזה."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"שנה שם"</string>
+    <string name="rename_error" msgid="4203041674883412606">"ניסיון שינוי שם המסמך נכשל"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index 519903a..932e7fc 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"端末"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"その他のアプリ"</string>
     <string name="empty" msgid="7858882803708117596">"アイテムがありません"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"該当するものは %1$s にありません"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"ファイルを開けません"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"一部のドキュメントを削除できません"</string>
     <string name="share_via" msgid="8966594246261344259">"共有ツール"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個のファイルを削除できませんでした</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個のファイルを削除できませんでした</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"タップすると詳細が表示されます"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"再試行"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ファイル(<xliff:g id="LIST">%1$s</xliff:g>)をコピーできませんでした"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ファイル(<xliff:g id="LIST">%1$s</xliff:g>)を移動できませんでした"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>件のファイルをクリップボードにコピーしました。</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"選択したファイルをこの場所に貼り付けることはできません。"</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"名前を変更"</string>
+    <string name="rename_error" msgid="4203041674883412606">"ドキュメントの名前を変更できませんでした"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 8a89a3a..370e228 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"მოწყობილობები"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"მეტი აპები"</string>
     <string name="empty" msgid="7858882803708117596">"ერთეულები არ არის"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"„%1$s“-ში დამთხვევა ვერ მოიძებნა"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"ფაილის გახსნა ვერ ხერხდება"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ზოგიერთი დოკუმენტის წაშლა ვერ ხერხდება"</string>
     <string name="share_via" msgid="8966594246261344259">"გაზიარება:"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ფაილი ვერ წაიშალა</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ფაილი ვერ წაიშალა</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"შეეხეთ დეტალების სანახავად"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"ხელახლა ცდა"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ეს ფაილები არ იყო გადაწერილი: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ეს ფაილები ვერ გადაადგილდა: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">მოხდა <xliff:g id="COUNT_0">%1$d</xliff:g> ფაილის გაცვლის ბუფერში კოპირება.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"ამ მდებარეობაში შერჩეული ფაილების ჩასმა შეუძლებელია."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"გადარქმევა"</string>
+    <string name="rename_error" msgid="4203041674883412606">"დოკუმენტის გადარქმევა ვერ მოხერხდა"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index a0b8677..bea34c7 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Құрылғылар"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Басқа қолданбалар"</string>
     <string name="empty" msgid="7858882803708117596">"Бос"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s ішінде сәйкестіктер жоқ"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Файлды аша алмады"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Кейбір құжаттарды жою мүмкін болмады"</string>
     <string name="share_via" msgid="8966594246261344259">"Бөлісу"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды жою мүмкін болмады</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файлды жою мүмкін болмады</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Мәліметтерді көру үшін түртіңіз"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Қайталау"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Мына файлдар көшірілген жоқ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Мына файлдар тасымалданған жоқ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Аралық сақтағышқа <xliff:g id="COUNT_0">%1$d</xliff:g> файл көшірілді.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Таңдалған файлдарды бұл орынға қою мүмкін емес."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Атын өзгерту"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Құжат қайта аталмады"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index f83bce7..31b8816 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">មិនអាចលុបឯកសារ <xliff:g id="COUNT_0">%1$d</xliff:g> បានទេ</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"ប៉ះដើម្បីមើលព័ត៌មានលម្អិត"</string>
-    <string name="retry" msgid="7564024179122207376">"ព្យាយាមម្ដងទៀត"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ឯកសារទាំងនេះមិនបានចម្លងទេ៖ <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ឯកសារទាំងនេះមិនអាចផ្លាស់ទីបានទេ៖ <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index 6ba108e..ab4e90b 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"ಸಾಧನಗಳು"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"ಇನ್ನಷ್ಟು ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
     <string name="empty" msgid="7858882803708117596">"ಯಾವುದೇ ಐಟಂಗಳಿಲ್ಲ"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s ರಲ್ಲಿ ಯಾವುದೇ ಹೊಂದಾಣಿಕೆಗಳಿಲ್ಲ"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"ಫೈಲ್ ತೆರೆಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ಕೆಲವು ಡಾಕ್ಯುಮೆಂಟ್‌ಗಳನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
     <string name="share_via" msgid="8966594246261344259">"ಈ ಮೂಲಕ ಹಂಚಿಕೊಳ್ಳಿ"</string>
@@ -99,9 +98,9 @@
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ಅಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"ವಿವರಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"ಮರುಪ್ರಯತ್ನಿಸು"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ಈ ಫೈಲ್‌ಗಳನ್ನು ನಕಲು ಮಾಡಿಲ್ಲ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ಈ ಫೈಲ್‌ಗಳನ್ನು ಸರಿಸಲಾಗಿಲ್ಲ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other">ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ <xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ನಕಲಿಸಲಾಗಿದೆ.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"ಈ ಸ್ಥಳದಲ್ಲಿ ಆಯ್ಕೆಮಾಡಿದ ಫೈಲ್‌ಗಳನ್ನು ಅಂಟಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"ಮರುಹೆಸರಿಸು"</string>
+    <string name="rename_error" msgid="4203041674883412606">"ಡಾಕ್ಯುಮೆಂಟ್ ಮರುಹೆಸರಿಸಲು ವಿಫಲವಾಗಿದೆ"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 344d403..9bb596d 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">파일 <xliff:g id="COUNT_0">%1$d</xliff:g>개를 삭제할 수 없습니다.</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"세부정보를 보려면 탭하세요."</string>
-    <string name="retry" msgid="7564024179122207376">"다시 시도"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"다음 파일이 복사되지 않았습니다. <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"다음 파일이 이동되지 않았습니다. <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index e2411ce..c29fc45 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Түзмөктөр"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Көбүрөөк колдонмолор"</string>
     <string name="empty" msgid="7858882803708117596">"Эч нерсе жок"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s ичинде дал келүүлөр жок"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Файл ачылбады"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Кээ бир документтерди өчүрүү кыйрады"</string>
     <string name="share_via" msgid="8966594246261344259">"Кийинки аркылуу бөлүшүү:"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файл жок кылынбай койду</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файл жок кылынбай койду</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Чоо-жайын көрүү үчүн таптаңыз"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Дагы аракет кылуу"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Төмөнкү файлдар көчүрүлгөн жок: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Төмөнкү файлдар жылдырылган жок: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> файл буферге көчүрүлдү.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Тандалган файлдарды бул жерге чаптоого мүмкүн эмес."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Аталышын өзгөртүү"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Документтин аталышы өзгөртүлбөй калды"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index 3ea582f..223adae 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"ອຸປະກອນ"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"ແອັບຯອື່ນໆ"</string>
     <string name="empty" msgid="7858882803708117596">"ບໍ່ມີລາຍການ"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"ບໍ່ພົບສິ່ງກົງກັນໃນ %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"ບໍ່ສາມດາເປີດໄຟລ໌ໄດ້"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ບໍ່ສາມາດລຶບບາງເອກະສານໄດ້"</string>
     <string name="share_via" msgid="8966594246261344259">"ແບ່ງປັນຜ່ານ"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">ບໍ່​ສາ​ມາດ​ລຶບ <xliff:g id="COUNT_1">%1$d</xliff:g> ໄຟລ໌</item>
       <item quantity="one">ບໍ່ສາມາດລຶບ <xliff:g id="COUNT_0">%1$d</xliff:g> ໄຟລ໌</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດ"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"ລອງໃໝ່"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ໄຟ​ລ໌​ເຫຼົ່າ​ນີ້​ບໍ່​ຖື​ກ​ອັດ​ສຳ​ເນົາ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ໄຟ​ລ໌​ເຫຼົ່າ​ນີ້​ບໍ່​ຖືກ​ຍ້າຍ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">ອັດ​ສຳ​ເນົາ <xliff:g id="COUNT_0">%1$d</xliff:g> ໄຟ​ລ໌​ໃສ່​ຄ​ລິບບອດ​ແລ້ວ.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"ບໍ່​ສາ​ມາດ​ແປະ​ໄຟ​ລ໌​ເລືອກ​ໄວ້​ຢູ່​ໃນ​ທີ່​ຕັ້ງ​ນີ້​ໄດ້."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"ປ່ຽນຊື່"</string>
+    <string name="rename_error" msgid="4203041674883412606">"ປ່ຽນຊື່ເອກະສານບໍ່ສຳເລັດ"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index c52aaff..8993ffa 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -111,7 +111,8 @@
       <item quantity="other">Nepavyko ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failų</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Palieskite, kad peržiūrėtumėte informaciją"</string>
-    <string name="retry" msgid="7564024179122207376">"Bandyti dar kartą"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Šie failai nenukopijuoti: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Šie failai nebuvo perkelti: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 0252740..6544834 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Ierīces"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Vairāk lietotņu"</string>
     <string name="empty" msgid="7858882803708117596">"Nav vienumu"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Failā %1$s nav atbilstību"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Nevar atvērt failu."</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nevar dzēst dažus dokumentus."</string>
     <string name="share_via" msgid="8966594246261344259">"Kopīgot, izmantojot"</string>
@@ -105,9 +104,9 @@
       <item quantity="one">Nevarēja izdzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failu.</item>
       <item quantity="other">Nevarēja izdzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus.</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Pieskarieties, lai skatītu informāciju"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Mēģināt vēlreiz"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Netika nokopēti šādi faili: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Šie faili netika pārvietoti: <xliff:g id="LIST">%1$s</xliff:g>."</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -116,8 +115,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> faili tika kopēti starpliktuvē.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Atlasītos failus šeit nevar ielīmēt."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Pārdēvēt"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Neizdevās pārdēvēt dokumentu"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index a633c4a..ec2ab82 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Уреди"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Повеќе апликации"</string>
     <string name="empty" msgid="7858882803708117596">"Нема ставки"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Нема совпаѓања во %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Датотеката не се отвора"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Некои документи не може да се избришат"</string>
     <string name="share_via" msgid="8966594246261344259">"Сподели преку"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Не можеше да се избрише <xliff:g id="COUNT_1">%1$d</xliff:g> датотека</item>
       <item quantity="other">Не можеше да се избришат <xliff:g id="COUNT_1">%1$d</xliff:g> датотеки</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Допрете за да ги погледнете деталите"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Обидете се повторно"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Датотекиве не се ископирани: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Овие датотеки не се преместија: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other">Копирани се <xliff:g id="COUNT_1">%1$d</xliff:g> датотеки на таблата со исечоци.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Не може да ги залепи избраните датотеки на локацијава."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Преименувај"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Не успеа да се преименува документот"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index e722b02..6e23f6c 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ഫയൽ ഇല്ലാതാക്കാൻ കഴിഞ്ഞില്ല</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"വിശദാംശങ്ങൾ കാണുന്നതിന് ടാപ്പുചെയ്യുക"</string>
-    <string name="retry" msgid="7564024179122207376">"വീണ്ടും ശ്രമിക്കുക"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ഈ ഫയലുകൾ പകർത്താനായില്ല: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ഈ ഫയലുകളെ നീക്കിയില്ല: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -108,5 +109,5 @@
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"തിരഞ്ഞെടുത്ത ഫയലുകൾ ഈ ലൊക്കേഷനിൽ ഒട്ടിക്കാനാകുന്നില്ല."</string>
     <string name="menu_rename" msgid="7678802479104285353">"പേരുമാറ്റുക"</string>
-    <string name="rename_error" msgid="4203041674883412606">"ഡോക്യുമെന്റ് പേരുമാറ്റുന്നത് പരാജയപ്പെട്ടു"</string>
+    <string name="rename_error" msgid="4203041674883412606">"ഡോക്യുമെന്റിന്റെ പേരുമാറ്റുന്നത് പരാജയപ്പെട്ടു"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index e7ce4c5..137d5eb 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> файлыг устгаж чадсангүй</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Дэлгэрэнгүй мэдээллийг үзэхийн тулд дарна уу"</string>
-    <string name="retry" msgid="7564024179122207376">"Дахин оролдох"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Дараах файлуудыг хуулаагүй: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Эдгээр файлыг зөөвөрлөөгүй байна: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 0b56a26..babb452 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"डिव्हाइसेस"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"अधिक अ‍ॅप्‍स"</string>
     <string name="empty" msgid="7858882803708117596">"कोणतेही आयटम नाहीत"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s मध्‍ये कोणत्याही जुळण्‍या नाहीत"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"फाईल उघडू शकत नाही"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"काही दस्‍तऐवज हटविण्‍यात अक्षम"</string>
     <string name="share_via" msgid="8966594246261344259">"द्वारे सामायिक करा"</string>
@@ -99,9 +98,9 @@
       <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> फाईल हटविणे शक्य झाले नाही</item>
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> फायली हटविणे शक्य झाले नाही</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"तपशील पाहण्यासाठी टॅप करा"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"पुन्हा प्रयत्न करा"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"या फायली कॉपी झाल्या नाहीत: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"या फायली हलविल्या नव्हत्या: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other">क्लिपबोर्डवर <xliff:g id="COUNT_1">%1$d</xliff:g> फायली कॉपी केल्या.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"या स्थानामध्‍ये निवडलेल्‍या फायली पेस्ट करू शकत नाही."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"पुनर्नामित करा"</string>
+    <string name="rename_error" msgid="4203041674883412606">"दस्तऐवज पुनर्नामित करण्‍यात अयशस्वी झाले"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index a9cf815..5d0dbdf 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Peranti"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Lebih banyak apl"</string>
     <string name="empty" msgid="7858882803708117596">"Tiada item"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Tiada padanan dalam %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Tidak dapat membuka fail"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Tidak dapat memadam beberapa dokumen"</string>
     <string name="share_via" msgid="8966594246261344259">"Kongsi melalui"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Tidak dapat memadamkan <xliff:g id="COUNT_1">%1$d</xliff:g> fail</item>
       <item quantity="one">Tidak dapat memadamkan <xliff:g id="COUNT_0">%1$d</xliff:g> fail</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Ketik untuk melihat butiran"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Cuba semula"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Fail ini tidak disalin: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Fail ini tidak dialihkan: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> fail disalin ke papan keratan.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Tidak boleh menampalkan fail yang dipilih dalam lokasi ini."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Namakan semula"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Gagal menamakan semula dokumen"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 8fff7f0..0621d44 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">ဖိုင် <xliff:g id="COUNT_0">%1$d</xliff:g> ခုကိုဖျက်၍မရပါ</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"အသေးစိတ်ကြည့်ရန် တို့ပါ"</string>
-    <string name="retry" msgid="7564024179122207376">"ထပ်စမ်းရန်"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ဤဖိုင်များ ကော်ပီကူးမထားပါ- <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ဤဖိုင်များကို မရွှေ့ခဲ့ပါ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 8957258..c4a8e2a 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Enheter"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Flere apper"</string>
     <string name="empty" msgid="7858882803708117596">"Ingen elementer"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Ingen treff i %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Kan ikke åpne filen"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Enkelte dokumenter kunne ikke slettes"</string>
     <string name="share_via" msgid="8966594246261344259">"Del via"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Kunne ikke slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer</item>
       <item quantity="one">Kunne ikke slette <xliff:g id="COUNT_0">%1$d</xliff:g> fil</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Trykk for å se detaljer"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Prøv på nytt"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Disse filene ble ikke kopiert: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Disse filene ble ikke flyttet: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Kopierte <xliff:g id="COUNT_0">%1$d</xliff:g> fil til utklippstavlen.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Kan ikke lime inn de valgte filene her."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Gi nytt navn"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Kunne ikke gi dokumentet nytt navn"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index c847e67..a40edc7 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> फाइल मेट्न सकेन</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"विवरणहरू हेर्न ट्याप गर्नुहोस्"</string>
-    <string name="retry" msgid="7564024179122207376">"पुनःप्रयास गर्नुहोस्"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"यी फाइलहरू प्रतिलिपि गरिएको थिएनः <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"यी फाइलहरू सारिएनन्: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index dd12aa5..eecc871 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">Kan <xliff:g id="COUNT_0">%1$d</xliff:g> bestand niet verwijderen</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Tik om details te bekijken"</string>
-    <string name="retry" msgid="7564024179122207376">"Opnieuw proberen"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Deze bestanden zijn niet gekopieerd: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Deze bestanden zijn niet verplaatst: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 00f7a8a..075ca4d 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਨੂੰ ਮਿਟਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"ਵੇਰਵਿਆਂ ਨੂੰ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
-    <string name="retry" msgid="7564024179122207376">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਦੀ ਪ੍ਰਤੀਲਿਪੀ ਨਹੀਂ ਬਣਾਈ ਗਈ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਨੂੰ ਮੂਵ ਨਹੀਂ ਕੀਤਾ ਗਿਆ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 71a7c0ae..3c86b7b 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Urządzenia"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Więcej aplikacji"</string>
     <string name="empty" msgid="7858882803708117596">"Brak elementów"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Brak wyników w %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Nie można otworzyć pliku"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nie można usunąć niektórych dokumentów"</string>
     <string name="share_via" msgid="8966594246261344259">"Udostępnij przez:"</string>
@@ -111,9 +110,9 @@
       <item quantity="other">Nie udało się usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliku</item>
       <item quantity="one">Nie udało się usunąć <xliff:g id="COUNT_0">%1$d</xliff:g> pliku</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Kliknij, by zobaczyć szczegóły"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Ponów"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Te pliki nie zostały skopiowane: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Te pliki nie zostały przeniesione: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -123,8 +122,6 @@
       <item quantity="one">Skopiowano <xliff:g id="COUNT_0">%1$d</xliff:g> plik do schowka.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Nie można wkleić wybranych plików w tej lokalizacji."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Zmień nazwę"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Nie udało się zmienić nazwy dokumentu"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index b30233d..186569c 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Dispositivos"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Mais apps"</string>
     <string name="empty" msgid="7858882803708117596">"Nenhum item"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Nenhum resultado em %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Não é possível abrir o arquivo"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Não foi possível excluir alguns documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Não foi possível excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos</item>
       <item quantity="other">Não foi possível excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tocar para ver detalhes"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Repetir"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Estes arquivos não foram copiados: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Estes arquivos não foram movidos: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> arquivos copiados para a área de transferência.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Não é possível colar os arquivos selecionados neste local."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Renomear"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 59ae4ae..961330e 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Dispositivos"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Mais aplicações"</string>
     <string name="empty" msgid="7858882803708117596">"Sem itens"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Sem correspondências para %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Não é possível abrir o ficheiro"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Não é possível eliminar alguns documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Partilhar através de"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Não foi possível eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros</item>
       <item quantity="one">Não foi possível eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Toque para ver detalhes"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Tentar novamente"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Os seguintes ficheiros não foram copiados: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Os seguintes ficheiros não foram movidos: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">Copiou <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro para a área de transferência.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Não é possível colar os ficheiros selecionados nesta localização."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Mudar o nome"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Falha ao mudar o nome do documento"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index b30233d..186569c 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Dispositivos"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Mais apps"</string>
     <string name="empty" msgid="7858882803708117596">"Nenhum item"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Nenhum resultado em %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Não é possível abrir o arquivo"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Não foi possível excluir alguns documentos"</string>
     <string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Não foi possível excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos</item>
       <item quantity="other">Não foi possível excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tocar para ver detalhes"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Repetir"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Estes arquivos não foram copiados: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Estes arquivos não foram movidos: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> arquivos copiados para a área de transferência.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Não é possível colar os arquivos selecionados neste local."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Renomear"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 92343c5..4ba7618 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Dispozitive"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Alte aplicații"</string>
     <string name="empty" msgid="7858882803708117596">"Nu există elemente"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Niciun rezultat în %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Fișierul nu poate fi deschis"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Unele documente nu au putut fi șterse"</string>
     <string name="share_via" msgid="8966594246261344259">"Trimiteți prin"</string>
@@ -105,9 +104,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> de fișiere nu au fost șterse</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> fișier nu a fost șters</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Atingeți pentru a vedea detaliile"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Reîncercați"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Aceste fișiere nu au fost copiate: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Aceste fișiere nu au fost mutate: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -116,8 +115,6 @@
       <item quantity="one">A fost copiat <xliff:g id="COUNT_0">%1$d</xliff:g> fișier în clipboard.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Fișierele selectate nu au putut fi inserate în această locație."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Redenumiți"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Documentul nu a putut fi redenumit"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 2b9629a2..924473a 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Устройства"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Другие приложения"</string>
     <string name="empty" msgid="7858882803708117596">"Ничего нет"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"В \"%1$s\" ничего не найдено"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Не удалось открыть файл"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Не удалось удалить некоторые документы"</string>
     <string name="share_via" msgid="8966594246261344259">"Поделиться"</string>
@@ -111,9 +110,9 @@
       <item quantity="many">Не удалось удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файлов</item>
       <item quantity="other">Не удалось удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Нажмите, чтобы узнать подробности."</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Повторить"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Не удалось скопировать эти файлы: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Эти файлы не были перемещены: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -123,8 +122,6 @@
       <item quantity="other">Скопированы <xliff:g id="COUNT_1">%1$d</xliff:g> файла</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Не удается вставить сюда выбранные файлы"</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Переименовать"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Не удалось переименовать документ"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index 60e964f..382bed1 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g>ක් මැකීමට නොහැකි විය</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"විස්තර බැලීමට තට්ටු කරන්න"</string>
-    <string name="retry" msgid="7564024179122207376">"නැවත උත්සාහ කරන්න"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"මෙම ගොනු පිටපත් නොකරන ලදී: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"මෙම ගොනු ගෙන නොයන ලදී: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 40b0863..882f513 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -111,7 +111,8 @@
       <item quantity="one">Nepodarilo sa odstrániť <xliff:g id="COUNT_0">%1$d</xliff:g> súbor</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Klepnutím zobrazíte podrobnosti"</string>
-    <string name="retry" msgid="7564024179122207376">"Skúsiť znova"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Tieto súbory neboli skopírované: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Tieto súbory neboli presunuté: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index 60abaee..154fdb2 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Naprave"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Več aplikacij"</string>
     <string name="empty" msgid="7858882803708117596">"Ni elementov"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Tukaj ni ujemanj: %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Datoteke ni mogoče odpreti"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Nekaterih dokumentov ni mogoče izbrisati"</string>
     <string name="share_via" msgid="8966594246261344259">"Deli z drugimi prek"</string>
@@ -111,9 +110,9 @@
       <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> datotek ni bilo mogoče izbrisati</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> datotek ni bilo mogoče izbrisati</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Dotaknite se za prikaz podrobnosti"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Poskusi znova"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Te datoteke niso bile kopirane: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Te datoteke niso bile premaknjene: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -123,8 +122,6 @@
       <item quantity="other">V odložišče je bilo kopiranih <xliff:g id="COUNT_1">%1$d</xliff:g> datotek.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Izbranih datotek ni mogoče prilepiti sem."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Dokumenta ni bilo mogoče preimenovati"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 0062e82..bcb4ff0 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Pajisjet"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Aplikacione të tjera"</string>
     <string name="empty" msgid="7858882803708117596">"Nuk ka artikuj"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Nuk ka asnjë përputhje në %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Skedari nuk mund të hapet"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"E pamundur të fshihen disa dokumente"</string>
     <string name="share_via" msgid="8966594246261344259">"Shpërnda publikisht përmes"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> skedarë nuk mund të fshiheshin</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> skedar nuk mund të fshihej</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Trokit për të parë detajet"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Provo përsëri"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Këta skedarë nuk u kopjuan: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Këta skedarë nuk u zhvendosën: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">U kopjua <xliff:g id="COUNT_0">%1$d</xliff:g> skedar në kujtesën e fragmenteve.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Skedarët e zgjedhur nuk mund të ngjiten në këtë vendndodhje."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Riemërto"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Riemërtimi i dokumentit dështoi"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index 403ae93..c0f8099 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Уређаји"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Још апликација"</string>
     <string name="empty" msgid="7858882803708117596">"Нема ставки"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Нема подударања у %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Није могуће отворити датотеку"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Није могуће избрисати неке документе"</string>
     <string name="share_via" msgid="8966594246261344259">"Делите преко"</string>
@@ -105,9 +104,9 @@
       <item quantity="few">Брисање <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке није успело</item>
       <item quantity="other">Брисање <xliff:g id="COUNT_1">%1$d</xliff:g> датотека није успело</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Додирните да бисте приказали детаље"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Покушај поново"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Следеће датотеке нису копиране: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Ове датотеке нису премештене: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -116,8 +115,6 @@
       <item quantity="other">Копирали сте <xliff:g id="COUNT_1">%1$d</xliff:g> датотека у привремену меморију.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Изабране датотеке не могу да се налепе на овој локацији."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Преименуј"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Преименовање документа није успело"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 50c5beb..e9af1f9 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Enheter"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Fler appar"</string>
     <string name="empty" msgid="7858882803708117596">"Inga objekt"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Det finns inga träffar i %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Det går inte att öppna filen"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Det gick inte att ta bort vissa dokument"</string>
     <string name="share_via" msgid="8966594246261344259">"Dela via"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">Det gick inte att radera <xliff:g id="COUNT_1">%1$d</xliff:g> filer</item>
       <item quantity="one">Det gick inte att radera <xliff:g id="COUNT_0">%1$d</xliff:g> fil</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Tryck om du vill visa informationen"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Försök igen"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Följande filer kopierades inte: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Följande filer har inte flyttats: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> fil har kopierats till Urklipp.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Det går inte att klistra in den valda filen på den här platsen."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Byt namn"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Det gick inte att byta namn på dokumentet"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index 875ffd4..188f5b5 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">Haikuweza kufuta faili <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Gonga ili uangalie maelezo"</string>
-    <string name="retry" msgid="7564024179122207376">"Jaribu tena"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Faili hizi hazikunakiliwa: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Faili hizi hazikuhamishwa: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 1a05053..a6d52c4 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"சாதனங்கள்"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"மேலும் பயன்பாடுகள்"</string>
     <string name="empty" msgid="7858882803708117596">"எதுவும் இல்லை"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s இல் பொருந்தும் முடிவு இல்லை"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"கோப்பைத் திறக்க முடியவில்லை"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"சில ஆவணங்களை நீக்க முடியவில்லை"</string>
     <string name="share_via" msgid="8966594246261344259">"இதன் வழியாகப் பகிர்"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> கோப்புகளை நீக்க முடியவில்லை</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> கோப்பை நீக்க முடியவில்லை</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"விவரங்களைப் பார்க்க, தட்டவும்"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"மீண்டும் முயற்சிக்கவும்"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"நகலெடுக்கப்படாத கோப்புகள்: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"இந்தக் கோப்புகள் நகர்த்தப்படவில்லை: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">கிளிப்போர்டிற்கு <xliff:g id="COUNT_0">%1$d</xliff:g> கோப்பு நகலெடுக்கப்பட்டது.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"தேர்ந்தெடுத்த கோப்புகளை இங்கு ஒட்ட முடியாது."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"மறுபெயரிடு"</string>
+    <string name="rename_error" msgid="4203041674883412606">"ஆவணத்திற்கு மறுபெயரிடுவதில் தோல்வி"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index 71b92f4..b2ac712 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ఫైల్‌ను తొలగించడం సాధ్యపడలేదు</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"వివరాలను వీక్షించడానికి నొక్కండి"</string>
-    <string name="retry" msgid="7564024179122207376">"మళ్లీ ప్రయత్నించు"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ఈ ఫైల్‌లు కాపీ చేయబడలేదు: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ఈ ఫైల్‌లు తరలించబడలేదు: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 1e90bc5..3261019 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"อุปกรณ์"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"แอปเพิ่มเติม"</string>
     <string name="empty" msgid="7858882803708117596">"ไม่มีรายการ"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"ไม่พบข้อมูลที่ตรงกันใน %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"ไม่สามารถเปิดไฟล์ได้"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"ไม่สามารถลบเอกสารบางรายการ"</string>
     <string name="share_via" msgid="8966594246261344259">"แชร์ผ่าน"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">ไม่สามารถลบ <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์</item>
       <item quantity="one">ไม่สามารถลบ <xliff:g id="COUNT_0">%1$d</xliff:g> ไฟล์</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"แตะเพื่อดูรายละเอียด"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"ลองอีกครั้ง"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"ไม่มีการคัดลอกไฟล์เหล่านี้: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"ไม่มีการย้ายไฟล์เหล่านี้: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">คัดลอก <xliff:g id="COUNT_0">%1$d</xliff:g> ไฟล์ไปยังคลิปบอร์ดแล้ว</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"ไม่สามารถวางไฟล์ที่เลือกในตำแหน่งนี้"</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"เปลี่ยนชื่อ"</string>
+    <string name="rename_error" msgid="4203041674883412606">"ไม่สามารถเปลี่ยนชื่อเอกสาร"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index 971186c..6548908 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Mga Device"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Higit pang apps"</string>
     <string name="empty" msgid="7858882803708117596">"Walang mga item"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"Walang mga katugma sa %1$s"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Hindi mabuksan ang file"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Hindi matanggal ang ilang dokumento"</string>
     <string name="share_via" msgid="8966594246261344259">"Ibahagi sa pamamagitan ng"</string>
@@ -99,9 +98,9 @@
       <item quantity="one">Hindi ma-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> file</item>
       <item quantity="other">Hindi ma-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> na file</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"I-tap upang tingnan ang mga detalye"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Subukang muli"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Hindi nakopya ang mga file na ito: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Hindi nailipat ang mga file na ito: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="other">Nakopya ang <xliff:g id="COUNT_1">%1$d</xliff:g> na file sa clipboard.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Hindi mai-paste sa lokasyong ito ang mga piniling file."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Palitan ang pangalan"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Hindi napalitan ang pangalan ng dokumento"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index 720f6bc..2db4a1b 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Cihazlar"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Diğer uygulamalar"</string>
     <string name="empty" msgid="7858882803708117596">"Öğe yok"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s içinde eşleşme bulunamadı"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Dosya açılamıyor"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Bazı dokümanlar silinemiyor"</string>
     <string name="share_via" msgid="8966594246261344259">"Şunu kullanarak paylaş:"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosya silinemedi</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dosya silinemedi</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Ayrıntıları görmek için hafifçe dokunun"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Yeniden dene"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Şu dosyalar kopyalanmadı: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Şu dosyalar taşınmadı: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dosya panoya kopyalandı.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Seçili dosyalar bu konuma yapıştırılamıyor."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Yeniden Adlandır"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Dokümanın adı değiştirilemedi"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 8aeda26..8624aec 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -111,7 +111,8 @@
       <item quantity="other">Не вдалося видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файлу</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Торкніться, щоб переглянути деталі"</string>
-    <string name="retry" msgid="7564024179122207376">"Повторити"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Ці файли не скопійовано: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Не переміщено ці файли: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index cf74224..6ddad5f 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"آلات"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"مزید ایپس"</string>
     <string name="empty" msgid="7858882803708117596">"کوئی آئٹمز نہيں ہیں"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"‏%1$s میں کوئی مماثل نہیں"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"فائل نہيں کھول سکتے ہیں"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"کچھ دستاویزات کو حذف کرنے سے قاصر"</string>
     <string name="share_via" msgid="8966594246261344259">"اشتراک کریں بذریعہ"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں حذف نہیں ہو سکیں</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> فائل حذف نہیں ہو سکی</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"تفصیلات دیکھنے کیلئے تھپتھپائیں"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"دوبارہ کوشش کریں"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"یہ فائلز کاپی نہیں کی گئیں: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"یہ فائلیں منتقل نہیں ہوئیں: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> فائل کلپ بورڈ پر کاپی کی گئی۔</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"منتخب کردہ فائلز کو اس مقام پر پیسٹ نہیں کیا جا سکتا۔"</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"نام تبدیل کریں"</string>
+    <string name="rename_error" msgid="4203041674883412606">"دستاویز کا نام تبدیل کرنے میں ناکام"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index e51cab8..78e48c6 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"Qurilmalar"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Ko‘proq dasturlar"</string>
     <string name="empty" msgid="7858882803708117596">"Hech narsa yo‘q"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s jildidan topilmadi"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Fayl ochilmadi"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"Ba’zi hujjatlar o‘chirilmadi"</string>
     <string name="share_via" msgid="8966594246261344259">"Quyidagi orqali ulashish"</string>
@@ -99,9 +98,9 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta faylni o‘chirib bo‘lmadi</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta faylni o‘chirib bo‘lmadi</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"Batafsil ma’lumot olish uchun bosing"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"Qayta urinish"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Ushbu fayllardan nusxa olinmadi: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Ushbu fayllar ko‘chirib o‘tkazilmadi: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta fayldan vaqtinchalik xotiraga nusxa olindi.</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"Tanlangan fayllarni bu yerga joylab bo‘lmadi."</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"Qayta nomlash"</string>
+    <string name="rename_error" msgid="4203041674883412606">"Hujjatni qayta nomlab bo‘lmadi"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index f418334..3f44f62 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">Không thể xóa <xliff:g id="COUNT_0">%1$d</xliff:g> tệp</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Nhấn để xem chi tiết"</string>
-    <string name="retry" msgid="7564024179122207376">"Thử lại"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Những tệp này chưa được sao chép: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Những tệp này chưa được di chuyển: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 7f8f2fd..c8b4a82 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -63,8 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"设备"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"更多应用"</string>
     <string name="empty" msgid="7858882803708117596">"无任何文件"</string>
-    <!-- no translation found for no_results (6622510343880730446) -->
-    <skip />
+    <string name="no_results" msgid="6622510343880730446">"%1$s中没有任何相符项"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"无法打开文件"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"无法删除部分文档"</string>
     <string name="share_via" msgid="8966594246261344259">"分享方式"</string>
@@ -99,9 +98,9 @@
       <item quantity="other">无法删除 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件</item>
       <item quantity="one">无法删除 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件</item>
     </plurals>
-    <!-- no translation found for notification_touch_for_details (6268189413228855582) -->
+    <string name="notification_touch_for_details" msgid="6268189413228855582">"点按即可查看详情"</string>
+    <!-- no translation found for close (3043722427445528732) -->
     <skip />
-    <string name="retry" msgid="7564024179122207376">"重试"</string>
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"以下文件无法复制:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"以下文件无法移动:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
@@ -109,8 +108,6 @@
       <item quantity="one">已将 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件复制到剪贴板。</item>
     </plurals>
     <string name="clipboard_files_cannot_paste" msgid="2878324825602325706">"无法将所选文件粘贴到此位置。"</string>
-    <!-- no translation found for menu_rename (7678802479104285353) -->
-    <skip />
-    <!-- no translation found for rename_error (4203041674883412606) -->
-    <skip />
+    <string name="menu_rename" msgid="7678802479104285353">"重命名"</string>
+    <string name="rename_error" msgid="4203041674883412606">"无法重命名文档"</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index 1a4ffde..46c1be3 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -63,7 +63,7 @@
     <string name="root_type_device" msgid="7121342474653483538">"裝置"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"更多應用程式"</string>
     <string name="empty" msgid="7858882803708117596">"沒有項目"</string>
-    <string name="no_results" msgid="6622510343880730446">"沒有與「%1$s」相符的結果"</string>
+    <string name="no_results" msgid="6622510343880730446">"「%1$s」中沒有相符結果"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"無法開啟檔案"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"無法刪除部分文件"</string>
     <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
@@ -99,7 +99,8 @@
       <item quantity="one">無法刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"輕按即可查看詳細資訊"</string>
-    <string name="retry" msgid="7564024179122207376">"重試"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"以下檔案未能複製:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"這些檔案並未移動:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index b48951f..1502176 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="one">無法刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案</item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"輕按即可查看詳細資訊"</string>
-    <string name="retry" msgid="7564024179122207376">"重試"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"未複製這些檔案:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"未移動以下檔案:<xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index 0e2d6fd..44f82cf 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -99,7 +99,8 @@
       <item quantity="other">Ayikwazanga ukususa amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g></item>
     </plurals>
     <string name="notification_touch_for_details" msgid="6268189413228855582">"Thepha ukuze ubuke imininingwane"</string>
-    <string name="retry" msgid="7564024179122207376">"Zama futhi"</string>
+    <!-- no translation found for close (3043722427445528732) -->
+    <skip />
     <string name="copy_failure_alert_content" msgid="3715575000297709082">"Lawa mafayela awazange akopishwe: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <string name="move_failure_alert_content" msgid="7151140279020481180">"Lawa mafayela awazange ahanjiswe: <xliff:g id="LIST">%1$s</xliff:g>"</string>
     <plurals name="clipboard_files_clipped" formatted="false" msgid="855459017537058539">
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ff28e15..e8d8c8e 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -18,7 +18,6 @@
     <!-- Allow Advanced Devices default value to be customised -->
     <bool name="config_defaultAdvancedDevices">false</bool>
 
-    <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/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 5a9bc16..afe9336 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -65,13 +65,9 @@
     <string name="menu_paste_from_clipboard">Paste</string>
 
     <!-- Menu item that reveals internal storage built into the device [CHAR LIMIT=24] -->
-    <string name="menu_advanced_show" product="nosdcard">Show internal storage</string>
-    <!-- Menu item that reveals SD cards built into the device [CHAR LIMIT=24] -->
-    <string name="menu_advanced_show" product="default">Show SD card</string>
+    <string name="menu_advanced_show">Show internal storage</string>
     <!-- Menu item that hides internal storage built into the device [CHAR LIMIT=24] -->
-    <string name="menu_advanced_hide" product="nosdcard">Hide internal storage</string>
-    <!-- Menu item that hides SD cards built into the device [CHAR LIMIT=24] -->
-    <string name="menu_advanced_hide" product="default">Hide SD card</string>
+    <string name="menu_advanced_hide">Hide internal storage</string>
 
     <!-- Menu item that reveals the sizes of displayed files [CHAR LIMIT=24] -->
     <string name="menu_file_size_show">Show file size</string>
@@ -185,6 +181,8 @@
     <string name="copy_failure_alert_content">These files weren\'t copied: <xliff:g id="list">%1$s</xliff:g></string>
     <!-- Contents of the moving failure alert dialog. [CHAR LIMIT=48] -->
     <string name="move_failure_alert_content">These files weren\'t moved: <xliff:g id="list">%1$s</xliff:g></string>
+    <!-- Contents of the copying warning dialog due to converted files. [CHAR LIMIT=64] -->
+    <string name="copy_converted_warning_content">These files were converted to another format: <xliff:g id="list" example="Document.pdf, Photo.jpg, Song.ogg">%1$s</xliff:g></string>
     <!-- Toast shown when a user copies files to clipboard. -->
     <plurals name="clipboard_files_clipped">
         <item quantity="one">Copied <xliff:g id="count" example="1">%1$d</xliff:g> file to clipboard.</item>
@@ -196,4 +194,16 @@
     <string name="menu_rename">Rename</string>
     <!-- Toast shown when renaming document failed with an error [CHAR LIMIT=48] -->
     <string name="rename_error">Failed to rename document</string>
+    <!-- First line for notifications saying that some files were converted to a different format
+         during a copy. [CHAR LIMIT=48] -->
+    <string name="notification_copy_files_converted_title">Some files were converted</string>
+
+    <!--  DO NOT TRANSLATE - final phrase has not been decided yet (b/26750152) -->
+    <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
+        access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> folder on
+        <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string>
+    <!-- Text in the button asking user to allow access to a given directory. -->
+    <string name="allow">Allow</string>
+    <!-- Text in the button asking user to deny access to a given directory. -->
+    <string name="deny">Deny</string>
 </resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index d14631d..f4dfd73 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -45,4 +45,8 @@
         <item name="android:maxHeight">3dp</item>    
     </style>
 
+    <!--  TODO: use the proper dialog and/or inline if not overriding -->
+    <style name="AlertDialogTheme" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
+    </style>
+
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index ad8b0d1..9309693 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -17,11 +17,13 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.State.MODE_GRID;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_DOWN;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_SIDE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_UP;
 import static com.android.internal.util.Preconditions.checkArgument;
+import static com.android.internal.util.Preconditions.checkState;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -51,8 +53,8 @@
 import android.widget.TextView;
 
 import com.android.documentsui.RecentsProvider.ResumeColumns;
-import com.android.documentsui.SearchManager;
 import com.android.documentsui.SearchManager.SearchManagerListener;
+import com.android.documentsui.State.ViewMode;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.DocumentStack;
@@ -102,7 +104,6 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        mProductivityDevice = getResources().getBoolean(R.bool.productivity_device);
         mState = (icicle != null)
                 ? icicle.<State>getParcelable(EXTRA_STATE)
                         : buildState();
@@ -204,6 +205,8 @@
     void onStackRestored(boolean restored, boolean external) {}
 
     void onRootPicked(RootInfo root) {
+        mState.derivedMode = LocalPreferences.getViewMode(this, root, MODE_GRID);
+
         // Clear entire backstack and start in new root
         mState.onRootChanged(root);
         mSearchManager.update(root);
@@ -260,11 +263,11 @@
                 return true;
 
             case R.id.menu_grid:
-                setUserMode(State.MODE_GRID);
+                setViewMode(State.MODE_GRID);
                 return true;
 
             case R.id.menu_list:
-                setUserMode(State.MODE_LIST);
+                setViewMode(State.MODE_LIST);
                 return true;
 
             case R.id.menu_paste_from_clipboard:
@@ -419,24 +422,27 @@
         invalidateOptionsMenu();
     }
 
-    public void onStateChanged() {
-        invalidateOptionsMenu();
-    }
-
     /**
      * Set state sort order based on explicit user action.
      */
     void setUserSortOrder(int sortOrder) {
         mState.userSortOrder = sortOrder;
-        DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
+        DirectoryFragment.get(getFragmentManager()).onSortOrderChanged();
     }
 
     /**
-     * Set state mode based on explicit user action.
+     * Set mode based on explicit user action.
      */
-    void setUserMode(int mode) {
-        mState.userMode = mode;
-        DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
+    void setViewMode(@ViewMode int mode) {
+        checkState(mState.stack.root != null);
+        LocalPreferences.setViewMode(this, mState.stack.root, mode);
+        mState.derivedMode = mode;
+
+        // view icon needs to be updated, but we *could* do it
+        // in onOptionsItemSelected, and not do the full invalidation
+        // But! That's a larger refactoring we'll save for another day.
+        invalidateOptionsMenu();
+        DirectoryFragment.get(getFragmentManager()).onViewModeChanged();
     }
 
     public void setPending(boolean pending) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 6719b23..b0542b9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -16,11 +16,11 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.Shared.TAG;
 import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME;
 import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
 import static com.android.documentsui.State.SORT_ORDER_SIZE;
-import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 
 import android.content.AsyncTaskLoader;
 import android.content.ContentProviderClient;
@@ -35,7 +35,6 @@
 import android.provider.DocumentsContract.Document;
 import android.util.Log;
 
-import com.android.documentsui.RecentsProvider.StateColumns;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
@@ -52,10 +51,10 @@
 
     private final int mType;
     private final RootInfo mRoot;
-    private DocumentInfo mDoc;
     private final Uri mUri;
     private final int mUserSortOrder;
 
+    private DocumentInfo mDoc;
     private CancellationSignal mSignal;
     private DirectoryResult mResult;
 
@@ -64,9 +63,9 @@
         super(context, ProviderExecutor.forAuthority(root.authority));
         mType = type;
         mRoot = root;
-        mDoc = doc;
         mUri = uri;
         mUserSortOrder = userSortOrder;
+        mDoc = doc;
     }
 
     @Override
@@ -83,8 +82,6 @@
 
         final DirectoryResult result = new DirectoryResult();
 
-        int userMode = State.MODE_UNKNOWN;
-
         // Use default document when searching
         if (mType == DirectoryFragment.TYPE_SEARCH) {
             final Uri docUri = DocumentsContract.buildDocumentUri(
@@ -98,25 +95,6 @@
             }
         }
 
-        // Pick up any custom modes requested by user
-        Cursor cursor = null;
-        try {
-            final Uri stateUri = RecentsProvider.buildState(
-                    mRoot.authority, mRoot.rootId, mDoc.documentId);
-            cursor = resolver.query(stateUri, null, null, null, null);
-            if (cursor.moveToFirst()) {
-                userMode = getCursorInt(cursor, StateColumns.MODE);
-            }
-        } finally {
-            IoUtils.closeQuietly(cursor);
-        }
-
-        if (userMode != State.MODE_UNKNOWN) {
-            result.mode = userMode;
-        } else {
-            result.mode = State.MODE_GRID;
-        }
-
         if (mUserSortOrder != State.SORT_ORDER_UNKNOWN) {
             result.sortOrder = mUserSortOrder;
         } else {
@@ -132,13 +110,13 @@
             result.sortOrder = State.SORT_ORDER_UNKNOWN;
         }
 
-        Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
-                + result.mode + ", sortOrder=" + result.sortOrder);
+        if (DEBUG)
+                Log.d(TAG, "userSortOrder=" + mUserSortOrder + ", sortOrder=" + result.sortOrder);
 
         ContentProviderClient client = null;
+        Cursor cursor = null;
         try {
             client = DocumentsApplication.acquireUnstableProviderOrThrow(resolver, authority);
-
             cursor = client.query(
                     mUri, null, null, null, getQuerySortOrder(result.sortOrder), mSignal);
             if (cursor == null) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
index e7e4f73..22e438a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
@@ -29,7 +29,6 @@
     public Cursor cursor;
     public Exception exception;
 
-    public int mode = MODE_UNKNOWN;
     public int sortOrder = SORT_ORDER_UNKNOWN;
 
     @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 6dcd472..c3395ae 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -346,11 +346,13 @@
             } else {
                 DirectoryFragment.showRecentsOpen(fm, anim);
 
-                // Start recents in grid when requesting visual things
-                final boolean visualMimes = MimePredicate.mimeMatches(
+                // In recents we pick layout mode based on the mimetype,
+                // picking GRID for visual types. We intentionally don't
+                // consult a user's saved preferences here since they are
+                // set per root (not per root and per mimetype).
+                boolean visualMimes = MimePredicate.mimeMatches(
                         MimePredicate.VISUAL_MIMES, mState.acceptMimes);
-                mState.userMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
-                mState.derivedMode = mState.userMode;
+                mState.derivedMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
             }
         } else {
             if (mSearchManager.isSearching()) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FailureDialogFragment.java b/packages/DocumentsUI/src/com/android/documentsui/FailureDialogFragment.java
deleted file mode 100644
index b8ef5ac..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/FailureDialogFragment.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import static com.android.internal.util.Preconditions.checkArgument;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.text.Html;
-
-import com.android.documentsui.model.DocumentInfo;
-import com.android.documentsui.model.DocumentStack;
-import com.android.documentsui.services.FileOperationService;
-import com.android.documentsui.services.FileOperations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Alert dialog for failed operations.
- */
-public class FailureDialogFragment extends DialogFragment {
-    private static final String TAG = "FailureDialogFragment";
-
-    public static void show(FragmentManager fm, int failure,
-            ArrayList<DocumentInfo> failedSrcList, DocumentStack dstStack, int operationType) {
-        // TODO: Add support for other failures than copy.
-        if (failure != FileOperationService.FAILURE_COPY) {
-            return;
-        }
-
-        final Bundle args = new Bundle();
-        args.putInt(FileOperationService.EXTRA_FAILURE, failure);
-        args.putInt(FileOperationService.EXTRA_OPERATION, operationType);
-        args.putParcelableArrayList(FileOperationService.EXTRA_SRC_LIST, failedSrcList);
-
-        final FragmentTransaction ft = fm.beginTransaction();
-        final FailureDialogFragment fragment = new FailureDialogFragment();
-        fragment.setArguments(args);
-
-        ft.add(fragment, TAG);
-        ft.commitAllowingStateLoss();
-    }
-
-    @Override
-    public Dialog onCreateDialog(Bundle inState) {
-        super.onCreate(inState);
-
-        final int operationType = getArguments().getInt(FileOperationService.EXTRA_OPERATION);
-        final List<DocumentInfo> failedSrcList = getArguments().getParcelableArrayList(
-                FileOperationService.EXTRA_SRC_LIST);
-
-        final StringBuilder list = new StringBuilder("<p>");
-        for (DocumentInfo documentInfo : failedSrcList) {
-            list.append(String.format("&#8226; %s<br>", documentInfo.displayName));
-        }
-        list.append("</p>");
-
-        // TODO: Add support for other file operations.
-        checkArgument(
-                operationType == FileOperationService.OPERATION_COPY
-                || operationType == FileOperationService.OPERATION_MOVE);
-
-        int messageId = operationType == FileOperationService.OPERATION_COPY
-                ? R.string.copy_failure_alert_content
-                : R.string.move_failure_alert_content;
-
-        final String messageFormat = getString(
-                messageId);
-
-        final String message = String.format(messageFormat, list.toString());
-
-        return new AlertDialog.Builder(getActivity())
-                .setMessage(Html.fromHtml(message))
-                .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int id) {
-                        dialog.dismiss();
-                    }
-                })
-                .create();
-    }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 5abe7f6..f51f689 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
 import static com.android.internal.util.Preconditions.checkArgument;
@@ -43,6 +44,7 @@
 import android.widget.Spinner;
 import android.widget.Toolbar;
 
+import com.android.documentsui.OperationDialogFragment.DialogType;
 import com.android.documentsui.RecentsProvider.ResumeColumns;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.model.DocumentInfo;
@@ -121,20 +123,20 @@
                     ProviderExecutor.forAuthority(homeUri.getAuthority()));
         }
 
-        final int failure = intent.getIntExtra(FileOperationService.EXTRA_FAILURE, 0);
-        final int opType = intent.getIntExtra(
-                FileOperationService.EXTRA_OPERATION,
-                FileOperationService.OPERATION_COPY);
-
+        final @DialogType int dialogType = intent.getIntExtra(
+                FileOperationService.EXTRA_DIALOG_TYPE, DIALOG_TYPE_UNKNOWN);
         // DialogFragment takes care of restoring the dialog on configuration change.
         // Only show it manually for the first time (icicle is null).
-        if (icicle == null && failure != 0) {
-            final ArrayList<DocumentInfo> failedSrcList =
+        if (icicle == null && dialogType != DIALOG_TYPE_UNKNOWN) {
+            final int opType = intent.getIntExtra(
+                    FileOperationService.EXTRA_OPERATION,
+                    FileOperationService.OPERATION_COPY);
+            final ArrayList<DocumentInfo> srcList =
                     intent.getParcelableArrayListExtra(FileOperationService.EXTRA_SRC_LIST);
-            FailureDialogFragment.show(
+            OperationDialogFragment.show(
                     getFragmentManager(),
-                    failure,
-                    failedSrcList,
+                    dialogType,
+                    srcList,
                     mState.stack,
                     opType);
         }
@@ -254,9 +256,6 @@
 
         pasteFromCb.setEnabled(mClipper.hasItemsToPaste());
 
-        newWindow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
-        newWindow.setVisible(mProductivityDevice);
-
         Menus.disableHiddenItems(menu, pasteFromCb);
         return true;
     }
@@ -285,6 +284,14 @@
         Metrics.logMultiWindow(this);
         Intent intent = LauncherActivity.createLaunchIntent(this);
         intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
+
+        // With new multi-window mode we have to pick how we are launched.
+        // By default we'd be launched in-place above the existing app.
+        // By setting launch-to-side ActivityManager will open us to side.
+        if (inMultiWindowMode()) {
+            intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE);
+        }
+
         startActivity(intent);
     }
 
@@ -296,12 +303,6 @@
 
         if (cwd == null) {
             DirectoryFragment.showRecentsOpen(fm, anim);
-
-            // Start recents in grid when requesting visual things
-            final boolean visualMimes = MimePredicate.mimeMatches(
-                    MimePredicate.VISUAL_MIMES, mState.acceptMimes);
-            mState.userMode = visualMimes ? State.MODE_GRID : State.MODE_LIST;
-            mState.derivedMode = mState.userMode;
         } else {
             if (mState.currentSearch != null) {
                 // Ongoing search
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
index b3d0cf3..7930c28 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
@@ -74,6 +74,9 @@
 
     private void startTask() {
         Intent intent = createLaunchIntent(this);
+
+        // Forward any flags from the original intent.
+        intent.setFlags(getIntent().getFlags());
         if (DEBUG) Log.d(TAG, "Starting new task > " + intent.getData());
         startActivity(intent);
     }
@@ -84,7 +87,7 @@
         startActivity(intent);
     }
 
-    static Intent createLaunchIntent(Context context) {
+    static final Intent createLaunchIntent(Context context) {
         Intent intent = new Intent(context, FilesActivity.class);
         intent.setData(buildLaunchUri());
         return intent;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 113e9d7..4bffc49 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -16,12 +16,19 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.State.MODE_UNKNOWN;
+import static com.android.internal.util.Preconditions.checkArgument;
+
 import android.content.Context;
 import android.preference.PreferenceManager;
 
+import com.android.documentsui.State.ViewMode;
+import com.android.documentsui.model.RootInfo;
+
 public class LocalPreferences {
     private static final String KEY_ADVANCED_DEVICES = "advancedDevices";
     private static final String KEY_FILE_SIZE = "fileSize";
+    private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
 
     public static boolean getDisplayAdvancedDevices(Context context) {
         boolean defaultAdvanced = context.getResources()
@@ -35,6 +42,12 @@
                 .getBoolean(KEY_FILE_SIZE, false);
     }
 
+    public static @ViewMode int getViewMode(
+            Context context, RootInfo root, @ViewMode int fallback) {
+        return PreferenceManager.getDefaultSharedPreferences(context)
+                .getInt(createKey(root), fallback);
+    }
+
     public static void setDisplayAdvancedDevices(Context context, boolean display) {
         PreferenceManager.getDefaultSharedPreferences(context).edit()
                 .putBoolean(KEY_ADVANCED_DEVICES, display).apply();
@@ -44,4 +57,14 @@
         PreferenceManager.getDefaultSharedPreferences(context).edit()
                 .putBoolean(KEY_FILE_SIZE, display).apply();
     }
+
+    public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
+        checkArgument(viewMode != MODE_UNKNOWN);
+        PreferenceManager.getDefaultSharedPreferences(context).edit()
+                .putInt(createKey(root), viewMode).apply();
+    }
+
+    private static String createKey(RootInfo root) {
+        return ROOT_VIEW_MODE_PREFIX + root.authority + root.rootId;
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
new file mode 100644
index 0000000..5dc4f57
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static android.os.Environment.isStandardDirectory;
+import static com.android.documentsui.Shared.DEBUG;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.ContentProvider;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.provider.DocumentsContract;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * Activity responsible for handling {@link Intent#ACTION_OPEN_EXTERNAL_DOCUMENT}.
+ */
+public class OpenExternalDirectoryActivity extends Activity {
+    private static final String TAG = "OpenExternalDirectoryActivity";
+    private static final String FM_TAG = "open_external_directory";
+    private static final String EXTERNAL_STORAGE_AUTH = "com.android.externalstorage.documents";
+    private static final String EXTRA_FILE = "com.android.documentsui.FILE";
+    private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL";
+    private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Intent intent = getIntent();
+        if (intent == null || intent.getData() == null) {
+            Log.d(TAG, "missing intent or intent data: " + intent);
+            setResult(RESULT_CANCELED);
+            finish();
+            return;
+        }
+
+        final String path = intent.getData().getPath();
+        final int userId = UserHandle.myUserId();
+        if (!showFragment(this, userId, path)) {
+            setResult(RESULT_CANCELED);
+            finish();
+            return;
+        }
+    }
+
+    /**
+     * Validates the given {@code path} and display the appropriate dialog asking the user to grant
+     * access to it.
+     */
+    static boolean showFragment(Activity activity, int userId, String path) {
+        Log.d(TAG, "showFragment() for path " + path + " and user " + userId);
+        if (path == null) {
+            Log.e(TAG, "INTERNAL ERROR: showFragment() with null path");
+            return false;
+        }
+        File file;
+        try {
+            file = new File(new File(path).getCanonicalPath());
+        } catch (IOException e) {
+            Log.e(TAG, "Could not get canonical file from " + path);
+            return false;
+        }
+        final StorageManager sm =
+                (StorageManager) activity.getSystemService(Context.STORAGE_SERVICE);
+
+        final String root = file.getParent();
+        final String directory = file.getName();
+
+        // Verify directory is valid.
+        if (TextUtils.isEmpty(directory) || !isStandardDirectory(directory)) {
+            Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '" + path + "')");
+            return false;
+        }
+
+        // Gets volume label and converted path
+        String volumeLabel = null;
+        final List<VolumeInfo> volumes = sm.getVolumes();
+        if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size());
+        for (VolumeInfo volume : volumes) {
+            if (isRightVolume(volume, root, userId)) {
+                final File internalRoot = volume.getInternalPathForUser(userId);
+                // Must convert path before calling getDocIdForFileCreateNewDir()
+                if (DEBUG) Log.d(TAG, "Converting " + root + " to " + internalRoot);
+                file = new File(internalRoot, directory);
+                volumeLabel = sm.getBestVolumeDescription(volume);
+                break;
+            }
+        }
+        if (volumeLabel == null) {
+            Log.e(TAG, "Could not get volume for " + path);
+            return false;
+        }
+
+        // Gets the package label.
+        final String appLabel = getAppLabel(activity);
+        if (appLabel == null) {
+            return false;
+        }
+
+        // Sets args that will be retrieve on onCreate()
+        final Bundle args = new Bundle();
+        args.putString(EXTRA_FILE, file.getAbsolutePath());
+        args.putString(EXTRA_VOLUME_LABEL, volumeLabel);
+        args.putString(EXTRA_APP_LABEL, appLabel);
+
+        final FragmentManager fm = activity.getFragmentManager();
+        final FragmentTransaction ft = fm.beginTransaction();
+        final OpenExternalDirectoryDialogFragment fragment =
+                new OpenExternalDirectoryDialogFragment();
+        fragment.setArguments(args);
+        ft.add(fragment, FM_TAG);
+        ft.commitAllowingStateLoss();
+
+        return true;
+    }
+
+    private static String getAppLabel(Activity activity) {
+        final String packageName = activity.getCallingPackage();
+        final PackageManager pm = activity.getPackageManager();
+        try {
+            return pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)).toString();
+        } catch (NameNotFoundException e) {
+            Log.w(TAG, "Could not get label for package " + packageName);
+            return null;
+        }
+    }
+
+    private static boolean isRightVolume(VolumeInfo volume, String root, int userId) {
+        final File userPath = volume.getPathForUser(userId);
+        final String path = userPath == null ? null : volume.getPathForUser(userId).getPath();
+        final boolean isVisible = volume.isVisibleForWrite(userId);
+        if (DEBUG) {
+            Log.d(TAG, "Volume: " + volume + " userId: " + userId + " root: " + root
+                    + " volumePath: " + volume.getPath().getPath()
+                    + " pathForUser: " + path
+                    + " internalPathForUser: " + volume.getInternalPath()
+                    + " isVisible: " + isVisible);
+        }
+        return volume.isVisibleForWrite(userId) && root.equals(path);
+    }
+
+    private static Intent createGrantedUriPermissionsIntent(ContentProviderClient provider,
+            File file) {
+        // Calls ExternalStorageProvider to get the doc id for the file
+        final Bundle bundle;
+        try {
+            bundle = provider.call("getDocIdForFileCreateNewDir", file.getPath(), null);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Did not get doc id from External Storage provider for " + file, e);
+            return null;
+        }
+        final String docId = bundle == null ? null : bundle.getString("DOC_ID");
+        if (docId == null) {
+            Log.e(TAG, "Did not get doc id from External Storage provider for " + file);
+            return null;
+        }
+        Log.d(TAG, "doc id for " + file + ": " + docId);
+
+        final Uri uri = DocumentsContract.buildTreeDocumentUri(EXTERNAL_STORAGE_AUTH, docId);
+        if (uri == null) {
+            Log.e(TAG, "Could not get URI for doc id " + docId);
+            return null;
+        }
+
+        if (DEBUG) Log.d(TAG, "URI for " + file + ": " + uri);
+        final Intent intent = new Intent();
+        intent.setData(uri);
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
+        return intent;
+    }
+
+    private static class OpenExternalDirectoryDialogFragment extends DialogFragment {
+
+        private File mFile;
+        private String mVolumeLabel;
+        private String mAppLabel;
+        private ContentProviderClient mExternalStorageClient;
+        private ContentResolver mResolver;
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            final Bundle args = getArguments();
+            if (args != null) {
+                mFile = new File(args.getString(EXTRA_FILE));
+                mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL);
+                mAppLabel = args.getString(EXTRA_APP_LABEL);
+                mResolver = getContext().getContentResolver();
+            }
+        }
+
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            if (mExternalStorageClient != null) {
+                mExternalStorageClient.close();
+            }
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final String folder = mFile.getName();
+            final Activity activity = getActivity();
+            final OnClickListener listener = new OnClickListener() {
+
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    Intent intent = null;
+                    if (which == DialogInterface.BUTTON_POSITIVE) {
+                        intent = createGrantedUriPermissionsIntent(getExternalStorageClient(),
+                                mFile);
+                    }
+                    if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
+                        activity.setResult(RESULT_CANCELED);
+                    } else {
+                        activity.setResult(RESULT_OK, intent);
+                    }
+                    activity.finish();
+                }
+            };
+
+            final CharSequence message = TextUtils
+                    .expandTemplate(
+                            getText(R.string.open_external_dialog_request), mAppLabel, folder,
+                            mVolumeLabel);
+            return new AlertDialog.Builder(activity, R.style.AlertDialogTheme)
+                    .setMessage(message)
+                    .setPositiveButton(R.string.allow, listener)
+                    .setNegativeButton(R.string.deny, listener)
+                    .create();
+        }
+
+        @Override
+        public void onCancel(DialogInterface dialog) {
+            super.onCancel(dialog);
+            final Activity activity = getActivity();
+            activity.setResult(RESULT_CANCELED);
+            activity.finish();
+        }
+
+        private synchronized ContentProviderClient getExternalStorageClient() {
+            if (mExternalStorageClient == null) {
+                mExternalStorageClient =
+                        mResolver.acquireContentProviderClient(EXTERNAL_STORAGE_AUTH);
+            }
+            return mExternalStorageClient;
+        }
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OperationDialogFragment.java b/packages/DocumentsUI/src/com/android/documentsui/OperationDialogFragment.java
new file mode 100644
index 0000000..85cc12b
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/OperationDialogFragment.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.services.FileOperationService.OpType;
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import android.annotation.IntDef;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.text.Html;
+
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.services.FileOperationService;
+import com.android.documentsui.services.FileOperations;
+import com.android.documentsui.services.Job;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Alert dialog for operation dialogs.
+ */
+public class OperationDialogFragment extends DialogFragment {
+
+    public static final int DIALOG_TYPE_UNKNOWN = 0;
+    public static final int DIALOG_TYPE_FAILURE = 1;
+    public static final int DIALOG_TYPE_CONVERTED = 2;
+
+    @IntDef(flag = true, value = {
+        DIALOG_TYPE_UNKNOWN,
+        DIALOG_TYPE_FAILURE,
+        DIALOG_TYPE_CONVERTED
+    })
+
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DialogType {}
+
+    private static final String TAG = "OperationDialogFragment";
+
+    public static void show(FragmentManager fm, @DialogType int dialogType,
+            ArrayList<DocumentInfo> failedSrcList, DocumentStack dstStack,
+            @OpType int operationType) {
+        final Bundle args = new Bundle();
+        args.putInt(FileOperationService.EXTRA_DIALOG_TYPE, dialogType);
+        args.putInt(FileOperationService.EXTRA_OPERATION, operationType);
+        args.putParcelableArrayList(FileOperationService.EXTRA_SRC_LIST, failedSrcList);
+
+        final FragmentTransaction ft = fm.beginTransaction();
+        final OperationDialogFragment fragment = new OperationDialogFragment();
+        fragment.setArguments(args);
+
+        ft.add(fragment, TAG);
+        ft.commitAllowingStateLoss();
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle inState) {
+        super.onCreate(inState);
+
+        final @DialogType int dialogType =
+              getArguments().getInt(FileOperationService.EXTRA_DIALOG_TYPE);
+        final @OpType int operationType =
+              getArguments().getInt(FileOperationService.EXTRA_OPERATION);
+        final ArrayList<DocumentInfo> srcList = getArguments().getParcelableArrayList(
+                FileOperationService.EXTRA_SRC_LIST);
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        String messageFormat;
+
+        switch (dialogType) {
+            case DIALOG_TYPE_CONVERTED:
+                messageFormat = getString(R.string.copy_converted_warning_content);
+                break;
+
+            case DIALOG_TYPE_FAILURE:
+                switch (operationType) {
+                    case FileOperationService.OPERATION_COPY:
+                        messageFormat = getString(R.string.copy_failure_alert_content);
+                        break;
+                    case FileOperationService.OPERATION_MOVE:
+                        messageFormat = getString(R.string.move_failure_alert_content);
+                        break;
+                    default:
+                        throw new UnsupportedOperationException();
+                }
+                break;
+
+            default:
+                throw new UnsupportedOperationException();
+        }
+
+        final StringBuilder list = new StringBuilder("<p>");
+        for (DocumentInfo documentInfo : srcList) {
+            list.append(String.format("&#8226; %s<br>", documentInfo.displayName));
+        }
+        list.append("</p>");
+        builder.setMessage(Html.fromHtml(String.format(messageFormat, list.toString())));
+        builder.setPositiveButton(
+                R.string.close,
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int id) {
+                        dialog.dismiss();
+                    }
+                });
+
+        return builder.create();
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index 82eb732..92ffb93 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -85,6 +85,8 @@
         public static final String AUTHORITY = "authority";
         public static final String ROOT_ID = Root.COLUMN_ROOT_ID;
         public static final String DOCUMENT_ID = Document.COLUMN_DOCUMENT_ID;
+
+        @Deprecated  // mode is tracked in local preferences now...by root only
         public static final String MODE = "mode";
         public static final String SORT_ORDER = "sortOrder";
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index 2f0224f..28f7432 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -16,6 +16,7 @@
 
 package com.android.documentsui;
 
+import android.annotation.IntDef;
 import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -26,18 +27,43 @@
 import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
 public class State implements android.os.Parcelable {
+
+    public static final int ACTION_OPEN = 1;
+    public static final int ACTION_CREATE = 2;
+    public static final int ACTION_GET_CONTENT = 3;
+    public static final int ACTION_OPEN_TREE = 4;
+    public static final int ACTION_MANAGE = 5;
+    public static final int ACTION_BROWSE = 6;
+    public static final int ACTION_PICK_COPY_DESTINATION = 8;
+
+    @IntDef(flag = true, value = {
+            MODE_UNKNOWN,
+            MODE_LIST,
+            MODE_GRID
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ViewMode {}
+    public static final int MODE_UNKNOWN = 0;
+    public static final int MODE_LIST = 1;
+    public static final int MODE_GRID = 2;
+
+    public static final int SORT_ORDER_UNKNOWN = 0;
+    public static final int SORT_ORDER_DISPLAY_NAME = 1;
+    public static final int SORT_ORDER_LAST_MODIFIED = 2;
+    public static final int SORT_ORDER_SIZE = 3;
+
     public int action;
     public String[] acceptMimes;
 
-    /** Explicit user choice */
-    public int userMode = MODE_UNKNOWN;
-    /** Derived after loader */
-    public int derivedMode = MODE_GRID;
+    /** Derived from local preferences */
+    public @ViewMode int derivedMode = MODE_GRID;
 
     /** Explicit user choice */
     public int userSortOrder = SORT_ORDER_UNKNOWN;
@@ -58,6 +84,8 @@
 
     /** Current user navigation stack; empty implies recents. */
     public DocumentStack stack = new DocumentStack();
+    private boolean mStackTouched;
+
     /** Currently active search, overriding any stack. */
     public String currentSearch;
 
@@ -70,25 +98,6 @@
     /** Name of the package that started DocsUI */
     public List<String> excludedAuthorities = new ArrayList<>();
 
-    public static final int ACTION_OPEN = 1;
-    public static final int ACTION_CREATE = 2;
-    public static final int ACTION_GET_CONTENT = 3;
-    public static final int ACTION_OPEN_TREE = 4;
-    public static final int ACTION_MANAGE = 5;
-    public static final int ACTION_BROWSE = 6;
-    public static final int ACTION_PICK_COPY_DESTINATION = 8;
-
-    public static final int MODE_UNKNOWN = 0;
-    public static final int MODE_LIST = 1;
-    public static final int MODE_GRID = 2;
-
-    public static final int SORT_ORDER_UNKNOWN = 0;
-    public static final int SORT_ORDER_DISPLAY_NAME = 1;
-    public static final int SORT_ORDER_LAST_MODIFIED = 2;
-    public static final int SORT_ORDER_SIZE = 3;
-
-    private boolean mStackTouched;
-
     public void initAcceptMimes(Intent intent) {
         if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
             acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
@@ -131,7 +140,6 @@
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(action);
-        out.writeInt(userMode);
         out.writeStringArray(acceptMimes);
         out.writeInt(userSortOrder);
         out.writeInt(allowMultiple ? 1 : 0);
@@ -155,7 +163,6 @@
         public State createFromParcel(Parcel in) {
             final State state = new State();
             state.action = in.readInt();
-            state.userMode = in.readInt();
             state.acceptMimes = in.readStringArray();
             state.userSortOrder = in.readInt();
             state.allowMultiple = in.readInt() != 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 74fa8d0..f57aa4b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -20,7 +20,6 @@
 import static com.android.documentsui.State.ACTION_MANAGE;
 import static com.android.documentsui.State.MODE_GRID;
 import static com.android.documentsui.State.MODE_LIST;
-import static com.android.documentsui.State.MODE_UNKNOWN;
 import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
@@ -37,7 +36,6 @@
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ClipData;
 import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Loader;
@@ -91,9 +89,6 @@
 import com.android.documentsui.MimePredicate;
 import com.android.documentsui.R;
 import com.android.documentsui.RecentLoader;
-import com.android.documentsui.RecentsProvider;
-import com.android.documentsui.RecentsProvider.StateColumns;
-import com.android.documentsui.dirlist.RenameDocumentFragment;
 import com.android.documentsui.RootsCache;
 import com.android.documentsui.Shared;
 import com.android.documentsui.Snackbars;
@@ -155,7 +150,6 @@
     private int mType = TYPE_NORMAL;
     private String mStateKey;
 
-    private int mLastMode = MODE_UNKNOWN;
     private int mLastSortOrder = SORT_ORDER_UNKNOWN;
     private boolean mLastShowSize;
     private DocumentsAdapter mAdapter;
@@ -240,7 +234,7 @@
         final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
         final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
 
-        mIconHelper = new IconHelper(context, state.derivedMode);
+        mIconHelper = new IconHelper(context, MODE_GRID);
 
         mAdapter = new SectionBreakDocumentsAdapterWrapper(
                 this, new ModelBackedDocumentsAdapter(this, mIconHelper));
@@ -323,12 +317,6 @@
                 if (!isAdded()) return;
 
                 mModel.update(result);
-
-                // Push latest state up to UI
-                // TODO: if mode change was racing with us, don't overwrite it
-                if (result.mode != MODE_UNKNOWN) {
-                    state.derivedMode = result.mode;
-                }
                 state.derivedSortOrder = result.sortOrder;
 
                 updateDisplayState();
@@ -361,8 +349,6 @@
 
         // Kick off loader at least once
         getLoaderManager().restartLoader(LOADER_ID, null, mCallbacks);
-
-        updateDisplayState();
     }
 
     @Override
@@ -425,61 +411,25 @@
         state.dirState.put(mStateKey, container);
     }
 
-    @Override
-    public void onResume() {
-        super.onResume();
-        updateDisplayState();
-    }
-
     public void onDisplayStateChanged() {
         updateDisplayState();
     }
 
-    public void onUserSortOrderChanged() {
-        // Sort order change always triggers reload; we'll trigger state change
-        // on the flip side.
+    public void onSortOrderChanged() {
+        // Sort order is implemented as a sorting wrapper around directory
+        // results. So when sort order changes, we force a reload of the directory.
         getLoaderManager().restartLoader(LOADER_ID, null, mCallbacks);
     }
 
-    public void onUserModeChanged() {
-        final ContentResolver resolver = getActivity().getContentResolver();
-        final State state = getDisplayState();
-
-        final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
-        final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
-
-        if (root != null && doc != null) {
-            final Uri stateUri = RecentsProvider.buildState(
-                    root.authority, root.rootId, doc.documentId);
-            final ContentValues values = new ContentValues();
-            values.put(StateColumns.MODE, state.userMode);
-
-            new AsyncTask<Void, Void, Void>() {
-                @Override
-                protected Void doInBackground(Void... params) {
-                    resolver.insert(stateUri, values);
-                    return null;
-                }
-            }.execute();
-        }
-
-        // Mode change is just visual change; no need to kick loader, and
-        // deliver change event immediately.
-        state.derivedMode = state.userMode;
-        ((BaseActivity) getActivity()).onStateChanged();
-
+    public void onViewModeChanged() {
+        // Mode change is just visual change; no need to kick loader.
         updateDisplayState();
     }
 
     private void updateDisplayState() {
-        final State state = getDisplayState();
-
-        if (mLastMode == state.derivedMode && mLastShowSize == state.showSize) return;
-        mLastMode = state.derivedMode;
+        State state = getDisplayState();
         mLastShowSize = state.showSize;
-
         updateLayout(state.derivedMode);
-
         mRecView.setAdapter(mAdapter);
     }
 
@@ -506,7 +456,6 @@
                 }
                 layout = mListLayout;
                 break;
-            case MODE_UNKNOWN:
             default:
                 throw new IllegalArgumentException("Unsupported layout mode: " + mode);
         }
@@ -516,7 +465,7 @@
         // setting layout manager automatically invalidates existing ViewHolders.
         mRecView.setLayoutManager(layout);
         mSelectionManager.handleLayoutChanged();  // RecyclerView doesn't do this for us
-        mIconHelper.setMode(mode);
+        mIconHelper.setViewMode(mode);
     }
 
     private int calculateColumnCount() {
@@ -539,7 +488,6 @@
             case MODE_LIST:
                 return getResources().getDimensionPixelSize(
                         R.dimen.list_container_padding);
-            case MODE_UNKNOWN:
             default:
                 throw new IllegalArgumentException("Unsupported layout mode: " + mode);
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/IconHelper.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/IconHelper.java
index 0314077..c97c446 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/IconHelper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/IconHelper.java
@@ -42,6 +42,8 @@
 import com.android.documentsui.ProviderExecutor;
 import com.android.documentsui.ProviderExecutor.Preemptable;
 import com.android.documentsui.R;
+import com.android.documentsui.State;
+import com.android.documentsui.State.ViewMode;
 import com.android.documentsui.ThumbnailCache;
 
 /**
@@ -64,7 +66,7 @@
      */
     public IconHelper(Context context, int mode) {
         mContext = context;
-        setMode(mode);
+        setViewMode(mode);
         mCache = DocumentsApplication.getThumbnailsCache(context, mThumbSize);
     }
 
@@ -82,7 +84,7 @@
      * Sets the current display mode.  This affects the thumbnail sizes that are loaded.
      * @param mode See {@link State.MODE_LIST} and {@link State.MODE_GRID}.
      */
-    public void setMode(int mode) {
+    public void setViewMode(@ViewMode int mode) {
         // TODO: Instead of exposing setMode, make the mode final, and make separate instances for
         // grid/list.
         int thumbSize;
@@ -94,7 +96,6 @@
                 thumbSize = mContext.getResources().getDimensionPixelSize(
                         R.dimen.list_item_thumbnail_size);
                 break;
-            case MODE_UNKNOWN:
             default:
                 throw new IllegalArgumentException("Unsupported layout mode: " + mode);
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 68756a3..880da9c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -19,7 +19,6 @@
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.State.MODE_GRID;
 import static com.android.documentsui.State.MODE_LIST;
-import static com.android.documentsui.State.MODE_UNKNOWN;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
@@ -92,7 +91,6 @@
             case MODE_LIST:
                 holder = new ListDocumentHolder(mEnv.getContext(), parent, mIconHelper);
                 break;
-            case MODE_UNKNOWN:
             default:
                 throw new IllegalStateException("Unsupported layout mode.");
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index 1d8eba5..e5e66f8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -21,17 +21,23 @@
 import static android.provider.DocumentsContract.buildDocumentUri;
 import static android.provider.DocumentsContract.getDocumentId;
 import static android.provider.DocumentsContract.isChildDocument;
+import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_CONVERTED;
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
+import static com.android.documentsui.services.FileOperationService.EXTRA_DIALOG_TYPE;
+import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
+import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
 import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
 import static com.google.common.base.Preconditions.checkArgument;
 
 import android.annotation.StringRes;
 import android.app.Notification;
 import android.app.Notification.Builder;
+import android.app.PendingIntent;
 import android.content.ContentProviderClient;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.net.Uri;
@@ -56,12 +62,14 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.text.NumberFormat;
+import java.util.ArrayList;
 import java.util.List;
 
 class CopyJob extends Job {
     private static final String TAG = "CopyJob";
     private static final int PROGRESS_INTERVAL_MILLIS = 1000;
     final List<DocumentInfo> mSrcs;
+    final ArrayList<DocumentInfo> convertedFiles = new ArrayList<>();
 
     private long mStartTime = -1;
     private long mBatchSize;
@@ -176,6 +184,29 @@
     }
 
     @Override
+    Notification getWarningNotification() {
+        final Intent navigateIntent = buildNavigateIntent();
+        navigateIntent.putExtra(EXTRA_DIALOG_TYPE, DIALOG_TYPE_CONVERTED);
+        navigateIntent.putExtra(EXTRA_OPERATION, operationType);
+
+        navigateIntent.putParcelableArrayListExtra(EXTRA_SRC_LIST, convertedFiles);
+
+        // TODO: Consider adding a dialog on tapping the notification with a list of
+        // converted files.
+        final Notification.Builder warningBuilder = new Notification.Builder(service)
+                .setContentTitle(service.getResources().getString(
+                        R.string.notification_copy_files_converted_title))
+                .setContentText(service.getString(
+                        R.string.notification_touch_for_details))
+                .setContentIntent(PendingIntent.getActivity(appContext, 0, navigateIntent,
+                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT))
+                .setCategory(Notification.CATEGORY_ERROR)
+                .setSmallIcon(R.drawable.ic_menu_copy)
+                .setAutoCancel(true);
+        return warningBuilder.build();
+    }
+
+    @Override
     void start() throws RemoteException {
         mStartTime = elapsedRealtime();
 
@@ -203,6 +234,11 @@
         }
     }
 
+    @Override
+    boolean hasWarnings() {
+        return !convertedFiles.isEmpty();
+    }
+
     /**
      * Logs progress on the current copy operation. Displays/Updates the progress notification.
      *
@@ -425,6 +461,10 @@
             }
         }
 
+        if (src.isVirtualDocument() && success) {
+           convertedFiles.add(src);
+        }
+
         return success;
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
index eef696a..24eb987 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
@@ -75,6 +75,11 @@
     }
 
     @Override
+    Notification getWarningNotification() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     void start() throws RemoteException {
         for (DocumentInfo doc : mSrcs) {
             if (DEBUG) Log.d(TAG, "Deleting document @ " + doc.derivedUri);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
index 5d74cdc..3a025c2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
@@ -55,6 +55,7 @@
     private static final int POOL_SIZE = 2;  // "pool size", not *max* "pool size".
     private static final int NOTIFICATION_ID_PROGRESS = 0;
     private static final int NOTIFICATION_ID_FAILURE = 1;
+    private static final int NOTIFICATION_ID_WARNING = 2;
 
     public static final String TAG = "FileOperationService";
 
@@ -63,7 +64,7 @@
     public static final String EXTRA_OPERATION = "com.android.documentsui.OPERATION";
     public static final String EXTRA_CANCEL = "com.android.documentsui.CANCEL";
     public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST";
-    public static final String EXTRA_FAILURE = "com.android.documentsui.FAILURE";
+    public static final String EXTRA_DIALOG_TYPE = "com.android.documentsui.DIALOG_TYPE";
 
     // This extra is used only for moving and deleting. Currently it's not the case,
     // but in the future those files may be from multiple different parents. In
@@ -306,6 +307,18 @@
         // Dismiss the ongoing copy notification when the copy is done.
         mNotificationManager.cancel(job.id, NOTIFICATION_ID_PROGRESS);
 
+        if (job.hasFailures()) {
+            Log.e(TAG, "Job failed on files: " + job.failedFiles.size() + ".");
+            mNotificationManager.notify(
+                job.id, NOTIFICATION_ID_FAILURE, job.getFailureNotification());
+        }
+
+        if (job.hasWarnings()) {
+            if (DEBUG) Log.d(TAG, "Job finished with warnings.");
+            mNotificationManager.notify(
+                    job.id, NOTIFICATION_ID_WARNING, job.getWarningNotification());
+        }
+
         synchronized (mRunning) {
             deleteJob(job);
         }
@@ -318,15 +331,6 @@
                 job.id, NOTIFICATION_ID_PROGRESS, job.getProgressNotification());
     }
 
-    @Override
-    public void onFailed(Job job) {
-        if (DEBUG) Log.d(TAG, "onFailed: " + job.id);
-        checkArgument(job.failed());
-        Log.e(TAG, "Job failed on files: " + job.failedFiles.size() + ".");
-        mNotificationManager.notify(job.id, NOTIFICATION_ID_FAILURE, job.getFailureNotification());
-        onFinished(job);  // Failed jobs don't call finished, so we do.
-    }
-
     private static final class JobRecord {
         private final Job job;
         private final ScheduledFuture<?> future;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
index 9534d6c..7b8011a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
@@ -18,11 +18,10 @@
 
 import static com.android.documentsui.DocumentsApplication.acquireUnstableProviderOrThrow;
 import static com.android.documentsui.services.FileOperationService.EXTRA_CANCEL;
-import static com.android.documentsui.services.FileOperationService.EXTRA_FAILURE;
+import static com.android.documentsui.services.FileOperationService.EXTRA_DIALOG_TYPE;
 import static com.android.documentsui.services.FileOperationService.EXTRA_JOB_ID;
 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
-import static com.android.documentsui.services.FileOperationService.FAILURE_COPY;
 import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
@@ -42,6 +41,7 @@
 import android.util.Log;
 
 import com.android.documentsui.FilesActivity;
+import com.android.documentsui.OperationDialogFragment;
 import com.android.documentsui.R;
 import com.android.documentsui.Shared;
 import com.android.documentsui.model.DocumentInfo;
@@ -57,8 +57,7 @@
  * A mashup of work item and ui progress update factory. Used by {@link FileOperationService}
  * to do work and show progress relating to this work.
  */
-abstract class Job implements Runnable {
-
+abstract public class Job implements Runnable {
     private static final String TAG = "Job";
     final Context service;
     final Context appContext;
@@ -114,13 +113,9 @@
             // to resolve business in an orderly fashion. That'll
             // ensure the service is shut down and notifications
             // shown/closed.
-            listener.onFailed(this);
+            Log.e(TAG, "Operation failed due to an exception.", e);
         } finally {
-            if (failed()) {
-                listener.onFailed(this);
-            } else {
-                listener.onFinished(this);
-            }
+            listener.onFinished(this);
         }
     }
 
@@ -131,6 +126,8 @@
     // abstract Notification getProgressNotification(long bytesCopied);
     abstract Notification getFailureNotification();
 
+    abstract Notification getWarningNotification();
+
     ContentProviderClient getClient(DocumentInfo doc) throws RemoteException {
         ContentProviderClient client = mClients.get(doc.authority);
         if (client == null) {
@@ -167,10 +164,14 @@
         failedFiles.add(file);
     }
 
-    final boolean failed() {
+    final boolean hasFailures() {
         return !failedFiles.isEmpty();
     }
 
+    boolean hasWarnings() {
+        return false;
+    }
+
     final boolean deleteDocument(DocumentInfo doc) {
         try {
             DocumentsContract.deleteDocument(getClient(doc), doc.derivedUri);
@@ -190,7 +191,7 @@
 
     Notification getFailureNotification(@PluralsRes int titleId, @DrawableRes int icon) {
         final Intent navigateIntent = buildNavigateIntent();
-        navigateIntent.putExtra(EXTRA_FAILURE, FAILURE_COPY);
+        navigateIntent.putExtra(EXTRA_DIALOG_TYPE, OperationDialogFragment.DIALOG_TYPE_FAILURE);
         navigateIntent.putExtra(EXTRA_OPERATION, operationType);
 
         navigateIntent.putParcelableArrayListExtra(EXTRA_SRC_LIST, failedFiles);
@@ -291,7 +292,6 @@
      */
     interface Listener {
         void onStart(Job job);
-        void onFailed(Job job);
         void onFinished(Job job);
         void onProgress(CopyJob job);
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java
index 9c58780..a1c6dab 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJob.java
@@ -63,6 +63,11 @@
     }
 
     @Override
+    Notification getWarningNotification() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     Builder createProgressBuilder() {
         // the "copy" stuff was just convenient and available :)
         return super.createProgressBuilder(
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJobListener.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJobListener.java
index 0110197..46b093d 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJobListener.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/TestJobListener.java
@@ -33,7 +33,6 @@
     private final CountDownLatch latch = new CountDownLatch(1);
     private final List<Job> progress = new ArrayList<>();
     @Nullable private Job started;
-    @Nullable private Job failed;
     @Nullable private Job finished;
 
     @Override
@@ -42,11 +41,6 @@
     }
 
     @Override
-    public void onFailed(Job job) {
-        failed = job;
-    }
-
-    @Override
     public void onFinished(Job job) {
         this.finished = job;
         latch.countDown();
@@ -70,28 +64,28 @@
     }
 
     public void assertFailed() {
-        if (failed == null) {
+        if (finished == null || !finished.hasFailures()) {
             fail("Job didn't fail. onFailed never called.");
         }
     }
 
     public void assertFilesFailed(ArrayList<String> names) {
-        if (failed == null) {
+        if (finished == null || !finished.hasFailures()) {
             fail("Can't test failed documetns. Job didn't fail.");
         }
 
-        assertEquals(failed.failedFiles.size(), names.size());
+        assertEquals(finished.failedFiles.size(), names.size());
         for (String name : names) {
             assertFileFailed(name);
         }
     }
 
     public void assertFileFailed(String name) {
-        if (failed == null) {
+        if (finished == null || !finished.hasFailures()) {
             fail("Can't test failed documetns. Job didn't fail.");
         }
 
-        for (DocumentInfo failed : failed.failedFiles) {
+        for (DocumentInfo failed : finished.failedFiles) {
             if (name.equals(failed.displayName)) {
                 return;
             }
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 43527a2..1bfc19c 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -25,6 +25,7 @@
 import android.database.MatrixCursor.RowBuilder;
 import android.graphics.Point;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.FileObserver;
 import android.os.FileUtils;
@@ -234,7 +235,13 @@
         return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
     }
 
+
     private String getDocIdForFile(File file) throws FileNotFoundException {
+        return getDocIdForFileMaybeCreate(file, false);
+    }
+
+    private String getDocIdForFileMaybeCreate(File file, boolean createNewDir)
+            throws FileNotFoundException {
         String path = file.getAbsolutePath();
 
         // Find the most-specific root path
@@ -266,6 +273,13 @@
             path = path.substring(rootPath.length() + 1);
         }
 
+        if (!file.exists() && createNewDir) {
+            Log.i(TAG, "Creating new directory " + file);
+            if (!file.mkdir()) {
+                Log.e(TAG, "Could not create directory " + file);
+            }
+        }
+
         return mostSpecificId + ':' + path;
     }
 
@@ -609,6 +623,34 @@
         }
     }
 
+    @Override
+    public Bundle call(String method, String arg, Bundle extras) {
+        Bundle bundle = super.call(method, arg, extras);
+        if (bundle == null && !TextUtils.isEmpty(method)) {
+            switch (method) {
+                case "getDocIdForFileCreateNewDir": {
+                    getContext().enforceCallingPermission(
+                            android.Manifest.permission.MANAGE_DOCUMENTS, null);
+                    if (TextUtils.isEmpty(arg)) {
+                        return null;
+                    }
+                    try {
+                        final String docId = getDocIdForFileMaybeCreate(new File(arg), true);
+                        bundle = new Bundle();
+                        bundle.putString("DOC_ID", docId);
+                    } catch (FileNotFoundException e) {
+                        Log.w(TAG, "file '" + arg + "' not found");
+                        return null;
+                    }
+                    break;
+                }
+                default:
+                    Log.w(TAG, "unknown method passed to call(): " + method);
+            }
+        }
+        return bundle;
+    }
+
     private static String getTypeForFile(File file) {
         if (file.isDirectory()) {
             return Document.MIME_TYPE_DIR;
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index cbf22c0..40c11cf 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -29,6 +29,7 @@
 import android.widget.Button;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.widget.LockPatternUtils;
 
@@ -117,7 +118,7 @@
      * Shows the emergency dialer or returns the user to the existing call.
      */
     public void takeEmergencyCallAction() {
-        MetricsLogger.action(mContext, MetricsLogger.ACTION_EMERGENCY_CALL);
+        MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_CALL);
         // TODO: implement a shorter timeout once new PowerManager API is ready.
         // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
         mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index c7d17dc..409f6a7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -18,7 +18,6 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.admin.DevicePolicyManager;
-import android.auditing.SecurityLog;
 import android.content.Context;
 import android.os.UserHandle;
 import android.util.AttributeSet;
@@ -424,11 +423,6 @@
         }
 
         public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
-            if (SecurityLog.isLoggingEnabled()) {
-                SecurityLog.writeEvent(SecurityLog.TAG_DEVICE_UNLOCK_ATTEMPT,
-                        (success ? 1 : 0),
-                        mCurrentSecuritySelection.name());
-            }
             KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
             if (success) {
                 monitor.clearFailedUnlockAttempts();
diff --git a/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp b/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
index 7b57d89..2b44d51 100644
--- a/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
+++ b/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
@@ -50,7 +50,8 @@
 
 static jclass app_fuse_class;
 static jmethodID app_fuse_get_file_size;
-static jmethodID app_fuse_get_object_bytes;
+static jmethodID app_fuse_read_object_bytes;
+static jfieldID app_fuse_buffer;
 
 // NOTE:
 // FuseRequest and FuseResponse shares the same buffer to save memory usage, so the handlers must
@@ -282,7 +283,7 @@
         out->prepare_buffer(0);
         const int64_t result = get_object_bytes(it->second, offset, size, out->data());
         if (result < 0) {
-            return -EIO;
+            return result;
         }
         out->set_size(result);
         return 0;
@@ -332,20 +333,24 @@
             uint64_t offset,
             uint32_t size,
             void* buf) {
-        ScopedLocalRef<jbyteArray> array(env_, static_cast<jbyteArray>(env_->CallObjectMethod(
+        const jlong read_size = env_->CallLongMethod(
                 self_,
-                app_fuse_get_object_bytes,
-                inode,
-                offset,
-                size)));
+                app_fuse_read_object_bytes,
+                static_cast<jint>(inode),
+                static_cast<jlong>(offset),
+                static_cast<jlong>(size));
+        if (read_size <= 0) {
+            return read_size;
+        }
+        ScopedLocalRef<jbyteArray> array(
+                env_, static_cast<jbyteArray>(env_->GetObjectField(self_, app_fuse_buffer)));
         if (array.get() == nullptr) {
-            return -1;
+            return -EFAULT;
         }
         ScopedByteArrayRO bytes(env_, array.get());
         if (bytes.get() == nullptr) {
-            return -1;
+            return -ENOMEM;
         }
-        const uint32_t read_size = std::min(static_cast<uint32_t>(bytes.size()), size);
         memcpy(buf, bytes.get(), read_size);
         return read_size;
     }
@@ -451,10 +456,16 @@
         return -1;
     }
 
-    app_fuse_get_object_bytes = env->GetMethodID(
-            app_fuse_class, "getObjectBytes", "(IJI)[B");
-    if (app_fuse_get_object_bytes == nullptr) {
-        ALOGE("Can't find getObjectBytes");
+    app_fuse_read_object_bytes = env->GetMethodID(
+            app_fuse_class, "readObjectBytes", "(IJJ)J");
+    if (app_fuse_read_object_bytes == nullptr) {
+        ALOGE("Can't find readObjectBytes");
+        return -1;
+    }
+
+    app_fuse_buffer = env->GetFieldID(app_fuse_class, "mBuffer", "[B");
+    if (app_fuse_buffer == nullptr) {
+        ALOGE("Can't find mBuffer");
         return -1;
     }
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
index 1300c47..6a98405 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java
@@ -16,9 +16,11 @@
 
 package com.android.mtp;
 
+import android.annotation.WorkerThread;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.storage.StorageManager;
+import android.system.OsConstants;
 import android.util.Log;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
@@ -40,6 +42,13 @@
 
     private final String mName;
     private final Callback mCallback;
+
+    /**
+     * Buffer for read bytes request.
+     * Don't use the buffer from the out of AppFuseMessageThread.
+     */
+    private byte[] mBuffer = new byte[MAX_READ];
+
     private Thread mMessageThread;
     private ParcelFileDescriptor mDeviceFd;
 
@@ -82,28 +91,48 @@
     }
 
     static interface Callback {
+        /**
+         * Returns file size for the given inode.
+         * @param inode
+         * @return File size. Must not be negative.
+         * @throws FileNotFoundException
+         */
         long getFileSize(int inode) throws FileNotFoundException;
-        byte[] getObjectBytes(int inode, long offset, int size) throws IOException;
+
+        /**
+         * Returns flie bytes for the give inode.
+         * @param inode
+         * @param offset Offset for file bytes.
+         * @param size Size for file bytes.
+         * @param bytes Buffer to store file bytes.
+         * @return Number of read bytes. Must not be negative.
+         * @throws IOException
+         */
+        long readObjectBytes(int inode, long offset, long size, byte[] bytes) throws IOException;
     }
 
     @UsedByNative("com_android_mtp_AppFuse.cpp")
+    @WorkerThread
     private long getFileSize(int inode) {
         try {
             return mCallback.getFileSize(inode);
-        } catch (IOException e) {
-            return -1;
+        } catch (FileNotFoundException e) {
+            return -OsConstants.ENOENT;
         }
     }
 
     @UsedByNative("com_android_mtp_AppFuse.cpp")
-    private byte[] getObjectBytes(int inode, long offset, int size) {
+    @WorkerThread
+    private long readObjectBytes(int inode, long offset, long size) {
         if (offset < 0 || size < 0 || size > MAX_READ) {
-            return null;
+            return -OsConstants.EINVAL;
         }
         try {
-            return mCallback.getObjectBytes(inode, offset, size);
+            // It's OK to share the same mBuffer among requests because the requests are processed
+            // by AppFuseMessageThread sequentially.
+            return mCallback.readObjectBytes(inode, offset, size, mBuffer);
         } catch (IOException e) {
-            return null;
+            return -OsConstants.EIO;
         }
     }
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 112914e..959fac6 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -165,22 +165,27 @@
                             cursor.close();
                         }
 
-                        long capacityBytes = 0;
-                        long availableBytes = 0;
-                        int capacityIndex = cursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
-                        int availableIndex = cursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
-                        while (storageCursor.moveToNext()) {
-                            // If requested columnNames does not include COLUMN_XXX_BYTES, we don't
-                            // calculate corresponding values.
-                            if (capacityIndex != -1) {
-                                capacityBytes += cursor.getLong(capacityIndex);
+                        if (storageCursor.getCount() != 0) {
+                            long capacityBytes = 0;
+                            long availableBytes = 0;
+                            int capacityIndex = cursor.getColumnIndex(Root.COLUMN_CAPACITY_BYTES);
+                            int availableIndex = cursor.getColumnIndex(Root.COLUMN_AVAILABLE_BYTES);
+                            while (storageCursor.moveToNext()) {
+                                // If requested columnNames does not include COLUMN_XXX_BYTES, we
+                                // don't calculate corresponding values.
+                                if (capacityIndex != -1) {
+                                    capacityBytes += cursor.getLong(capacityIndex);
+                                }
+                                if (availableIndex != -1) {
+                                    availableBytes += cursor.getLong(availableIndex);
+                                }
                             }
-                            if (availableIndex != -1) {
-                                availableBytes += cursor.getLong(availableIndex);
-                            }
+                            values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
+                            values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
+                        } else {
+                            values.putNull(Root.COLUMN_CAPACITY_BYTES);
+                            values.putNull(Root.COLUMN_AVAILABLE_BYTES);
                         }
-                        values.put(Root.COLUMN_CAPACITY_BYTES, capacityBytes);
-                        values.put(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
                     }
                 } finally {
                     storageCursor.close();
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 3ac1b3d..6b5f16a 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -16,8 +16,6 @@
 
 package com.android.mtp;
 
-import static com.android.internal.util.Preconditions.checkArgument;
-
 import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
@@ -40,7 +38,6 @@
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -391,16 +388,12 @@
     }
 
     private class AppFuseCallback implements AppFuse.Callback {
-        final byte[] mBytes = new byte[AppFuse.MAX_READ];
-
         @Override
-        public byte[] getObjectBytes(int inode, long offset, int size) throws IOException {
+        public long readObjectBytes(
+                int inode, long offset, long size, byte[] buffer) throws IOException {
             final Identifier identifier = mDatabase.createIdentifier(Integer.toString(inode));
-            final long readSize = mMtpManager.getPartialObject(
-                    identifier.mDeviceId, identifier.mObjectHandle, offset, size, mBytes);
-            // TODO: Change signature so that getObjectBytes can return read size without copying
-            // bytes.
-            return Arrays.copyOf(mBytes, (int) readSize);
+            return mMtpManager.getPartialObject(
+                    identifier.mDeviceId, identifier.mObjectHandle, offset, size, buffer);
         }
 
         @Override
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/AppFuseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/AppFuseTest.java
index 6354880..c0973bd 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/AppFuseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/AppFuseTest.java
@@ -77,30 +77,35 @@
 
     public void testReadFile() throws IOException {
         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
-        final int INODE = 10;
-        final byte[] BYTES = new byte[] { 'a', 'b', 'c', 'd', 'e' };
+        final int fileInode = 10;
+        final byte[] fileBytes = new byte[] { 'a', 'b', 'c', 'd', 'e' };
         final AppFuse appFuse = new AppFuse(
                 "test",
                 new TestCallback() {
                     @Override
                     public long getFileSize(int inode) throws FileNotFoundException {
-                        if (inode == INODE) {
-                            return BYTES.length;
+                        if (inode == fileInode) {
+                            return fileBytes.length;
                         }
                         return super.getFileSize(inode);
                     }
 
                     @Override
-                    public byte[] getObjectBytes(int inode, long offset, int size)
+                    public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
                             throws IOException {
-                        if (inode == INODE) {
-                            return Arrays.copyOfRange(BYTES, (int) offset, (int) offset + size);
+                        if (inode == fileInode) {
+                            int i = 0;
+                            while (i < size && i + offset < fileBytes.length)  {
+                                bytes[i] = fileBytes[(int) (i + offset)];
+                                i++;
+                            }
+                            return i;
                         }
-                        return super.getObjectBytes(inode, offset, size);
+                        return super.readObjectBytes(inode, offset, size, bytes);
                     }
                 });
         appFuse.mount(storageManager);
-        final ParcelFileDescriptor fd = appFuse.openFile(INODE);
+        final ParcelFileDescriptor fd = appFuse.openFile(fileInode);
         try (final ParcelFileDescriptor.AutoCloseInputStream stream =
                 new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
             final byte[] buffer = new byte[1024];
@@ -117,7 +122,7 @@
         }
 
         @Override
-        public byte[] getObjectBytes(int inode, long offset, int size)
+        public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
                 throws IOException {
             throw new IOException();
         }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 97ea717..8075999 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -899,4 +899,24 @@
         mDatabase.getMapper().stopAddingDocuments(null);
         assertEquals("1", mDatabase.getDocumentIdForDevice(100));
     }
+
+    public void testGetClosedDevice() {
+        mDatabase.getMapper().startAddingDocuments(null);
+        mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
+                0, "Device", /* opened is */ false , new MtpRoot[0], null, null));
+        mDatabase.getMapper().stopAddingDocuments(null);
+
+        final String[] columns = new String [] {
+                DocumentsContract.Root.COLUMN_ROOT_ID,
+                DocumentsContract.Root.COLUMN_TITLE,
+                DocumentsContract.Root.COLUMN_AVAILABLE_BYTES
+        };
+        try (final Cursor cursor = mDatabase.queryRoots(columns)) {
+            assertEquals(1, cursor.getCount());
+            assertTrue(cursor.moveToNext());
+            assertEquals(1, cursor.getLong(0));
+            assertEquals("Device", cursor.getString(1));
+            assertTrue(cursor.isNull(2));
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index d3c1364..210682f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.UserInfo;
 import android.graphics.Color;
@@ -178,7 +179,7 @@
                     if (userInfo.isManagedProfile()) {
                         // If userInfo.id is a managed profile, we also need to look at
                         // the policies set on the parent.
-                        DevicePolicyManager parentDpm = dpm.getParentProfileInstance(admin);
+                        DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
                         if ((parentDpm.getKeyguardDisabledFeatures(admin, userInfo.id)
                                 & keyguardFeatures) != 0) {
                             if (enforcedAdmin == null) {
@@ -227,6 +228,26 @@
     }
 
     /**
+     * Check if an application is suspended.
+     *
+     * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
+     * or {@code null} if the application is not suspended.
+     */
+    public static EnforcedAdmin checkIfApplicationIsSuspended(Context context, String packageName,
+            int userId) {
+        IPackageManager ipm = AppGlobals.getPackageManager();
+        try {
+            ApplicationInfo ai = ipm.getApplicationInfo(packageName, 0, userId);
+            if (ai != null && ((ai.flags & ApplicationInfo.FLAG_SUSPENDED) != 0)) {
+                return getProfileOrDeviceOwnerOnCallingUser(context);
+            }
+        } catch (RemoteException e) {
+            // Nothing to do
+        }
+        return null;
+    }
+
+    /**
      * Check if account management for a specific type of account is disabled by admin.
      * Only a profile or device owner can disable account management. So, we check if account
      * management is disabled and return profile or device owner on the calling user.
@@ -375,7 +396,7 @@
                     if (userInfo.isManagedProfile()) {
                         // If userInfo.id is a managed profile, we also need to look at
                         // the policies set on the parent.
-                        DevicePolicyManager parentDpm = dpm.getParentProfileInstance(admin);
+                        DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
                         if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
                             if (enforcedAdmin == null) {
                                 enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 2ee4b12..5b8ed28 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -37,6 +37,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.support.annotation.NonNull;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.TextUtils;
@@ -104,7 +105,8 @@
     private static final int PSK_WPA2 = 2;
     private static final int PSK_WPA_WPA2 = 3;
 
-    private static final int VISIBILITY_OUTDATED_AGE_IN_MILLI = 20000;
+    public static final int SIGNAL_LEVELS = 4;
+
     private final Context mContext;
 
     private String ssid;
@@ -167,7 +169,7 @@
     }
 
     @Override
-    public int compareTo(AccessPoint other) {
+    public int compareTo(@NonNull AccessPoint other) {
         // Active one goes first.
         if (isActive() && !other.isActive()) return -1;
         if (!isActive() && other.isActive()) return 1;
@@ -182,8 +184,9 @@
         if (networkId == WifiConfiguration.INVALID_NETWORK_ID
                 && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
 
-        // Sort by signal strength.
-        int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi);
+        // Sort by signal strength, bucketed by level
+        int difference = WifiManager.calculateSignalLevel(other.mRssi, SIGNAL_LEVELS)
+                - WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
         if (difference != 0) {
             return difference;
         }
@@ -260,7 +263,7 @@
         if (mRssi == Integer.MAX_VALUE) {
             return -1;
         }
-        return WifiManager.calculateSignalLevel(mRssi, 4);
+        return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
     }
 
     public int getRssi() {
diff --git a/packages/SettingsProvider/res/values-bs-rBA/defaults.xml b/packages/SettingsProvider/res/values-bs-rBA/defaults.xml
new file mode 100644
index 0000000..5650077
--- /dev/null
+++ b/packages/SettingsProvider/res/values-bs-rBA/defaults.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for def_device_name (6309317409634339402) -->
+    <skip />
+    <!-- no translation found for def_device_name_simple (9037785625140748221) -->
+    <skip />
+    <string name="def_nfc_payment_component" msgid="5861297439873026958"></string>
+</resources>
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index 9d97e68..b9a7c24 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Tuisskerm"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Foutverslag word tans gegenereer"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Foutverslag vasgevang"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Voeg tans besonderhede by die foutverslag"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Wag asseblief …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swiep na links om jou foutverslag te deel"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Raak om jou foutverslag te deel"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Foutverslae bevat data van die stelsel se verskillende loglêers af, insluitend persoonlike en private inligting. Deel foutverslae net met programme en mense wat jy vertrou."</string>
diff --git a/packages/Shell/res/values-b+sr+Latn/strings.xml b/packages/Shell/res/values-b+sr+Latn/strings.xml
index afed746..f39dbcb 100644
--- a/packages/Shell/res/values-b+sr+Latn/strings.xml
+++ b/packages/Shell/res/values-b+sr+Latn/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Izveštaj o grešci se generiše"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Izveštaj o grešci je snimljen"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodaju se detalji u izveštaj o grešci"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sačekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prevucite ulevo da biste delili izveštaj o greškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Dodirnite da biste delili izveštaj o grešci"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Izveštaji o greškama sadrže podatke iz različitih sistemskih datoteka evidencije, uključujući lične i privatne podatke. Delite izveštaje o greškama samo sa aplikacijama i ljudima u koje imate poverenja."</string>
diff --git a/packages/Shell/res/values-bs-rBA/strings.xml b/packages/Shell/res/values-bs-rBA/strings.xml
new file mode 100644
index 0000000..55a9341
--- /dev/null
+++ b/packages/Shell/res/values-bs-rBA/strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for app_label (3701846017049540910) -->
+    <skip />
+    <!-- no translation found for bugreport_in_progress_title (7409917338223386637) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_title (2293711546892863898) -->
+    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje detalja u izvještaj o greškama"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string>
+    <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+    <skip />
+    <!-- no translation found for bugreport_finished_text (3559904746859400732) -->
+    <skip />
+    <!-- no translation found for bugreport_confirm (5130698467795669780) -->
+    <skip />
+    <!-- no translation found for bugreport_confirm_repeat (4926842460688645058) -->
+    <skip />
+    <!-- no translation found for bugreport_storage_title (5332488144740527109) -->
+    <skip />
+    <!-- no translation found for bugreport_unreadable_text (586517851044535486) -->
+    <skip />
+    <!-- no translation found for bugreport_unnamed (2800582406842092709) -->
+    <skip />
+    <!-- no translation found for bugreport_info_action (2158204228510576227) -->
+    <skip />
+    <!-- no translation found for bugreport_screenshot_action (8677781721940614995) -->
+    <skip />
+    <!-- no translation found for bugreport_screenshot_taken (7175343181767429088) -->
+    <skip />
+    <!-- no translation found for bugreport_screenshot_failed (5853049140806834601) -->
+    <skip />
+    <!-- no translation found for bugreport_info_dialog_title (3113549839798564645) -->
+    <skip />
+    <!-- no translation found for bugreport_info_name (4414036021935139527) -->
+    <skip />
+    <!-- no translation found for bugreport_info_title (5599558206004371052) -->
+    <skip />
+    <!-- no translation found for bugreport_info_description (4117088998733546784) -->
+    <skip />
+</resources>
diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml
index 24d705c..19a4453 100644
--- a/packages/Shell/res/values-cs/strings.xml
+++ b/packages/Shell/res/values-cs/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Vytváří se zpráva o chybě"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Bylo vytvořeno chybové hlášení"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Přidávání podrobností do zprávy o chybě"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Čekejte prosím…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Chcete-li hlášení chyby sdílet, přejeďte doleva."</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Chybové hlášení můžete sdílet klepnutím."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Chybová hlášení obsahují data z různých souborů protokolů systému včetně osobních a soukromých informací. Chybová hlášení sdílejte pouze s aplikacemi a uživateli, kterým důvěřujete."</string>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index 85cad60..4f5e6c5 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Fehlerbericht wird generiert"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Fehlerbericht erfasst"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Informationen werden zum Fehlerbericht hinzugefügt"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Bitte warten…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Wische nach links, um deinen Fehlerbericht zu teilen."</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tippen, um Fehlerbericht zu teilen"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Fehlerberichte enthalten Daten aus verschiedenen Protokolldateien des Systems, darunter auch personenbezogene und private Daten. Teile Fehlerberichte nur mit Apps und Personen, denen du vertraust."</string>
diff --git a/packages/Shell/res/values-en-rAU/strings.xml b/packages/Shell/res/values-en-rAU/strings.xml
index 46f1299..a1bd979 100644
--- a/packages/Shell/res/values-en-rAU/strings.xml
+++ b/packages/Shell/res/values-en-rAU/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Bug report is being generated"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Bug report captured"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml
index 46f1299..a1bd979 100644
--- a/packages/Shell/res/values-en-rGB/strings.xml
+++ b/packages/Shell/res/values-en-rGB/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Bug report is being generated"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Bug report captured"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml
index 46f1299..a1bd979 100644
--- a/packages/Shell/res/values-en-rIN/strings.xml
+++ b/packages/Shell/res/values-en-rIN/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Bug report is being generated"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Bug report captured"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml
index 606b37f..f86fea0 100644
--- a/packages/Shell/res/values-es-rUS/strings.xml
+++ b/packages/Shell/res/values-es-rUS/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"El informe de errores se está generando"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Informe de errores capturado"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Agregando detalles al informe de errores"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Desliza el dedo hacia la izquierda para compartir el informe de errores."</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca para compartir tu informe de errores."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida la información personal y privada. Comparte los informes de errores únicamente con aplicaciones y personas en las que confíes."</string>
diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml
index 18955bdd..0fc4b77 100644
--- a/packages/Shell/res/values-fi/strings.xml
+++ b/packages/Shell/res/values-fi/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Komentotulkki"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Luodaan virheraporttia"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Virheraportti tallennettu"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Lisätään tietoja virheraporttiin"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Odota…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Jaa virheraportti pyyhkäisemällä vasemmalle"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Jaa virheraportti koskettamalla tätä"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Virheraportit sisältävät järjestelmän lokitietoja, ja niihin voi sisältyä henkilökohtaisia ja yksityisiä tietoja. Jaa virheraportteja vain luotettaville sovelluksille ja käyttäjille."</string>
diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml
index 354eac3..d2ef54c 100644
--- a/packages/Shell/res/values-fr-rCA/strings.xml
+++ b/packages/Shell/res/values-fr-rCA/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Le rapport de bogue est en cours de création"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Rapport de bogue enregistré"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout de détails au rapport de bogue"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport de bogue."</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Appuyer ici pour partager votre rapport de bogue"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bogue contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bogue qu\'avec les applications et les personnes que vous estimez fiables."</string>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index 192bbed..ca135ed 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Le rapport de bug est en cours de création."</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Rapport de bug enregistré"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout d\'informations au rapport de bug"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport d\'erreur."</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Appuyez ici pour partager le rapport de bug"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bug qu\'avec les applications et les personnes que vous estimez fiables."</string>
diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml
index c07adb8..612d346 100644
--- a/packages/Shell/res/values-gl-rES/strings.xml
+++ b/packages/Shell/res/values-gl-rES/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Estase xerando o informe de erro"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Informe de erros rexistrado"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Engadindo detalles ao informe de erro"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Agarda..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Pasa o dedo á esquerda para compartir o teu informe de erros"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca aquí para compartir o teu informe de erros"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os informes de erros conteñen datos dos distintos ficheiros de rexistro do sistema, incluída información persoal e privada. Comparte os informes de erros unicamente con aplicacións e persoas de confianza."</string>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index 36d2cce..810ad3a 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Ljuska"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Generira se izvješće o programskoj pogrešci"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Prijava programske pogreške snimljena je"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje pojedinosti u izvješće o progr. pogrešci"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prijeđite prstom ulijevo da biste poslali izvješće o programskim pogreškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Dodirnite za dijeljenje prijave programske pogreške"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Prijave programskih pogrešaka sadržavaju podatke iz različitih datoteka zapisnika sustava, uključujući osobne i privatne informacije. Prijave programskih pogrešaka dijelite samo s aplikacijama i osobama koje smatrate pouzdanima."</string>
diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml
index 0635d39..4912d54 100644
--- a/packages/Shell/res/values-hy-rAM/strings.xml
+++ b/packages/Shell/res/values-hy-rAM/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Խեցի"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Վրիպակի զեկույցը ստեղծվում է"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Վրիպակի զեկույց է ստացվել"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Տվյալների ավելացում վրիպակի զեկույցում"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Խնդրում ենք սպասել…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Սահեցրեք ձախ՝ սխալի հաշվետվությունը համօգտագործելու համար"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Հպեք` ձեր վրիպակի մասին զեկույցը տարածելու համար"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մուտքի ֆայլերից, այդ թվում նաև անհատական ​​և գաղտնի տեղեկություններ: Վրիպակի զեկույցները կիսեք միայն այն հավելվածների և մարդկանց հետ, որոնց վստահում եք:"</string>
diff --git a/packages/Shell/res/values-is-rIS/strings.xml b/packages/Shell/res/values-is-rIS/strings.xml
index a8fc182..d175b4f 100644
--- a/packages/Shell/res/values-is-rIS/strings.xml
+++ b/packages/Shell/res/values-is-rIS/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Skipanalína"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Verið er að búa til villutilkynningu"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Villutilkynning útbúin"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Bætir upplýsingum við villutilkynningu"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Augnablik..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Strjúktu til vinstri til að deila villuskýrslunni"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Snertu til að deila villutilkynningunni"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Villutilkynningar innihalda gögn úr hinum ýmsu annálsskrám kerfisins, þ. á m. persónuleg gögn og trúnaðarupplýsingar. Deildu villutilkynningum eingöngu með forritum og fólki sem þú treystir."</string>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index c869e01..40bd73b 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"מעטפת"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"מופק דוח על באג"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"דוח הבאגים צולם"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"מוסיף פרטים לדוח על הבאג"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"המתן…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"החלק שמאלה כדי לשתף את דוח הבאגים"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"גע כדי לשתף את דוח הבאגים שלך"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"דוחות על באגים כוללים נתונים מקובצי היומן השונים במערכת, כולל מידע אישי ופרטי. שתף דוחות באגים רק עם אפליקציות ואנשים שאתה סומך עליהם."</string>
diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml
index ba40614..f0183b5 100644
--- a/packages/Shell/res/values-ja/strings.xml
+++ b/packages/Shell/res/values-ja/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"シェル"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"バグレポートを生成しています"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"バグレポートが記録されました"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"バグレポートに詳細情報を追加しています"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"お待ちください…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"バグレポートを共有するには左にスワイプ"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"バグレポートを共有するにはタップします"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"バグレポートには、個人の非公開情報など、システムのさまざまなログファイルのデータが含まれます。共有する場合は信頼するアプリとユーザーのみを選択してください。"</string>
diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml
index eb4d10a..a7ad694 100644
--- a/packages/Shell/res/values-ka-rGE/strings.xml
+++ b/packages/Shell/res/values-ka-rGE/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"გარეკანი"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"მიმდინარეობს ხარვეზის შესახებ ანგარიშის გენერირება"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"ანგარიში ხარვეზების შესახებ შექმნილია"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"ხარვეზის შესახებ ანგარიშს დეტალები ემატება"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"გთხოვთ, მოითმინოთ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"გაასრიალეთ მარცხნივ თქვენი ხარვეზის შეტყობინების გასაზიარებლად"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"შეეხეთ თქვენი ხარვეზების ანგარიშის გასაზიარებლად"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ხარვეზის ანგარიშები მოიცავს მონაცემებს სხვადასხვა სისტემური ჟურნალის ფაილებიდან, მათ შორის პირად და კონფიდენციალურ ინფორმაციას."</string>
diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml
index 995bc76..25a3879 100644
--- a/packages/Shell/res/values-kk-rKZ/strings.xml
+++ b/packages/Shell/res/values-kk-rKZ/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Қабыршық"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Қате туралы есеп жасалып жатыр"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Вирус туралы баянат қабылданды"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Қате туралы есепке мәліметтер қосылуда"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күте тұрыңыз…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Қате туралы есепті бөлісу үшін солға жанаңыз"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Бөліс үшін, вирус туралы баянатты түртіңіз."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Вирус туралы баянатта жүйеде тіркелген әртүрлі файлдар туралы деректер болады, оған жеке және құпия ақпарат та кіреді. Вирус баянаттарын сенімді қолданбалар және сенімді адамдармен ғана бөлісіңіз."</string>
diff --git a/packages/Shell/res/values-kn-rIN/strings.xml b/packages/Shell/res/values-kn-rIN/strings.xml
index 880b279..a3c9b95 100644
--- a/packages/Shell/res/values-kn-rIN/strings.xml
+++ b/packages/Shell/res/values-kn-rIN/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"ಶೆಲ್"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"ದೋಷ ವರದಿಯನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"ದೋಷದ ವರದಿಯನ್ನು ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"ಬಗ್ ವರದಿಗೆ ವಿವರಗಳನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ನಿಮ್ಮ ದೋಷ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್‌ ಮಾಡಿ"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ನಿಮ್ಮ ದೋಷದ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಸ್ಪರ್ಶಿಸಿ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ವೈಯಕ್ತಿಕ ಮತ್ತು ಖಾಸಗಿ ಮಾಹಿತಿಯು ಸೇರಿದಂತೆ, ಸಿಸ್ಟಂನ ಹಲವಾರು ಲಾಗ್ ಫೈಲ್‌ಗಳಿಂದ ಡೇಟಾವನ್ನು ದೋಷದ ವರದಿಗಳು ಒಳಗೊಂಡಿವೆ. ನೀವು ನಂಬುವಂತಹ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಜನರೊಂದಿಗೆ ಮಾತ್ರ ದೋಷದ ವರದಿಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ."</string>
diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml
index 42527cc..8ad785c 100644
--- a/packages/Shell/res/values-ky-rKG/strings.xml
+++ b/packages/Shell/res/values-ky-rKG/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Командалык кабык"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Мүчүлүштүктөр тууралуу билдирүү түзүлүүдө"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Ката тууралуу билдирүү түзүлдү"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Мүчүлүштүк жөнүндө кабардын чоо-жайы кошулууда"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күтө туруңуз…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Ката жөнүндө кабар менен бөлүшүү үчүн солго серпип коюңуз"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Ката тууралуу билдирүүңүздү жөнөтүш үчүн, тийиңиз"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Ката тууралуу билдирүүлөр системанын ар кандай лог файлдарынын берилиштерин камтыйт, аларга өздүк жана купуя маалыматтар дагы кирет. Ката тууралуу билдирүүлөрдү сиз ишенген колдонмолор жана адамдар менен гана бөлүшүңүз."</string>
diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml
index ec278fb..d159254 100644
--- a/packages/Shell/res/values-lo-rLA/strings.xml
+++ b/packages/Shell/res/values-lo-rLA/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"ກຳລັງສ້າງລາຍງານບັນຫາ"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"ລາຍງານຈຸດບົກພ່ອງຖືກເກັບກຳແລ້ວ"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"ກຳລັງເພີ່ມລາຍລະອຽດໃສ່ລາຍງານຂໍ້ຜິດພາດ"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"ກະລຸນາລໍຖ້າ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"​ປັດ​ໄປ​ຊ້າຍ​ເພື່ອ​ສົ່ງ​ລາຍ​ງານ​ຂໍ້​ຜິດ​ພາດ​ຂອງ​ທ່ານ"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ແຕະເພື່ອສົ່ງການລາຍງານປັນຫາຂອງທ່ານ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ການລາຍງານຂໍ້ຜິດພາດປະກອບມີ ຂໍ້ມູນຈາກໄຟລ໌ບັນທຶກຂອງລະບົບຫຼາຍໄຟລ໌, ຮວມທັງຂໍ້ມູນສ່ວນໂຕນຳ. ທ່ານຕ້ອງແບ່ງປັນລາຍງານຂໍ້ຜິດພາດໃຫ້ແອັບຯ ແລະຄົນທີ່ທ່ານເຊື່ອຖືໄດ້ເທົ່ານັ້ນ."</string>
diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml
index 5212aaa..1baa343 100644
--- a/packages/Shell/res/values-lv/strings.xml
+++ b/packages/Shell/res/values-lv/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Aizsargs"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Notiek kļūdas pārskata izveide"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Izveidots kļūdu pārskats"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Informācijas pievienošana kļūdas pārskatam"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lūdzu, uzgaidiet..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Velciet pa kreisi, lai kopīgotu savu kļūdu ziņojumu."</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Pieskarieties, lai kopīgotu kļūdu pārskatu."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Kļūdu pārskatā ir iekļauti dati no dažādiem sistēmas žurnālfailiem, tostarp personas dati un privāta informācija. Kļūdu pārskatus ieteicams kopīgot tikai ar uzticamām lietotnēm un lietotājiem."</string>
diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml
index e13ce4c..efbec8e 100644
--- a/packages/Shell/res/values-mk-rMK/strings.xml
+++ b/packages/Shell/res/values-mk-rMK/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Обвивка"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Се генерира извештајот за грешки"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Извештајот за грешка е снимен"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Се додаваат детали на извештајот за грешка"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Почекајте..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Повлечете налево за да споделите пријава за грешка"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Допри да се сподели твојот извештај за грешка"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаите за грешка содржат податоци од разни датотеки за евиденција на системот, вклучувајќи лични и приватни информации. Извештаите за грешка споделувајте ги само со апликации и луѓе на коишто им верувате."</string>
diff --git a/packages/Shell/res/values-mr-rIN/strings.xml b/packages/Shell/res/values-mr-rIN/strings.xml
index b621928..763eec6 100644
--- a/packages/Shell/res/values-mr-rIN/strings.xml
+++ b/packages/Shell/res/values-mr-rIN/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"शेल"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"दोष अहवाल तयार केला जात आहे"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"दोष अहवाल कॅप्‍चर केला"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"दोष अहवालामध्‍ये तपशील जोडत आहे"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करा..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"आपला दोष अहवाल सामायिक करण्यासाठी डावीकडे स्वाइप करा"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"आपला दोष अहवाल सामायिक करण्‍यासाठी स्‍पर्श करा"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"दोष अहवालांमध्‍ये वैयक्तिक आणि खाजगी माहितीसह, सिस्‍टमच्‍या अनेक लॉग फायलींमधील डेटा असतो. केवळ आपला विश्वास असलेल्‍या अ‍ॅप्‍स आणि लोकांसह दोष अहवाल सामायिक करा."</string>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index c14d3ed..1afe430 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Laporan pepijat sedang dijana"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Laporan pepijat telah ditangkap"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Menambahkan butiran pada laporan pepijat"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sila tunggu…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Leret ke kiri untuk berkongsi laporan pepijat anda"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Sentuh untuk berkongsi laporan pepijat anda"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan pepijat mengandungi data dari pelbagai fail log sistem, termasuk maklumat peribadi dan sulit. Kongsikan laporan pepijat hanya dengan apl dan orang yang anda percayai."</string>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index 5abb9dd..87b3530 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Kommandoliste"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Feilrapporten blir generert"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Feilrapporten er lagret"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Legger til detaljer i feilrapporten"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vent litt"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Sveip til venstre for å dele feilrapporten din"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Trykk for å dele feilrapporten din"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Feilrapporter inkluderer data fra systemets forskjellige loggfiler. Dette omfatter personlig og privat informasjon. Du bør bare dele feilrapporter med apper og folk du stoler på."</string>
diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml
index 2176ef1..7a67ac6 100644
--- a/packages/Shell/res/values-pl/strings.xml
+++ b/packages/Shell/res/values-pl/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Powłoka"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Trwa generowanie raportu o błędzie"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Raport o błędach został zapisany"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodaję szczegóły do raportu o błędzie"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Czekaj..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Przesuń palcem w lewo, by udostępnić swoje zgłoszenie błędu"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Kliknij, by udostępnić raport o błędach"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Raporty o błędach zawierają dane z różnych plików dzienników systemu, w tym dane osobowe i prywatne. Udostępniaj je tylko aplikacjom i osobom, którym ufasz."</string>
diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml
index a215a16..471e959 100644
--- a/packages/Shell/res/values-pt-rBR/strings.xml
+++ b/packages/Shell/res/values-pt-rBR/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Um relatório do bug está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Relatório de bugs capturado"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toque para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index a413172..ed78f55 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"O relatório de erro está a ser criado"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Relatório de erros capturado"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"A adicionar detalhes ao relatório de erro"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslizar rapidamente para a esquerda para partilhar o seu relatório de erros"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toque para partilhar o relatório de erros"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de erros incluem dados de vários ficheiros de registo do sistema, nomeadamente informações pessoais e privadas. Partilhe relatórios de erros apenas com aplicações e pessoas fidedignas."</string>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index a215a16..471e959 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Um relatório do bug está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Relatório de bugs capturado"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toque para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string>
diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml
index 46c7924..af67bc6 100644
--- a/packages/Shell/res/values-ro/strings.xml
+++ b/packages/Shell/res/values-ro/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Se generează raportul de eroare"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Raportul despre erori a fost creat"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Se adaugă detaliile la raportul de eroare"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Așteptați…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Glisați la stânga pentru a trimite raportul de erori"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Atingeți pentru a permite accesul la raportul despre erori"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Rapoartele despre erori conțin date din diferite fișiere de jurnal ale sistemului, inclusiv informații private și personale. Permiteți accesul la rapoartele despre erori numai aplicațiilor și persoanelor în care aveți încredere."</string>
diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml
index ef60015..a5e2bd2 100644
--- a/packages/Shell/res/values-ru/strings.xml
+++ b/packages/Shell/res/values-ru/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Оболочка"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Создание отчета об ошибке…"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Отчет об ошибке сохранен"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Добавление данных в отчет об ошибке"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Подождите…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Проведите влево, чтобы отправить отчет"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Нажмите, чтобы отправить отчет об ошибках"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Отчеты об ошибках содержат данные различных системных журналов и могут включать личную информацию. Рекомендуем открывать к ним доступ только лицам и приложениям, заслуживающим доверие."</string>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index 606e797..c249961 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Lupina"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Poročilo o napakah se pripravlja"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Poročilo o napaki je posneto"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodajanje podrobnosti v poročilo o napakah"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Počakajte ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Povlecite v levo, če želite poslati sporočilo o napaki"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Dotaknite se, če želite deliti sporočilo o napaki z drugimi"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Poročila o napakah vsebujejo podatke iz različnih dnevniških datotek sistema, vključno z osebnimi in zasebnimi podatki. Poročila o napakah delite samo z aplikacijami in ljudmi, ki jim zaupate."</string>
diff --git a/packages/Shell/res/values-sq-rAL/strings.xml b/packages/Shell/res/values-sq-rAL/strings.xml
index ae30d68..8a306b3 100644
--- a/packages/Shell/res/values-sq-rAL/strings.xml
+++ b/packages/Shell/res/values-sq-rAL/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Guaska"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Po krijohet raporti i defekteve në kod"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Raporti i defektit në kod u regjistrua"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Po shtohen detajet te raporti i defekteve në kod"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Qëndro në pritje..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Rrëshqit majtas për të ndarë raportin e defektit në kod"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Prek për të ndarë raportin e defektit në kod"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Raportet e gabimeve përmbajnë të dhëna nga skedarë të ndryshëm ditarësh sistemi, përfshi informacione personale dhe private. Shpërndaji publikisht raportet e gabimeve vetëm me aplikacionet dhe personat që iu beson."</string>
diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml
index d1646f4..9bff65c 100644
--- a/packages/Shell/res/values-sr/strings.xml
+++ b/packages/Shell/res/values-sr/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Извештај о грешци се генерише"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Извештај о грешци је снимљен"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Додају се детаљи у извештај о грешци"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Сачекајте..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Превуците улево да бисте делили извештај о грешкама"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Додирните да бисте делили извештај о грешци"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаји о грешкама садрже податке из различитих системских датотека евиденције, укључујући личне и приватне податке. Делите извештаје о грешкама само са апликацијама и људима у које имате поверења."</string>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index 3a13837..fb962bf 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Skal"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Felrapporten genereras"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Felrapporten har skapats"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Lägger till information i felrapporten"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vänta …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Svep åt vänster om du vill dela felrapporten"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tryck om du vill dela felrapporten"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Felrapporter innehåller data från systemets olika loggfiler, inklusive personliga och privata uppgifter. Dela bara felrapporter med personer du litar på."</string>
diff --git a/packages/Shell/res/values-ta-rIN/strings.xml b/packages/Shell/res/values-ta-rIN/strings.xml
index 77bec36..15c7014 100644
--- a/packages/Shell/res/values-ta-rIN/strings.xml
+++ b/packages/Shell/res/values-ta-rIN/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"ஷெல்"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"பிழை அறிக்கை உருவாக்கப்படுகிறது"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"பிழை அறிக்கைகள் படமெடுக்கப்பட்டன"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"பிழை அறிக்கையில் விவரங்களைச் சேர்க்கிறது"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"காத்திருக்கவும்…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"பிழை அறிக்கையைப் பகிர இடது புறமாகத் தேய்க்கவும்"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"உங்கள் பிழை அறிக்கையைப் பகிர, தொடவும்"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"பிழை அறிக்கைகளில், சொந்த வாழ்க்கை மற்றும் தனிப்பட்ட தகவல் உள்பட கணினியின் பல்வேறு பதிவுகளில் உள்ள தரவு இருக்கும். நீங்கள் நம்பும் பயன்பாடுகள் மற்றும் நபர்களுடன் மட்டும் பிழை அறிக்கைகளைப் பகிரவும்."</string>
diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml
index cfad947..f29978e 100644
--- a/packages/Shell/res/values-th/strings.xml
+++ b/packages/Shell/res/values-th/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"กำลังสร้างรายงานข้อบกพร่อง"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"จับภาพรายงานข้อบกพร่องแล้ว"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"กำลังเพิ่มรายละเอียดในรายงานข้อบกพร่อง"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"โปรดรอสักครู่…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"กวาดไปทางซ้ายเพื่อแชร์รายงานข้อบกพร่อง"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"รายงานข้อบกพร่องมีข้อมูลจากไฟล์บันทึกต่างๆ ของระบบ รวมถึงข้อมูลส่วนตัว แชร์รายงานข้อบกพร่องกับแอปและบุคคลที่คุณไว้ใจเท่านั้น"</string>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index c89fe56..c12191a 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Binubuo na ang ulat ng bug"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Na-capture ang ulat ng bug"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Pagdaragdag ng mga detalye sa ulat ng bug"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Mangyaring maghintay..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Mag-swipe pakaliwa upang ibahagi ang iyong ulat ng bug"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Pindutin upang ibahagi ang iyong ulat ng bug"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Naglalaman ang mga ulat ng bug ng data mula sa iba\'t ibang file ng log ng system, kabilang ang personal at pribadong impormasyon. Magbahagi lang ng mga ulat ng bug sa apps at mga tao na pinagkakatiwalaan mo."</string>
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index ac974d4..3f562d7 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Kabuk"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Hata raporu oluşturuluyor"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Hata raporu kaydedildi"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Hata raporuna ayrıntılar ekleniyor"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfen bekleyin…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Hata raporunuzu paylaşmak için hızlıca sola kaydırın"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Hata raporunuzu paylaşmak için dokunun"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Hata raporları, kişisel ve özel bilgiler dahil olmak üzere sistemin çeşitli günlük dosyalarından veriler içerir. Hata raporlarını sadece güvendiğiniz uygulamalar ve kişilerle paylaşın."</string>
diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml
index fd31369..52a45a0 100644
--- a/packages/Shell/res/values-ur-rPK/strings.xml
+++ b/packages/Shell/res/values-ur-rPK/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"شیل"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"بگ رپورٹ تخلیق ہو رہی ہے"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"بَگ رپورٹ کیپچر کر لی گئی"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"بگ رپورٹ میں تفصیلات شامل کی جا رہی ہیں"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"براہ کرم انتظار کریں…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"اپنی بگ رپورٹ کا اشتراک کرنے کیلئے بائیں سوائپ کریں"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"اپنی بَگ رپورٹ کا اشتراک کرنے کیلئے ٹچ کریں"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"بَگ رپورٹس میں سسٹم کی مختلف لاگ فائلوں سے ڈیٹا شامل ہوتا ہے، بشمول ذاتی اور نجی معلومات۔ بَگ رپورٹس کا اشتراک صرف اپنے بھروسے مند ایپس اور لوگوں کے ساتھ کریں۔"</string>
diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml
index b0c5a20..56e0965 100644
--- a/packages/Shell/res/values-uz-rUZ/strings.xml
+++ b/packages/Shell/res/values-uz-rUZ/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Terminal"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"Xatoliklar hisoboti tayyorlanmoqda"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"Xatolik hisobotini yozib olindi"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"Xatoliklar hisobotiga tafsilotlar qo‘shilmoqda"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"Iltimos, kuting…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Xatolik hisobotini yuborish uchun barmog‘ingiz bilan chapga suring"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Xatolik hisobotini bo‘lishish uchun barmog‘ingizni tegizing."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Xatolik hisobotlari tizimdagi har xil jurnal fayllardagi ma’lumotlarni, shuningdek, shaxsiy hamda maxfiy ma’lumotlarni o‘z ichiga oladi. Xatolik hisobotlarini faqat ishonchli dasturlar va odamlar bilan bo‘lishing."</string>
diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml
index 48ef30f..c933961 100644
--- a/packages/Shell/res/values-zh-rCN/strings.xml
+++ b/packages/Shell/res/values-zh-rCN/strings.xml
@@ -19,10 +19,8 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="7409917338223386637">"正在生成错误报告"</string>
     <string name="bugreport_finished_title" msgid="2293711546892863898">"已抓取错误报告"</string>
-    <!-- no translation found for bugreport_updating_title (4423539949559634214) -->
-    <skip />
-    <!-- no translation found for bugreport_updating_wait (3322151947853929470) -->
-    <skip />
+    <string name="bugreport_updating_title" msgid="4423539949559634214">"正在向错误报告添加详细信息"</string>
+    <string name="bugreport_updating_wait" msgid="3322151947853929470">"请稍候…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑动即可分享错误报告"</string>
     <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"触摸即可分享您的错误报告"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"错误报告包含的数据来自于系统的各个日志文件,其中包含个人信息和隐私信息。请务必只与您信任的应用和用户分享错误报告。"</string>
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index e4d0fec..88313bb 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -12,6 +12,7 @@
     android-support-v7-preference \
     android-support-v7-appcompat \
     android-support-v14-preference \
+    android-support-v17-leanback \
     framework-protos
 
 LOCAL_JAVA_LIBRARIES := telephony-common
@@ -30,10 +31,12 @@
     frameworks/support/v7/preference/res \
     frameworks/support/v14/preference/res \
     frameworks/support/v7/appcompat/res \
-    frameworks/support/v7/recyclerview/res
+    frameworks/support/v7/recyclerview/res \
+    frameworks/support/v17/leanback/res
 
 LOCAL_AAPT_FLAGS := --auto-add-overlay \
-    --extra-packages com.android.keyguard:android.support.v7.recyclerview:android.support.v7.preference:android.support.v14.preference:android.support.v7.appcompat
+    --extra-packages com.android.keyguard:android.support.v7.recyclerview:android.support.v7.preference:android.support.v14.preference:android.support.v7.appcompat \
+    --extra-packages android.support.v17.leanback
 
 ifneq ($(SYSTEM_UI_INCREMENTAL_BUILDS),)
     LOCAL_PROGUARD_ENABLED := disabled
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 21abb90..2713fb5 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -236,6 +236,20 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".recents.tv.RecentsTvActivity"
+                  android:label="@string/accessibility_desc_recent_apps"
+                  android:exported="false"
+                  android:launchMode="singleInstance"
+                  android:excludeFromRecents="true"
+                  android:stateNotNeeded="true"
+                  android:resumeWhilePausing="true"
+                  android:screenOrientation="behind"
+                  android:theme="@style/RecentsTheme.Wallpaper">
+            <intent-filter>
+                <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
+            </intent-filter>
+        </activity>
+
         <!-- Callback for dismissing screenshot notification after a share target is picked -->
         <receiver android:name=".screenshot.GlobalScreenshot$TargetChosenReceiver"
                   android:process=":screenshot"
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 2ea8c9c..d0c2d29 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -35,3 +35,4 @@
 }
 
 -keep class ** extends android.support.v14.preference.PreferenceFragment
+-keep class com.android.systemui.tuner.*
diff --git a/packages/SystemUI/res/drawable/clipboard_empty.xml b/packages/SystemUI/res/drawable/clipboard_empty.xml
new file mode 100644
index 0000000..14a5ad2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/clipboard_empty.xml
@@ -0,0 +1,25 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the License);
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an AS IS BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.0,2.0l-4.18,0.0C14.0,0.84 13.3,0.0 12.0,0.0c-1.3,0.0 -2.0,0.84 -2.82,2.0L5.0,2.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,16.0c0.0,1.0 0.9,2.0 2.0,2.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L21.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,0.0c0.55,0.0 1.0,0.45 1.0,1.0s-0.45,1.0 -1.0,1.0 -1.0,-0.45 -1.0,-1.0 0.45,-1.0 1.0,-1.0zm7.0,18.0L5.0,20.0L5.0,4.0l2.0,0.0l0.0,3.0l10.0,0.0L17.0,4.0l2.0,0.0l0.0,16.0z" />
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/clipboard_full.xml b/packages/SystemUI/res/drawable/clipboard_full.xml
new file mode 100644
index 0000000..2d46870
--- /dev/null
+++ b/packages/SystemUI/res/drawable/clipboard_full.xml
@@ -0,0 +1,25 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the License);
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an AS IS BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24.0dp"
+    android:height="24.0dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.0,2.0l-4.18,0.0C14.0,0.84 13.3,0.0 12.0,0.0c-1.3,0.0 -2.0,0.84 -2.82,2.0L5.0,2.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,16.0c0.0,1.0 0.9,2.0 2.0,2.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L21.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,0.0c0.55,0.0 1.0,0.45 1.0,1.0s-0.45,1.0 -1.0,1.0 -1.0,-0.45 -1.0,-1.0 0.45,-1.0 1.0,-1.0zm7.0,18.0L5.0,20.0L5.0,4.0l2.0,0.0l0.0,3.0l10.0,0.0L17.0,4.0l2.0,0.0l0.0,16.0z M 6,8 l 12,0 l 0,11 l -12,0 l 0,-11z" />
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_drag_handle.xml b/packages/SystemUI/res/drawable/ic_drag_handle.xml
new file mode 100644
index 0000000..9b319f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_drag_handle.xml
@@ -0,0 +1,24 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M20.0,9.0L4.0,9.0l0.0,2.0l16.0,0.0L20.0,9.0zM4.0,15.0l16.0,0.0l0.0,-2.0L4.0,13.0l0.0,2.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_history.xml b/packages/SystemUI/res/drawable/ic_history.xml
new file mode 100644
index 0000000..e936864
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_history.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89 .07 .14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7
+7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13
+21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54 .72 -1.21-3.5-2.08V8H12z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
new file mode 100644
index 0000000..b4144a3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
@@ -0,0 +1,24 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="40.0"
+        android:viewportHeight="40.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_width.xml b/packages/SystemUI/res/drawable/ic_width.xml
new file mode 100644
index 0000000..a302c81
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_width.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M7.77,6.76L6.23,5.4 0.82,12.0l5.41,6.52 1.54,-1.28L3.42,12.0l4.35,-5.24z
+        M17.77,5.48l-1.54,1.28L20.58,12.0l-4.35,5.24 1.54,1.28L23.18,12.0l-5.41,-6.52z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M2.0,13.0l20.0,0.0l0.0,-2.0l-20.0,0.0l0.0,2.0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/recents_dismiss_all_history.xml b/packages/SystemUI/res/drawable/recents_dismiss_all_history.xml
new file mode 100644
index 0000000..6a417e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_dismiss_all_history.xml
@@ -0,0 +1,54 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="16dp"
+    android:width="28dp"
+    android:viewportHeight="48"
+    android:viewportWidth="72" >
+    <group
+        android:name="dismiss_all"
+        android:translateX="48"
+        android:translateY="6" >
+        <group
+            android:name="3"
+            android:translateX="-24"
+            android:translateY="36" >
+            <path
+                android:name="rectangle_path_1_2"
+                android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
+                android:fillColor="#FFFFFFFF"
+                android:fillAlpha="1" />
+        </group>
+        <group
+            android:name="2"
+            android:translateX="-12"
+            android:translateY="18" >
+            <path
+                android:name="rectangle_path_1_1"
+                android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
+                android:fillColor="#FFFFFFFF"
+                android:fillAlpha="1" />
+        </group>
+        <group
+            android:name="1" >
+            <path
+                android:name="rectangle_path_1"
+                android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
+                android:fillColor="#FFFFFFFF"
+                android:fillAlpha="1" />
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
new file mode 100644
index 0000000..4e2a024
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_disabled.xml
@@ -0,0 +1,24 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="17.0dp"
+        android:height="17.0dp"
+        android:viewportWidth="40.0"
+        android:viewportHeight="40.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/switchbar_background.xml b/packages/SystemUI/res/drawable/switchbar_background.xml
new file mode 100644
index 0000000..8d97c46
--- /dev/null
+++ b/packages/SystemUI/res/drawable/switchbar_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:drawable="@color/switch_bar_background" />
+</ripple>
+
diff --git a/packages/SystemUI/res/layout-land/nav_bar_tuner.xml b/packages/SystemUI/res/layout-land/nav_bar_tuner.xml
new file mode 100644
index 0000000..a430b73
--- /dev/null
+++ b/packages/SystemUI/res/layout-land/nav_bar_tuner.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:elevation="4dp"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"
+        android:paddingStart="8dp"
+        android:paddingEnd="8dp"
+        android:background="@android:color/white"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/preview"
+            android:paddingStart="8dp"
+            android:paddingEnd="8dp"
+            android:textColor="?android:attr/colorAccent"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <FrameLayout
+            android:id="@+id/nav_preview_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp-land/nav_bar_tuner.xml b/packages/SystemUI/res/layout-sw600dp-land/nav_bar_tuner.xml
new file mode 100644
index 0000000..5479157
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp-land/nav_bar_tuner.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:elevation="4dp"
+        android:paddingTop="8dp"
+        android:paddingBottom="8dp"
+        android:paddingStart="12dp"
+        android:paddingEnd="12dp"
+        android:layout_gravity="bottom"
+        android:background="@android:color/white"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/preview"
+            android:paddingTop="8dp"
+            android:paddingBottom="8dp"
+            android:textColor="?android:attr/colorAccent"
+            android:textAppearance="?android:attr/textAppearanceLarge" />
+
+        <FrameLayout
+            android:id="@+id/nav_preview_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/clipboard.xml b/packages/SystemUI/res/layout/clipboard.xml
new file mode 100644
index 0000000..441d6737
--- /dev/null
+++ b/packages/SystemUI/res/layout/clipboard.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.systemui.tuner.ClipboardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="@dimen/navigation_side_padding"
+    android:layout_height="match_parent"
+    android:layout_weight="0"
+    android:scaleType="center"
+    android:contentDescription="@string/clipboard"
+    />
+
diff --git a/packages/SystemUI/res/layout/color_matrix_settings.xml b/packages/SystemUI/res/layout/color_matrix_settings.xml
new file mode 100644
index 0000000..3725e78
--- /dev/null
+++ b/packages/SystemUI/res/layout/color_matrix_settings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/switch_bar" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/custom_key.xml b/packages/SystemUI/res/layout/custom_key.xml
new file mode 100644
index 0000000..0b5cb72
--- /dev/null
+++ b/packages/SystemUI/res/layout/custom_key.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.systemui.statusbar.policy.KeyButtonView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="@dimen/navigation_side_padding"
+    android:layout_height="match_parent"
+    android:layout_weight="0"
+    android:scaleType="center"
+    android:tint="@android:color/white"
+    android:contentDescription="@string/accessibility_key" />
+
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
new file mode 100644
index 0000000..5a6553f
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/keyboard_shortcuts_keyword_wrapper"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="24dp"
+        android:paddingEnd="24dp"
+        android:paddingBottom="8dp">
+    <TextView
+            android:id="@+id/keyboard_shortcuts_keyword"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingEnd="12dp"
+            android:background="@android:color/white"
+            android:textColor="#D9000000"
+            android:textSize="16sp"
+            android:maxLines="5"
+            android:singleLine="false"
+            android:scrollHorizontally="false"
+            android:layout_alignParentStart="true"
+            android:minWidth="100dp"
+            android:maxWidth="260dp"/>
+    <!--TODO: introduce and use a layout that allows wrapping and right align -->
+    <LinearLayout
+            android:id="@+id/keyboard_shortcuts_item_container"
+            android:layout_toEndOf="@+id/keyboard_shortcuts_keyword"
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@android:color/white"
+            android:layout_alignParentEnd="true"
+            android:gravity="end"
+            android:textSize="14sp"
+            android:paddingStart="0dp"
+            android:paddingEnd="0dp"
+            android:scrollHorizontally="false"
+            android:minWidth="100dp"
+            android:maxWidth="260dp"/>
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
new file mode 100644
index 0000000..80a478a
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="match_parent"
+          android:layout_height="match_parent"
+          android:textSize="14sp"
+          android:paddingStart="24dp"
+          android:paddingTop="20dp"
+          android:paddingEnd="24dp"
+          android:paddingBottom="13dp" />
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml
new file mode 100644
index 0000000..fa07eb1
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="horizontal"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content">
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
new file mode 100644
index 0000000..5002c12
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_marginStart="4dp"
+          android:padding="4dp"
+          android:background="#EEEEEE"
+          android:textColor="#8C000000"
+          android:singleLine="true"
+          android:textSize="14sp"/>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
index 460433e..77b1264 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2015 The Android Open Source Project
+  ~ Copyright (C) 2016 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
@@ -14,11 +14,25 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/keyboard_shortcuts_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginTop="40dp"
-    android:focusable="true">
-</RelativeLayout>
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/keyboard_shortcuts_wrapper"
+        android:layout_width="488dp"
+        android:layout_height="wrap_content"
+        android:focusable="true">
+    <ScrollView
+            android:id="@+id/keyboard_shortcuts_scroll_view"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1">
+        <LinearLayout
+                android:id="@+id/keyboard_shortcuts_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"/>
+    </ScrollView>
+    <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="?android:attr/listDivider"/>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml
new file mode 100644
index 0000000..802acfe
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content">
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/nav_bar_tuner.xml b/packages/SystemUI/res/layout/nav_bar_tuner.xml
new file mode 100644
index 0000000..5479157
--- /dev/null
+++ b/packages/SystemUI/res/layout/nav_bar_tuner.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:elevation="4dp"
+        android:paddingTop="8dp"
+        android:paddingBottom="8dp"
+        android:paddingStart="12dp"
+        android:paddingEnd="12dp"
+        android:layout_gravity="bottom"
+        android:background="@android:color/white"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/preview"
+            android:paddingTop="8dp"
+            android:paddingBottom="8dp"
+            android:textColor="?android:attr/colorAccent"
+            android:textAppearance="?android:attr/textAppearanceLarge" />
+
+        <FrameLayout
+            android:id="@+id/nav_preview_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
new file mode 100644
index 0000000..b237633
--- /dev/null
+++ b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.systemui.tuner.PreviewNavInflater
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:background="@android:color/black"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/navigation_bar_size">
+
+    <include android:id="@+id/rot0" layout="@layout/navigation_layout" />
+
+    <include android:id="@+id/rot90" layout="@layout/navigation_layout_rot90" />
+
+</com.android.systemui.tuner.PreviewNavInflater>
diff --git a/packages/SystemUI/res/layout/nav_control_widget.xml b/packages/SystemUI/res/layout/nav_control_widget.xml
new file mode 100644
index 0000000..51dd68f
--- /dev/null
+++ b/packages/SystemUI/res/layout/nav_control_widget.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    android:gravity="center"
+    android:orientation="horizontal">
+
+    <ImageView
+        android:id="@+id/width"
+        android:layout_width="48dp"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_width"
+        android:clickable="true"
+        android:tint="?android:attr/textColorPrimary" />
+
+    <View
+        android:layout_width="1dp"
+        android:layout_height="match_parent"
+        android:background="?android:attr/listDivider" />
+
+    <ImageView
+        android:id="@+id/close"
+        android:layout_width="48dp"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_close"
+        android:clickable="true"
+        android:tint="?android:attr/textColorPrimary" />
+
+    <View
+        android:layout_width="1dp"
+        android:layout_height="match_parent"
+        android:background="?android:attr/listDivider" />
+
+    <ImageView
+        android:id="@+id/drag"
+        android:layout_width="48dp"
+        android:layout_height="wrap_content"
+        android:src="@drawable/ic_drag_handle"
+        android:clickable="true"
+        android:tint="?android:attr/textColorPrimary" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/nav_width_view.xml b/packages/SystemUI/res/layout/nav_width_view.xml
new file mode 100644
index 0000000..6a72faf
--- /dev/null
+++ b/packages/SystemUI/res/layout/nav_width_view.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<SeekBar
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/seekbar"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:paddingTop="12dp"
+    android:paddingBottom="4dp" />
diff --git a/packages/SystemUI/res/layout/preference_matrix.xml b/packages/SystemUI/res/layout/preference_matrix.xml
index ebf486f..1f6066e 100644
--- a/packages/SystemUI/res/layout/preference_matrix.xml
+++ b/packages/SystemUI/res/layout/preference_matrix.xml
@@ -19,82 +19,86 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="horizontal">
-    <Space
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1" />
-    <GridLayout
-        android:id="@+id/edit_group"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:rowCount="5"
-        android:columnCount="5">
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    android:orientation="vertical">
 
-        <Space android:layout_width="40dp" />
+    <LinearLayout
+        android:id="@+id/r_group"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp"
+        android:orientation="horizontal">
 
         <TextView
-            android:layout_width="40dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:text="@string/color_modification_r"
             android:gravity="center"
             android:textAppearance="?android:attr/textAppearanceMedium" />
 
+        <SeekBar android:id="@*android:id/seekbar"
+            android:layout_marginStart="16dp"
+            android:layout_gravity="center_vertical"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/g_group"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp"
+        android:orientation="horizontal">
+
         <TextView
-            android:layout_width="40dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:text="@string/color_modification_g"
             android:gravity="center"
             android:textAppearance="?android:attr/textAppearanceMedium" />
 
+        <SeekBar android:id="@*android:id/seekbar"
+            android:layout_marginStart="16dp"
+            android:layout_gravity="center_vertical"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/b_group"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp"
+        android:orientation="horizontal">
+
         <TextView
-            android:layout_width="40dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:text="@string/color_modification_b"
             android:gravity="center"
             android:textAppearance="?android:attr/textAppearanceMedium" />
 
-        <Space android:layout_width="40dp" />
+        <SeekBar android:id="@*android:id/seekbar"
+            android:layout_marginStart="16dp"
+            android:layout_gravity="center_vertical"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1" />
+    </LinearLayout>
 
-        <TextView
-            android:layout_width="40dp"
-            android:text="@string/color_modification_r"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-
-        <TextView
-            android:layout_width="40dp"
-            android:text="@string/color_modification_g"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-
-        <TextView
-            android:layout_width="40dp"
-            android:text="@string/color_modification_b"
-            android:gravity="center"
-            android:textAppearance="?android:attr/textAppearanceMedium" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-
-        <Space android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-        <EditText android:inputType="numberDecimal" android:layout_width="40dp" />
-
-    </GridLayout>
     <Button
         android:id="@+id/apply"
-        android:layout_width="0dp"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_gravity="bottom"
+        android:layout_gravity="end"
         android:text="@string/color_apply" />
+
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 16ff14c..186aaf6 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -17,14 +17,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-    <!-- Status Bar Scrim View -->
-    <ImageView
-        android:id="@+id/status_bar_scrim"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal|top"
-        android:scaleType="fitXY"
-        android:src="@drawable/recents_status_gradient" />
 
     <!-- Recents View -->
     <com.android.systemui.recents.views.RecentsView
@@ -33,12 +25,6 @@
         android:layout_height="match_parent">
     </com.android.systemui.recents.views.RecentsView>
 
-    <!-- History View -->
-    <ViewStub android:id="@+id/history_view_stub"
-           android:layout="@layout/recents_history"
-           android:layout_width="match_parent"
-           android:layout_height="match_parent" />
-
     <!-- Nav Bar Scrim View -->
     <ImageView
         android:id="@+id/nav_bar_scrim"
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 4b68e77..b2c0331 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -24,5 +24,4 @@
     android:textColor="#ffffffff"
     android:text="@string/recents_empty_message"
     android:fontFamily="sans-serif"
-    android:background="#80000000"
     android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_history.xml b/packages/SystemUI/res/layout/recents_history.xml
index b65a5c5..dc2da72 100644
--- a/packages/SystemUI/res/layout/recents_history.xml
+++ b/packages/SystemUI/res/layout/recents_history.xml
@@ -17,7 +17,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="#99000000"
     android:orientation="vertical">
     <android.support.v7.widget.RecyclerView
         android:id="@+id/list"
diff --git a/packages/SystemUI/res/layout/recents_history_button.xml b/packages/SystemUI/res/layout/recents_history_button.xml
index 8c96fc6..538bad1 100644
--- a/packages/SystemUI/res/layout/recents_history_button.xml
+++ b/packages/SystemUI/res/layout/recents_history_button.xml
@@ -15,15 +15,24 @@
 -->
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:id="@+id/button"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
     android:gravity="start|center_vertical"
-    android:text="@string/recents_show_history_button_label"
+    android:paddingStart="14dp"
+    android:paddingEnd="14dp"
+    android:paddingTop="12dp"
+    android:paddingBottom="12dp"
+    android:text="@string/recents_history_button_label"
     android:textSize="14sp"
     android:textColor="#FFFFFF"
     android:textAllCaps="true"
+    android:drawableStart="@drawable/ic_history"
+    android:drawablePadding="6dp"
     android:shadowColor="#99000000"
     android:shadowDx="0"
     android:shadowDy="2"
     android:shadowRadius="5"
-    android:fontFamily="sans-serif-medium" />
\ No newline at end of file
+    android:fontFamily="sans-serif-medium"
+    android:background="?android:selectableItemBackground"
+    android:visibility="invisible" />
diff --git a/packages/SystemUI/res/layout/recents_history_clear_all_button.xml b/packages/SystemUI/res/layout/recents_history_clear_all_button.xml
new file mode 100644
index 0000000..05f0979
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_history_clear_all_button.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/button"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:gravity="start|center_vertical"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
+    android:paddingTop="14dp"
+    android:paddingBottom="14dp"
+    android:drawableStart="@drawable/recents_dismiss_all_history"
+    android:contentDescription="@string/recents_history_clear_all_button_label"
+    android:textSize="14sp"
+    android:textColor="#FFFFFF"
+    android:textAllCaps="true"
+    android:shadowColor="#99000000"
+    android:shadowDx="0"
+    android:shadowDy="2"
+    android:shadowRadius="5"
+    android:fontFamily="sans-serif-medium"
+    android:background="?android:selectableItemBackground"
+    android:visibility="invisible" />
diff --git a/packages/SystemUI/res/layout/recents_history_date.xml b/packages/SystemUI/res/layout/recents_history_date.xml
index 6d6a9ee..13c7dbe 100644
--- a/packages/SystemUI/res/layout/recents_history_date.xml
+++ b/packages/SystemUI/res/layout/recents_history_date.xml
@@ -15,10 +15,12 @@
 -->
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:theme="@android:style/Theme.Material"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="12dp"
+    android:paddingStart="4dp"
+    android:paddingEnd="4dp"
+    android:paddingTop="12dp"
+    android:paddingBottom="12dp"
     android:gravity="start"
     android:textSize="14sp"
     android:textColor="#009688"
diff --git a/packages/SystemUI/res/layout/recents_history_task.xml b/packages/SystemUI/res/layout/recents_history_task.xml
index ae11006..e92c24a 100644
--- a/packages/SystemUI/res/layout/recents_history_task.xml
+++ b/packages/SystemUI/res/layout/recents_history_task.xml
@@ -15,7 +15,6 @@
 -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:theme="@android:style/Theme.Material"
     android:layout_width="match_parent"
     android:layout_height="48dp"
     android:orientation="horizontal"
@@ -27,7 +26,8 @@
         android:layout_width="32dp"
         android:layout_height="32dp"
         android:layout_gravity="center"
-        android:layout_marginStart="16dp" />
+        android:layout_marginStart="4dp"
+        android:layout_marginEnd="12dp" />
     <TextView
         android:id="@+id/description"
         android:layout_width="0dp"
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
new file mode 100644
index 0000000..b4543bd
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.systemui.recents.tv.views.RecentsTvView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/recents_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:clipChildren="false"
+    android:clipToPadding="false" >
+
+    <com.android.systemui.recents.tv.views.TaskStackHorizontalGridView
+        android:id="@+id/task_list"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:descendantFocusability="beforeDescendants"
+        android:gravity="center"
+        android:paddingStart="@dimen/recents_tv_grid_row_padding"
+        android:paddingEnd="@dimen/recents_tv_grid_row_padding"
+        android:focusable="true"/>
+
+</com.android.systemui.recents.tv.views.RecentsTvView>
+
diff --git a/packages/SystemUI/res/layout/recents_task_card_view.xml b/packages/SystemUI/res/layout/recents_task_card_view.xml
new file mode 100644
index 0000000..fa1daad
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_card_view.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.systemui.recents.tv.views.TaskCardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:focusable="true"
+    android:focusableInTouchMode="true"
+    android:layout_gravity="center"
+    android:layout_centerInParent="true">
+
+    <RelativeLayout
+            android:layout_width="@dimen/recents_tv_card_width"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:layout_gravity="center">
+        <ImageView
+                android:id="@+id/card_view_thumbnail"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/recents_tv_card_height"
+                android:scaleType="centerCrop"
+                android:gravity="center"
+                android:layout_alignParentTop="true"
+                android:layout_centerHorizontal="true"/>
+
+        <RelativeLayout
+                android:id="@+id/card_info_field"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/card_view_thumbnail"
+                android:background="@color/recents_tv_card_background_color" >
+            <TextView
+                    android:id="@+id/card_title_text"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentTop="false"
+                    android:includeFontPadding="true"
+                    android:minLines="1"
+                    android:maxLines="2"
+                    android:textColor="@color/recents_tv_card_title_text_color"
+                    android:ellipsize="end" />
+            <TextView
+                    android:id="@+id/card_content_text"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentStart="true"
+                    android:layout_below="@id/card_title_text"
+                    android:includeFontPadding="true"
+                    android:minLines="1"
+                    android:maxLines="2"
+                    android:textColor="@color/recents_tv_card_content_text_color"
+                    android:ellipsize="end" />
+            <ImageView
+                    android:id="@+id/card_extra_badge"
+                    android:layout_width="@dimen/recents_tv_card_extra_badge_size"
+                    android:layout_height="@dimen/recents_tv_card_extra_badge_size"
+                    android:scaleType="fitCenter"
+                    android:background="@android:color/transparent"
+                    android:contentDescription="@null"
+                    android:layout_centerVertical="true"
+                    android:layout_alignParentRight="true"/>
+        </RelativeLayout>
+    </RelativeLayout>
+</com.android.systemui.recents.tv.views.TaskCardView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/switch_bar.xml b/packages/SystemUI/res/layout/switch_bar.xml
new file mode 100644
index 0000000..f98de96
--- /dev/null
+++ b/packages/SystemUI/res/layout/switch_bar.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/switch_bar"
+    android:layout_width="match_parent"
+    android:layout_height="?android:attr/actionBarSize"
+    android:background="@drawable/switchbar_background"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
+    android:clickable="true"
+    android:gravity="center">
+
+    <TextView android:id="@+id/switch_text"
+        android:layout_height="wrap_content"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_gravity="center_vertical"
+        android:paddingStart="48dp"
+        android:maxLines="2"
+        android:ellipsize="end"
+        android:textAppearance="@android:style/TextAppearance.Material.Title"
+        android:textColor="?android:attr/textColorPrimaryInverse"
+        android:textAlignment="viewStart"
+        android:text="@string/switch_bar_on" />
+
+    <Switch
+        android:id="@android:id/switch_widget"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:background="@null"
+        android:theme="@style/ThemeOverlay.SwitchBar" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 2eaf988..f1000ff 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Oorfone is gekoppel"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kopstuk is gekoppel"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktiveer of deaktiveer ikone om op die statusbalk gewys te word."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index cedc061..fa8dc9d 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"የጆር ማዳመጫዎች ተገናኝተዋል"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"የጆሮ ማዳመጫ ተገናኝቷል"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"አዶዎች በሁኔታ አሞሌ ላይ እንዲታዩ ወይም እንዳይታዩ ያንቁ ወይም ያሰናክሉ።"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b0c0719..10853bf 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -497,4 +497,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"تم توصيل سماعات رأس"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"تم توصيل سماعات رأس"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"يمكنك تمكين أو تعطيل الرموز بحيث لا تظهر في شريط الحالة."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index b3aefb8..00b78b2 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Qulaqlıq qoşulub"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Qulaqlıq qoşulub"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"İkonaların status panelində görünməsini aktiv və ya deaktiv edin."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index a4130da..4b3f157 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -494,4 +494,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalice su povezane"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Naglavne slušalice su povezane"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogućite ili onemogućite prikazivanje ikona na statusnoj traci."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6dd2fb4..a5fdd8e 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалките (без микрофон) са свързани"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Слушалките са свързани"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Активиране или деактивиране на показването на икони в лентата на състоянието."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index a836903..d6f5868 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"হেডফোনগুলি সংযুক্ত হয়েছে"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"হেডসেট সংযুক্ত হয়েছে"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"স্থিতি দন্ডে দেখানোর জন্য আইকনগুলিকে সক্ষম বা অক্ষম করুন৷"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings_car.xml b/packages/SystemUI/res/values-bs-rBA/strings_car.xml
index 1e95a03..744eea8 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings_car.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Vozite sigurno"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Uvijek budite upoznati s uslovima za vožnju i poštujte važeće zakone. Upute za kretanje mogu biti netačne, nepotpune, opasne, neprikladne, zabranjene ili takve da obuhvataju suprotstavljene administrativne oblasti. Poslovne informacije mogu biti netačne ili nepotpune. Podaci nisu u realnom vremenu, a tačnost lokacije se ne može garantirati. U vožnji nemojte rukovati mobilnim uređajm ili koristiti aplikacije koje nisu namijenjene za Android Auto."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Uvijek budite upoznati s uslovima za vožnju i poštujte važeće zakone. Upute za kretanje mogu biti netačne, nepotpune, opasne, neprikladne, zabranjene ili takve da obuhvataju prelaženje preko administrativnih područja. Poslovne informacije takođe mogu biti netačne ili nepotpune. Podaci nisu u realnom vremenu, a tačnost lokacije se ne može garantirati. U vožnji nemojte rukovati mobilnim uređajem ili koristiti aplikacije koje nisu namijenjene za Android Auto."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 51084e5..714b750 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -490,7 +490,13 @@
     <string name="battery" msgid="7498329822413202973">"Bateria"</string>
     <string name="clock" msgid="7416090374234785905">"Rellotge"</string>
     <string name="headset" msgid="4534219457597457353">"Auriculars"</string>
-    <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auricular connectat"</string>
+    <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculars connectats"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculars connectats"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activa o desactiva les icones a la barra d\'estat."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings_car.xml b/packages/SystemUI/res/values-ca/strings_car.xml
index c5c4086..efcac23 100644
--- a/packages/SystemUI/res/values-ca/strings_car.xml
+++ b/packages/SystemUI/res/values-ca/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Condueix amb precaució"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Estigues al cas de la conducció i respecta sempre les normes de trànsit. Les indicacions poden ser inexactes, perilloses, inadequades o estar incompletes, o bé poden comportar maniobres prohibides o que creuis circumscripcions territorials. La informació de les empreses també pot ser inexacta o estar incompleta. No s\'ofereixen dades en temps real i no es pot garantir la precisió de les ubicacions. Mentre condueixes, no utilitzis el dispositiu mòbil ni cap aplicació que no estigui destinada a Android Auto."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Estigues al cas de la conducció i respecta sempre les lleis aplicables. Les indicacions poden ser inexactes, perilloses, inadequades o incompletes, o bé poden comportar maniobres prohibides o que creuis circumscripcions territorials. La informació de les empreses també pot ser inexacta o incompleta. No s\'ofereixen dades en temps real i no es pot garantir la precisió de les ubicacions. Mentre condueixes, no utilitzis el dispositiu mòbil ni cap aplicació que no estigui destinada a Android Auto."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 491ec92..dcd42e0 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Sluchátka připojena"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Náhlavní souprava připojena"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Umožňuje aktivovat nebo deaktivovat zobrazení ikon na stavovém řádku."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 932df2e..835ce69 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hovedtelefoner er tilsluttet"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset er forbundet"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Slå visning af ikoner i statusbjælken til eller fra."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index fcac6c8..4888c23 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Mit Kopfhörer verbunden"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mit Headset verbunden"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Symbole in der Statusleiste ein- bzw. ausblenden"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 41c6cf3..882e5fa 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Τα ακουστικά συνδέθηκαν"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Τα ακουστικά συνδέθηκαν"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ενεργοποίηση ή απενεργοποίηση εμφάνιση εικονιδίων στη γραμμή κατάστασης."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index a6e0a91..6ded945 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a6e0a91..6ded945 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a6e0a91..6ded945 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphones connected"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset connected"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Enable or disable icons from being shown in the status bar."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 8a1da56..0cdb4c6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculares conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculares conectados"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Habilitar o inhabilitar la visualización de los íconos en la barra de estado"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 2926675..cd5c95a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auriculares conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auriculares conectados"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Permite mostrar u ocultar iconos en la barra de estado"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 025d59c..52fc39e 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kõrvaklapid on ühendatud"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Peakomplekt on ühendatud"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Lubatakse või keelatakse ikoonide kuvamine olekuribal."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index dc49fd1..06a43f6 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Aurikularrak konektatu dira"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mikrofonodun entzungailua konektatu da"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Gaitu edo desgaitu ikonoak egoera-barran erakusteko aukera."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 84d0e97..0af19ba 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"هدفون وصل شد"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"هدست وصل شد"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"فعال یا غیرفعال کردن نمایش نمادها در نوار وضعیت."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 35759ed..327e1df 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kuulokkeet liitetty"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kuulokemikrofoni liitetty"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ota tilapalkin kuvakkeet käyttöön tai poista ne käytöstä."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 87e88d2..7ebb5ab 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Écouteurs connectés"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Écouteurs connectés"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activer ou désactiver l\'affichage des icônes dans la barre d\'état"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 99e9d4f..d16f680 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Casque connecté"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Casque connecté"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activer ou désactiver l\'affichage des icônes dans la barre d\'état"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings_car.xml b/packages/SystemUI/res/values-fr/strings_car.xml
index 3d261d9..d42586e 100644
--- a/packages/SystemUI/res/values-fr/strings_car.xml
+++ b/packages/SystemUI/res/values-fr/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Soyez prudent sur la route"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Tenez compte des conditions de conduite et respectez toujours les lois en vigueur. Les itinéraires peuvent être incorrects, incomplets, dangereux, inappropriés ou interdits, et traverser des zones administratives. Les informations sur les établissements peuvent également être incorrectes ou incomplètes. Les données ne sont pas fournies en temps réel, et la précision de la localisation n\'est pas garantie. Ne manipulez pas votre appareil mobile et n\'utilisez pas d\'applications non conçues pour Android Auto lorsque vous conduisez."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Tenez compte des conditions de conduite et respectez toujours les lois en vigueur. Les itinéraires peuvent être incorrects, incomplets, dangereux, inappropriés ou interdits, et traverser des frontières administratives. Les informations sur les établissements peuvent également être incorrectes ou incomplètes. Les données ne sont pas fournies en temps réel, et la précision de la localisation n\'est pas garantie. Ne manipulez pas votre appareil mobile et n\'utilisez pas d\'applications non conçues pour Android Auto lorsque vous conduisez."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index b27b56c..fad6b43 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Conectáronse os auriculares"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Conectáronse os auriculares"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activa ou desactiva a visualización das iconas na barra de estado."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings_car.xml b/packages/SystemUI/res/values-gl-rES/strings_car.xml
index 043f5d8..bb3f8eb 100644
--- a/packages/SystemUI/res/values-gl-rES/strings_car.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Conduce de forma segura"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Ten moi en conta as condicións de condución e respecta sempre as leis aplicables. É posible que as indicacións sexan imprecisas, incompletas, perigosas, inadecuadas, estean prohibidas ou que impliquen atravesar áreas administrativas. A información de empresa tamén pode ser imprecisa ou estar incompleta. Os datos non se proporcionan en tempo real e non se garante a precisión da localización. Non manipules o teu dispositivo móbil nin utilices aplicacións que non estean deseñadas para Android Auto mentres conduces."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Ten moi en conta as condicións de condución e respecta sempre as leis aplicables. É posible que as indicacións sexan imprecisas, incompletas, perigosas, inadecuadas, estean prohibidas ou que impliquen atravesar áreas administrativas. A información das empresas tamén pode ser imprecisa ou estar incompleta. Os datos non se proporcionan en tempo real e non se garante a precisión da localización. Non manipules o teu dispositivo móbil nin utilices aplicacións que non estean deseñadas para Android Auto mentres conduces."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 6b317bc..576c332 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"હેડફોન કનેક્ટ કર્યાં"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"હેડસેટ કનેક્ટ કર્યો"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"સ્થિતિ બારમાં બતાવવામાં આવતા આઇકન્સને સક્ષમ અથવા અક્ષમ કરો."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index d208221..5d97aa6 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफ़ोन कनेक्‍ट किए गए"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हैडसेट कनेक्‍ट किया गया"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"आइकन को स्‍थिति बार में दिखाए जाने से सक्षम या अक्षम करें."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index fbc8094..d96c308 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -494,4 +494,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalice su povezane"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Slušalice su povezane"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogućuje ili onemogućuje prikazivanje ikona na traci statusa."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index fedbe86..0f4c31b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fejhallgató csatlakoztatva"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset csatlakoztatva"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ikonok megjelenítése és elrejtése az állapotsoron."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 57bd4b0..d135933 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Ականջակալը կապակցված է"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ականջակալը կապակցված է"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Միացնել կամ անջատել պատկերակների ցուցադրումը կարգավիճակի գոտում:"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ae60ed6..6335c5d 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Headphone terhubung"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset terhubung"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktifkan atau nonaktifkan ikon yang ditampilkan di bilah status."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 0d2518e..76f5389 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Heyrnartól tengd"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Höfuðtól tengt"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Birtu eða feldu myndtákn í stöðustikunni."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6ca9693..cfcd42c 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Cuffie collegate"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auricolare collegato"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Consente di attivare o disattivare la visualizzazione delle icone nella barra di stato."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 1fd5248..6fd3456 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"אוזניות מחוברות"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"אוזניות מחוברות"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"הפעלה או השבתה של סמלים המוצגים בשורת הסטטוס."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b6a1386..189fcd9 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ヘッドホンを接続しました"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ヘッドセットを接続しました"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ステータスバーでのアイコンの表示を有効または無効にします。"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index bf4586ee..07390f5 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ყურსასმენები დაკავშირებულია"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ყურსაცვამი დაკავშირებულია"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"სტატუსის ზოლში ხატულების ჩვენების ჩართვა ან გათიშვა."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 41ac331..02e773c 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Құлақаспап қосылды"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Құлақаспап жинағы қосылды"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Белгішелердің күй жолағында көрсетілуін қосу немесе өшіру"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 3fce8fa..513a5b8 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"បានភ្ជាប់កាស"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"បានភ្ជាប់កាស"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"បើក ឬបិទដំណើរការបង្ហាញរូបតំណាងនៅលើរបារស្ថានភាព"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 9c48579..a64fe5a 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ಹೆಡ್‌ಫೋನ್ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ಹೆಡ್‌ಸೆಟ್ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಐಕಾನ್‌ಗಳು ತೋರಿಸುವುದನ್ನು ಸಕ್ರಿಯ ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f22e903..30a9422 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"헤드폰 연결됨"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"헤드셋 연결됨"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"아이콘이 상태 표시줄에 표시되도록 사용 설정 또는 중지합니다."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 2718417..873cf37 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Гарнитуралар туташкан"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнитура туташты"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Абал тилкесиндеги сүрөтчөнү иштетүү же өчүрүү."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings_car.xml b/packages/SystemUI/res/values-ky-rKG/strings_car.xml
index 730f53d..1d99ff2 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings_car.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings_car.xml
@@ -19,6 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Коопсуз айдаңыз"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Унаа айдоо шарттарына толук көңүл буруп, бардык колдонулган эрежелерди аткарыңыз. Багыттар так эмес, толук эмес, коркунучтуу, ылайыксыз болушу же административдик аймактарды кесип өтүшү мүмкүн. Ишкердик тууралуу маалымат да так эмес же толук эмес болушу мүмкүн. Дайындар анык убакта эмес жана жайгашкан жердин тактыгына кепилдик жок. Унаа айдоо учурунда мобилдик түзмөгүңүздү же Android Auto үчүн дайындалбаган колдонмолорду пайдаланбаңыз."</string>
+    <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Коопсуздук эрежелерин сактаңыз"</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Унаа айдап бара жатканда жолдогу шарттар менен эрежелерге ар дайым көңүл буруңуз. Багыттар так же толук эмес берилип, кесип өтүү үчүн опурталдуу же ылайыксыз болгон административдик аймактар аркылуу өтүшү мүмкүн. Ишканалар тууралуу маалымат да так же толук эмес болушу мүмкүн. Дайындар тез-тез жаңыртылып турбагандыктан, жайгашкан жердин так аныкталгандыгына кепилдик жок. Андыктан унаа айдап бара жатканда, мобилдик түзмөгүңүздү же Android Auto\'го арналбаган колдонмолорду пайдаланбаңыз."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 9f075d0..7a85446 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ເຊື່ອມຕໍ່ຊຸດຫູຟັງແລ້ວ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ເຊື່ອມ​ຕໍ່ຊຸດ​ຫູ​ຟັງແລ້ວ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ເປີດ ຫຼື ປິດໄອຄອນຕ່າງໆຈາກການສະແດງໃນແຖບສະຖານະ."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 69e7832..c9a5959 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Ausinės prijungtos"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ausinės prijungtos"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Įgalinti arba išjungti piktogramų rodymą būsenos juostoje."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 2ef7865..5e115a8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -494,4 +494,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Austiņas ir pievienotas"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Austiņas ar mikrofonu ir pievienotas"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Iespējojiet vai atspējojiet ikonu rādīšanu statusa joslā."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index aa8019e..348d679 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалките се поврзани"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Слушалките се поврзани"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Овозможете или оневозможете прикажување на иконите во статусната лента."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index d22a7f9..a393e42 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ഹെഡ്ഫോണുകൾ കണക്റ്റുചെയ്തു"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ഹെഡ്‌സെറ്റ് കണക്‌റ്റുചെയ്‌തു"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"സ്റ്റാറ്റസ് ബാറിൽ കാണിക്കുന്നതിൽ നിന്ന് ഐക്കണുകളെ പ്രവർത്തനക്ഷമമാക്കുകയോ പ്രവർത്തനരഹിതമാക്കുകയോ ചെയ്യുക"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 1bd8d98..9b45994 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -491,4 +491,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Чихэвч холбогдсон"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Чихэвч холбогдсон"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Статусын самбарт харагдах дүрс тэмдгийг идэвхжүүлэх эсвэл идэвхгүй болгоно уу."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index e404c2d..9329909 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफोन कनेक्ट केले"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हेडसेट कनेक्ट केला"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"चिन्हे स्टेटस बारमध्ये दर्शविले जाण्‍यापासून प्रतिबंधित करण्‍यासाठी ती सक्षम किंवा अक्षम करा."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 2bc9c51..a4e90c0 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fon kepala disambungkan"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Set kepala disambungkan"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Dayakan atau lumpuhkan ikon daripada dipaparkan dalam bar status."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index e119686..cfcc15ab 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"နားကြပ်တပ်ဆင်ပြီးပါပြီ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"မိုက်ခွက်ပါနားကြပ်တပ်ဆင်ပြီးပါပြီ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"အခြေအနေဘားတန်းတွင် သင်္ကေတပုံပြခြင်းကို ဖွင့်ရန် သို့မဟုတ် ပိတ်ရန်"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 61da224..377642b 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Øretelefoner er tilkoblet"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Hodetelefoner er tilkoblet"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Vis eller skjul ikoner i statusfeltet."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index db638c0..2a15c87 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -492,5 +492,11 @@
     <string name="headset" msgid="4534219457597457353">"हेडसेट"</string>
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"हेडफोनहरू जडान गरियो"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"हेडसेट जडान गरियो"</string>
-    <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"वस्तुस्थिति पट्टीमा देखाउने हुनबाट आइकनहरूलाई सक्रिय वा निष्क्रिय गर्नुहोस्।"</string>
+    <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"वस्तुस्थिति पट्टीमा देखाइनको लागि आइकनहरू सक्रिय वा निष्क्रिय गर्नुहोस्।"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings_car.xml b/packages/SystemUI/res/values-ne-rNP/strings_car.xml
index 0b22d4ac..1a4f8ef9 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings_car.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"सुरक्षित तरिकाले सवारी चलाउनुहोस्"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"ड्राइभिङ सर्तहरूको पूर्ण सजग रहनुहोस् र जहिले पनि लागू हुने नियमहरूको पालना गर्नुहोस्। दिशा निर्देशनहरू अशुद्ध, अपूर्ण, खतरनाक, उपयुक्त नभएको, निषेधित वा प्रशासनिक क्षेत्र पार गरेको हुन सक्छ। व्यवसाय जानकारी अशुद्ध वा अपूर्ण पनि हुन सक्छ। डेटा वास्तविक समयको होइन र स्थान सटीकताको ग्यारेन्टी गर्न सकिँदैन। आफ्नो मोबाइल यन्त्र ह्याण्डल गर्ने वा सवारी चलाएको बेलामा Android स्वतःको लागि अभिप्रेत नभएको अनुप्रयोगहरूको प्रयोग गर्ने नगर्नुहोस्।"</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"ड्राइभिङ सर्तहरूका बारे पूर्ण सजग रहनुहोस् र जहिले पनि लागू हुने नियमहरूको पालना गर्नुहोस्। दिशा निर्देशनहरू अशुद्ध, अपूर्ण, खतरनाक, अनुपयुक्त, निषेधित वा प्रशासनिक क्षेत्र पार गर्ने हुन सक्छ। व्यवसायिक जानकारी अशुद्ध वा अपूर्ण पनि हुन सक्छ। डेटा वास्तविक समयको हुँदैन र स्थान सटीकताको ग्यारेन्टी गर्न सकिँदैन। आफ्नो मोबाइल यन्त्र ह्याण्डल गर्ने वा सवारी चलाएको बेलामा Android स्वतःको लागि लक्षित नगरिएका अनुप्रयोगहरूको प्रयोग गर्ने नगर्नुहोस्।"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 55285d8..3e91b5c 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hoofdtelefoon aangesloten"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset aangesloten"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"De weergave van pictogrammen in de statusbalk in- of uitschakelen."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 0217781..1c98369 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ਹੈੱਡਫੋਨਾਂ ਨੂੰ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ਹੈੱਡਸੈੱਟ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"ਚਿੰਨ੍ਹਾਂ ਦੇ ਸਥਿਤੀ ਪੱਟੀ ਵਿੱਚ ਵਿਖਾਏ ਜਾਣ ਨੂੰ ਯੋਗ ਜਾਂ ਅਯੋਗ ਬਣਾਓ।"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index db685be..fde806b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Słuchawki są podłączone"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Zestaw słuchawkowy jest podłączony"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Włącz lub wyłącz wyświetlanie ikon na pasku stanu."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 56d1209..38a6b79 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fones de ouvido conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Fone de ouvido conectado"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a exibição de ícones na barra de status."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 9f9a12b..7e66dcf 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Auscultadores ligados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Auscultadores com microfone integrado ligados"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a apresentação de ícones na barra de estado."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 56d1209..38a6b79 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Fones de ouvido conectados"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Fone de ouvido conectado"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Ativar ou desativar a exibição de ícones na barra de status."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 796c261..e045fc8 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -56,7 +56,7 @@
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permiteți aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze accesoriul USB?"</string>
     <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Deschideţi <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui dispozitiv USB?"</string>
     <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Deschideţi <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui accesoriu USB?"</string>
-    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aplic. instal. nu funcţ. cu acest acces. USB. Aflaţi despre acest accesoriu la <xliff:g id="URL">%1$s</xliff:g>"</string>
+    <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aplic. instal. nu funcţ. cu acest acces. USB. Aflați despre acest accesoriu la <xliff:g id="URL">%1$s</xliff:g>"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"Accesoriu USB"</string>
     <string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
     <string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
@@ -494,4 +494,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Căștile sunt conectate"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Setul căști-microfon este conectat"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Activați sau dezactivați afișarea pictogramelor în bara de stare."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index bd16a82..d9f7a9b 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Наушники подключены"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнитура подключена"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Включение и отключение показа значков в строке состояния"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index ddd95b4..69514d4 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"හෙඩ්ෆෝන් සම්බන්ධ කළ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"හෙඩ්සෙට් සම්බන්ධ කළ"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"තත්ත්ව තීරුව මත අයිකන පෙන්වීම සබල හෝ අබල කරන්න."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index b149fcb..9ef3d47 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slúchadlá pripojené"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Náhlavná súprava pripojená"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Umožňuje aktivovať alebo deaktivovať zobrazenie ikon v stavovom riadku."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index bf6078e..9fda17b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Slušalke priključene"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Slušalke z mikrofonom priključene"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Omogoči ali onemogoči prikaz ikon v vrstici stanja."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 0014b33..a43ac7e 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Kufjet u lidhën"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Kufjet me mikrofon u lidhën"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Aktivizo ose çaktivizo shfaqjen e ikonave në shiritin e statusit."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 15b01dc..765df27 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -494,4 +494,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Слушалице су повезане"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Наглавне слушалице су повезане"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Омогућите или онемогућите приказивање икона на статусној траци."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d786e64..c76d1d3 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Hörlurar anslutna"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Headset anslutet"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Visa eller dölj ikoner i statusfältet."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index b2d8362..031e2b1 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Imeunganisha spika za masikioni"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Imeunganisha vifaa vya sauti"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Washa au uzime aikoni ili zisionekane kwenye sehemu ya arifa"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index aa1da9a..b64ef74 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -485,12 +485,18 @@
     <string name="tuner_full_zen_title" msgid="5905081395132280054">"ஒலி உரையாடலில் தொந்தரவு செய்ய வேண்டாம் என்பதைக் காட்டு"</string>
     <string name="tuner_full_zen_summary" msgid="6883568374520596402">"ஒலி உரையாடலில் தொந்தரவு செய்ய வேண்டாம் என்பதன் முழுக் கட்டுப்பாட்டையும் அனுமதி."</string>
     <string name="volume_and_do_not_disturb" msgid="3114580364524650941">"ஒலி மற்றும் தொந்தரவு செய்ய வேண்டாம்"</string>
-    <string name="volume_down_silent" msgid="66962568467719591">"ஒலி குறைக்கும் போது தொந்தரவு செய்ய வேண்டாம் என்பதை இயக்கு"</string>
-    <string name="volume_up_silent" msgid="7141255269783588286">"ஒலி அதிகரிக்கும் போது தொந்தரவு செய்ய வேண்டாம் என்பதை முடக்கு"</string>
+    <string name="volume_down_silent" msgid="66962568467719591">"ஒலியைக் குறைக்கும் போது தொந்தரவு செய்ய வேண்டாம் என்பதை இயக்கு"</string>
+    <string name="volume_up_silent" msgid="7141255269783588286">"ஒலியைக் கூட்டும் போது தொந்தரவு செய்ய வேண்டாம் என்பதை முடக்கு"</string>
     <string name="battery" msgid="7498329822413202973">"பேட்டரி"</string>
     <string name="clock" msgid="7416090374234785905">"கடிகாரம்"</string>
     <string name="headset" msgid="4534219457597457353">"ஹெட்செட்"</string>
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ஹெட்ஃபோன்கள் இணைக்கப்பட்டன"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ஹெட்செட் இணைக்கப்பட்டது"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"நிலைப் பட்டியில் ஐகான்களைக் காட்டுவதை இயக்கும் அல்லது முடக்கும்."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index eb3feac..1e953d8 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"హెడ్‌ఫోన్‌లు కనెక్ట్ చేయబడ్డాయి"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"హెడ్‌సెట్ కనెక్ట్ చేయబడింది"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"స్థితి పట్టీలో చిహ్నాలు ప్రదర్శించడాన్ని ప్రారంభించండి లేదా నిలిపివేయండి."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index fba1efc..c09b50f 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"เชื่อมต่อหูฟังแล้ว"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"เชื่อมต่อชุดหูฟังแล้ว"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"เปิดหรือปิดไอคอนจากการแสดงในแถบสถานะ"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 082cc28..e76b40c 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Nakakonekta ang mga headphone"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Nakakonekta ang headset"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"I-enable o i-disable ang pagpapakita sa mga icon sa status bar."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 62639d0..a16adfd 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Mikrofonlu kulaklık bağlı"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Mikrofonlu kulaklık bağlı"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Simgelerin durum çubuğunda görüntülenmesini etkinleştir veya devre dışı bırak"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d9c9b7f..1c0e04e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -495,4 +495,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Навушники під’єднано"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Гарнітуру під’єднано"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Показати або сховати значки в рядку стану."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 5bf8210..67b52fd 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ہیڈ فونز منسلک ہیں"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ہیڈ سیٹ منسلک ہے"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"اسٹیٹس بار میں دکھائے جانے کیلئے آئیکنز فعال یا غیر فعال کریں۔"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 1c642b0..dd91bad 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Quloqchinlar ulandi"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Audio moslama ulandi"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Holat qatorida begilarning ko‘rsatilishini yoqish yoki o‘chirish."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 55154ac..a95e312 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Đã kết nối tai nghe"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Đã kết nối tai nghe"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Bật hoặc tắt biểu tượng hiển thị trong thanh trạng thái."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 8bbd41c..e276fb5 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已连接到耳机"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已连接到耳机"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"指定在状态栏中显示或隐藏图标。"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 1ec4205..86f78e4 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已連接至耳機"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已連接至耳機"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"顯示或隱藏狀態列上的圖示。"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ab0a713..00eb788 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已與耳機連線"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已與耳機連線"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"指定在狀態列中顯示或隱藏圖示。"</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 2820a2e..08dc7cc 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -493,4 +493,10 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Amahedfoni axhunyiwe"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Ama-earphone axhunyiwe"</string>
     <string name="tuner_status_bar_explanation" msgid="9032196769944137864">"Nika amandla noma khubaza izithonjana kusukela ekubonisweni kubha yesimo."</string>
+    <!-- no translation found for data_saver (5037565123367048522) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_on (8454111686783887148) -->
+    <skip />
+    <!-- no translation found for accessibility_data_saver_off (8841582529453005337) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 955efb5..19bc755 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -28,9 +28,6 @@
     <declare-styleable name="NotificationLinearLayout">
         <attr name="insetLeft" format="dimension" />
     </declare-styleable>
-    <declare-styleable name="NotificationRowLayout">
-        <attr name="rowHeight" format="dimension" />
-    </declare-styleable>
     <declare-styleable name="RecentsPanelView">
         <attr name="recentItemLayout" format="reference" />
     </declare-styleable>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 5e25d2c..9bb6dc6 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -151,4 +151,12 @@
     <color name="qs_tile_tint_unavailable">#40ffffff</color>
     <color name="qs_tile_tint_inactive">#4dffffff</color>
     <color name="qs_tile_tint_active">#ffffffff</color>
+
+    <color name="switch_bar_background">#ff37474f</color>
+    <color name="switch_accent_color">#ff7fcac3</color>
+
+    <!-- Keyboard shortcuts colors -->
+    <color name="ksh_system_group_color">#ff00bcd4</color>
+    <color name="ksh_application_group_color">#fff44336</color>
+    <color name="ksh_dialog_background_color">#ffffffff</color>
 </resources>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
new file mode 100644
index 0000000..6f4c983
--- /dev/null
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+    <color name="recents_tv_card_background_color">#FF37474F</color>
+    <color name="recents_tv_card_title_text_color">#FFEEEEEE</color>
+    <color name="recents_tv_card_content_text_color">#99EEEEEE</color>
+    <color name="recents_tv_card_source_text_color">#99EEEEEE</color>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e245c24..32d09e8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -137,6 +137,8 @@
     <dimen name="standard_notification_panel_width">416dp</dimen>
     <dimen name="notification_panel_width">@dimen/match_parent</dimen>
 
+    <dimen name="volume_dialog_panel_width">@dimen/standard_notification_panel_width</dimen>
+
     <!-- Gravity for the notification panel -->
     <integer name="standard_notification_panel_layout_gravity">0x31</integer><!-- top|center_horizontal -->
     <integer name="notification_panel_layout_gravity">0x37</integer><!-- fill_horizontal|top -->
@@ -604,5 +606,4 @@
 
     <dimen name="docked_divider_handle_width">16dp</dimen>
     <dimen name="docked_divider_handle_height">2dp</dimen>
-
 </resources>
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
new file mode 100644
index 0000000..77605bd
--- /dev/null
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+    <!-- Dimens for recents card in the recents view on tv -->
+    <dimen name="recents_tv_card_width">150dip</dimen>
+    <dimen name="recents_tv_card_height">85dip</dimen>
+    <dimen name="recents_tv_card_extra_badge_size">16dip</dimen>
+
+    <!-- Padding for grid view in recents view on tv -->
+    <dimen name="recents_tv_grid_row_padding">56dip</dimen>
+    <dimen name="recents_tv_gird_row_top_padding">57dip</dimen>
+    <dimen name="recents_tv_grid_max_row_height">200dip</dimen>
+    <dimen name="recents_tv_gird_card_spacing">8dip</dimen>
+
+    <!-- Values for focus animation -->
+    <dimen name="recents_tv_unselected_item_z">6dp</dimen>
+    <dimen name="recents_tv_selected_item_z_delta">10dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/integers_tv.xml b/packages/SystemUI/res/values/integers_tv.xml
new file mode 100644
index 0000000..bfd8f8b
--- /dev/null
+++ b/packages/SystemUI/res/values/integers_tv.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <integer name="item_scale_anim_duration">150</integer>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 02158ac..32da3c6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -359,6 +359,9 @@
     <!-- Content description of the data connection with no SIM for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_no_sim">No SIM.</string>
 
+    <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_cell_data_off">Cellular Data Off</string>
+
     <!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
 
@@ -712,9 +715,9 @@
     <!-- Recents: Launch error string. [CHAR LIMIT=NONE] -->
     <string name="recents_launch_error_message">Could not start <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
     <!-- Recents: Show history string. [CHAR LIMIT=NONE] -->
-    <string name="recents_show_history_button_label">More</string>
-    <!-- Recents: A format string to set the number of availabe historical tasks in recents. [CHAR LIMIT=NONE] -->
-    <string name="recents_history_label_format"><xliff:g id="number">%d</xliff:g> More</string>
+    <string name="recents_history_button_label">History</string>
+    <!-- Recents: History clear all string. [CHAR LIMIT=NONE] -->
+    <string name="recents_history_clear_all_button_label">Clear</string>
 
     <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
     <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
@@ -1248,6 +1251,9 @@
     <!-- Label for custom color transform [CHAR LIMIT=30] -->
     <string name="color_matrix_custom">Custom colors</string>
 
+    <!-- Label for auto color transforms [CHAR LIMIT=30] -->
+    <string name="color_matrix_auto">Auto</string>
+
     <!-- Label for unknown color transform [CHAR LIMIT=30] -->
     <string name="color_matrix_unknown">Unknown colors</string>
 
@@ -1337,4 +1343,61 @@
     <!-- Accessibility description for data saver being off [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_saver_off">Data Saver is off</string>
 
+    <!-- Label for feature switch [CHAR LIMIT=30] -->
+    <string name="switch_bar_on">On</string>
+
+    <!-- SysUI Tuner: Button that leads to the navigation bar customization screen [CHAR LIMIT=60] -->
+    <string name="nav_bar">Navigation bar</string>
+
+    <!-- SysUI Tuner: Group of buttons that show on the start of the screen [CHAR LIMIT=30] -->
+    <string name="start">Start</string>
+    <!-- SysUI Tuner: Group of buttons that show on the center of the screen [CHAR LIMIT=30] -->
+    <string name="center">Center</string>
+    <!-- SysUI Tuner: Group of buttons that show on the end of the screen [CHAR LIMIT=30] -->
+    <string name="end">End</string>
+    <!-- SysUI Tuner: Name of space used in custom navigation bar layouts [CHAR LIMIT=30] -->
+    <string name="space">Spacer</string>
+    <!-- SysUI Tuner: Name of Combination Menu / Keyboard Switcher button [CHAR LIMIT=30] -->
+    <string name="menu_ime">Menu / Keyboard Switcher</string>
+    <!-- SysUI Tuner: Title for dialog to add a button [CHAR LIMIT=30] -->
+    <string name="select_button">Select button to add</string>
+    <!-- SysUI Tuner: Button to add a button [CHAR LIMIT=30] -->
+    <string name="add_button">Add button</string>
+    <!-- SysUI Tuner: Save the current settings [CHAR LIMIT=30] -->
+    <string name="save">Save</string>
+    <!-- SysUI Tuner: Reset to default settings [CHAR LIMIT=30] -->
+    <string name="reset">Reset</string>
+
+    <!-- SysUI Tuner: Title of no home warning dialog [CHAR LIMIT=30] -->
+    <string name="no_home_title">No home button found</string>
+    <!-- SysUI Tuner: Message of no home warning dialog [CHAR LIMIT=NONE] -->
+    <string name="no_home_message">A home button is required to be able to navigate this device. Please add a home button before saving.</string>
+
+    <!-- SysUI Tuner: Adjust button width dialog title [CHAR LIMIT=60] -->
+    <string name="adjust_button_width">Adjust button width</string>
+
+    <!-- SysUI Tuner: Nav bar button that holds the clipboard [CHAR LIMIT=30] -->
+    <string name="clipboard">Clipboard</string>
+
+    <!-- SysUI Tuner: Description of nav bar button that holds the clipboard [CHAR LIMIT=NONE] -->
+    <string name="clipboard_description">The Clipboard allows items to be dragged directly to the clipboard. Items can also be dragged directly out of the clipboard when present.</string>
+
+    <!-- SysUI Tuner: Accessibility description for custom nav key [CHAR LIMIT=NONE] -->
+    <string name="accessibility_key">Custom navigation button</string>
+
+    <!-- SysUI Tuner: Nav bar button that emulates a keycode [CHAR LIMIT=30] -->
+    <string name="keycode">Keycode</string>
+
+    <!-- SysUI Tuner: Description of nav bar button that emulates a keycode [CHAR LIMIT=NONE] -->
+    <string name="keycode_description">Keycode buttons allow keyboard keys to
+        be added to the Navigation Bar. When pressed they emulate the selected
+        keyboard key. First the key must be selected for the button, followed
+        by an image to be shown on the button.</string>
+
+    <!-- SysUI Tuner: Title of dialog to select which key to emulate [CHAR LIMIT=60] -->
+    <string name="select_keycode">Select Keyboard Button</string>
+
+    <!-- SysUI Tuner: Label for preview area in navigation bar tuner [CHAR LIMIT=NONE] -->
+    <string name="preview">Preview</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index d432a62..c64327d 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -18,15 +18,15 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Button to close PIP on PIP UI -->
-    <string name="pip_exit">Close PIP</string>
+    <string name="pip_exit" translatable="false">Close PIP</string>
     <!-- Button to move PIP screen to the fullscreen on PIP UI -->
-    <string name="pip_fullscreen">Full screen</string>
+    <string name="pip_fullscreen" translatable="false">Full screen</string>
     <!-- Button to play the current media on PIP UI -->
-    <string name="pip_play">Play</string>
+    <string name="pip_play" translatable="false">Play</string>
     <!-- Button to pause the current media on PIP UI -->
-    <string name="pip_pause">Pause</string>
+    <string name="pip_pause" translatable="false">Pause</string>
     <!-- Button to close PIP overlay menu on PIP UI -->
-    <string name="pip_cancel">Cancel</string>
+    <string name="pip_cancel" translatable="false">Cancel</string>
     <!-- Overlay text on PIP -->
-    <string name="pip_hold_home">Hold HOME to control PIP</string>
+    <string name="pip_hold_home" translatable="false">Hold HOME to control PIP</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 4329f78..9931ab9 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -20,7 +20,7 @@
         <item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
     </style>
 
-    <style name="RecentsTheme" parent="@android:style/Theme.Material.Light">
+    <style name="RecentsTheme" parent="@android:style/Theme.Material">
         <!-- NoTitle -->
         <item name="android:windowNoTitle">true</item>
         <!-- Misc -->
@@ -310,6 +310,7 @@
     </style>
 
     <style name="TunerSettings" parent="@android:style/Theme.Material.Settings">
+        <item name="android:windowActionBar">false</item>
         <item name="preferenceTheme">@style/TunerPreferenceTheme</item>
     </style>
 
@@ -345,4 +346,8 @@
         <item name="android:textColor">@*android:color/material_deep_teal_500</item>
     </style>
 
+    <style name="ThemeOverlay.SwitchBar" parent="@android:style/ThemeOverlay">
+        <item name="android:colorAccent">@color/switch_accent_color</item>
+    </style>
+
 </resources>
diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml
new file mode 100644
index 0000000..45cdc07
--- /dev/null
+++ b/packages/SystemUI/res/values/values_tv.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <item format="float" type="raw" name="unselected_scale">1.0</item>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 67a7a23..febe518 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -166,6 +166,11 @@
 
     </PreferenceScreen>
 
+    <Preference
+        android:key="nav_bar"
+        android:title="@string/nav_bar"
+        android:fragment="com.android.systemui.tuner.NavBarTuner" />
+
     <!-- Warning, this goes last. -->
     <Preference
         android:summary="@string/tuner_persistent_warning"
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 5b955a4..6b74652 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -67,6 +67,7 @@
     private FalsingManager mFalsingManager;
 
     private float mInitialTouchPos;
+    private float mPerpendicularInitialTouchPos;
     private boolean mDragging;
     private View mCurrView;
     private View mCurrAnimView;
@@ -117,6 +118,10 @@
         return mSwipeDirection == X ? ev.getX() : ev.getY();
     }
 
+    private float getPerpendicularPos(MotionEvent ev) {
+        return mSwipeDirection == X ? ev.getY() : ev.getX();
+    }
+
     private float getTranslation(View v) {
         return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY();
     }
@@ -240,6 +245,7 @@
                     mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
                     mVelocityTracker.addMovement(ev);
                     mInitialTouchPos = getPos(ev);
+                    mPerpendicularInitialTouchPos = getPerpendicularPos(ev);
 
                     if (mLongPressListener != null) {
                         if (mWatchLongPress == null) {
@@ -271,8 +277,11 @@
                 if (mCurrView != null && !mLongPressSent) {
                     mVelocityTracker.addMovement(ev);
                     float pos = getPos(ev);
+                    float perpendicularPos = getPerpendicularPos(ev);
                     float delta = pos - mInitialTouchPos;
-                    if (Math.abs(delta) > mPagingTouchSlop) {
+                    float deltaPerpendicular = perpendicularPos - mPerpendicularInitialTouchPos;
+                    if (Math.abs(delta) > mPagingTouchSlop
+                            && Math.abs(delta) > Math.abs(deltaPerpendicular)) {
                         mCallback.onBeginDrag(mCurrView);
                         mDragging = true;
                         mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView);
@@ -280,7 +289,6 @@
                         removeLongPressCallback();
                     }
                 }
-
                 break;
 
             case MotionEvent.ACTION_UP:
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 27d4c0e..c7e5ea4 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -35,6 +35,10 @@
 public class HumanInteractionClassifier extends Classifier {
     private static final String HIC_ENABLE = "HIC_enable";
     private static final float FINGER_DISTANCE = 0.1f;
+
+    /** Default value for the HIC_ENABLE setting: 1 - enabled, 0 - disabled */
+    private static final int HIC_ENABLE_DEFAULT = 1;
+
     private static HumanInteractionClassifier sInstance = null;
 
     private final Handler mHandler = new Handler();
@@ -101,9 +105,9 @@
     }
 
     private void updateConfiguration() {
-        mEnableClassifier = Build.IS_DEBUGGABLE && 0 != Settings.Global.getInt(
+        mEnableClassifier = 0 != Settings.Global.getInt(
                 mContext.getContentResolver(),
-                HIC_ENABLE, 0);
+                HIC_ENABLE, HIC_ENABLE_DEFAULT);
     }
 
     public void setType(int type) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 0475c72..958572f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -24,7 +24,6 @@
 import android.app.SearchManager;
 import android.app.StatusBarManager;
 import android.app.trust.TrustManager;
-import android.auditing.SecurityLog;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -1371,10 +1370,8 @@
      * @see #KEYGUARD_DONE
      */
     private void handleKeyguardDone(boolean authenticated) {
-        if (SecurityLog.isLoggingEnabled()
-                && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
-            SecurityLog.writeEvent(SecurityLog.TAG_DEVICE_UNLOCK_ATTEMPT,
-                    (authenticated ? 1 : 0), "Unknown");
+        if (mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
+            mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed();
         }
         if (DEBUG) Log.d(TAG, "handleKeyguardDone");
         synchronized (this) {
@@ -1487,9 +1484,8 @@
      * @see #SHOW
      */
     private void handleShow(Bundle options) {
-        if (SecurityLog.isLoggingEnabled()
-                && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
-            SecurityLog.writeEvent(SecurityLog.TAG_DEVICE_LOCKED, "");
+        if (mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
+            mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured();
         }
         synchronized (KeyguardViewMediator.this) {
             if (!mSystemReady) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 72629a3..35000d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs;
 
+import android.app.ActivityManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -23,7 +24,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.UserHandle;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.View;
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.DisplayController;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -82,9 +83,8 @@
     /**
      * Declare the category of this tile.
      *
-     * Categories are defined in {@link com.android.internal.logging.MetricsLogger}
-     * or if there is no relevant existing category you may define one in
-     * {@link com.android.systemui.qs.QSTile}.
+     * Categories are defined in {@link com.android.internal.logging.MetricsProto.MetricsEvent}
+     * by editing frameworks/base/proto/src/metrics_constants.proto.
      */
     abstract public int getMetricsCategory();
 
@@ -271,7 +271,7 @@
 
     protected void checkIfRestrictionEnforced(State state, String userRestriction) {
         EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
-                userRestriction, UserHandle.myUserId());
+                userRestriction, ActivityManager.getCurrentUser());
         if (admin != null) {
             state.disabledByPolicy = true;
             state.enforcedAdmin = admin;
@@ -390,6 +390,7 @@
         UserInfoController getUserInfoController();
         BatteryController getBatteryController();
         TileServices getTileServices();
+        DisplayController getDisplayController();
         void removeTile(String tileSpec);
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
index ac4f05f..36bed0d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/BlankCustomTile.java
@@ -20,7 +20,9 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.graphics.drawable.Drawable;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 
@@ -84,6 +86,6 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_INTENT;
+        return MetricsEvent.QS_INTENT;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 8ae2d7b..3748a30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -72,8 +72,9 @@
             }
             mCurrentTiles = tileSpecs;
             final TileGroup group = new TileGroup("com.android.settings", mContext);
+            boolean hasColorMod = host.getDisplayController().isEnabled();
             String possible = mContext.getString(R.string.quick_settings_tiles_default)
-                    + ",hotspot,inversion,saver";
+                    + ",hotspot,inversion,saver" + (hasColorMod ? ",colors" : "");
             String[] possibleTiles = possible.split(",");
             for (int i = 0; i < possibleTiles.length; i++) {
                 final String spec = possibleTiles[i];
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index d398b64..886531a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -31,7 +31,9 @@
 import android.view.IWindowManager;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.phone.QSTileHost;
@@ -197,7 +199,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_CUSTOM;
+        return MetricsEvent.QS_CUSTOM;
     }
 
     public void startUnlockAndRun() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index c696f88..d78d6ff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -24,6 +24,7 @@
 import android.provider.Settings.Global;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSTile;
@@ -85,7 +86,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_AIRPLANEMODE;
+        return MetricsEvent.QS_AIRPLANEMODE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 60238fc3..fd8857d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -25,7 +25,7 @@
 import android.widget.Checkable;
 import android.widget.ImageView;
 import android.widget.TextView;
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.BatteryInfo;
 import com.android.systemui.BatteryMeterDrawable;
 import com.android.systemui.R;
@@ -64,7 +64,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_BATTERY_TILE;
+        return MetricsEvent.QS_BATTERY_TILE;
     }
 
     @Override
@@ -199,7 +199,7 @@
 
         @Override
         public int getMetricsCategory() {
-            return MetricsLogger.QS_BATTERY_DETAIL;
+            return MetricsEvent.QS_BATTERY_DETAIL;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 3750290..dbb7423 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -24,7 +24,9 @@
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
@@ -76,6 +78,10 @@
 
     @Override
     protected void handleClick() {
+        if (!mController.canConfigBluetooth()) {
+            mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
+            return;
+        }
         if (!mState.value) {
             mState.value = true;
             mController.setBluetoothEnabled(true);
@@ -127,7 +133,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_BLUETOOTH;
+        return MetricsEvent.QS_BLUETOOTH;
     }
 
     @Override
@@ -181,14 +187,14 @@
 
         @Override
         public void setToggleState(boolean state) {
-            MetricsLogger.action(mContext, MetricsLogger.QS_BLUETOOTH_TOGGLE, state);
+            MetricsLogger.action(mContext, MetricsEvent.QS_BLUETOOTH_TOGGLE, state);
             mController.setBluetoothEnabled(state);
             showDetail(false);
         }
 
         @Override
         public int getMetricsCategory() {
-            return MetricsLogger.QS_BLUETOOTH_DETAILS;
+            return MetricsEvent.QS_BLUETOOTH_DETAILS;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index de4c21c..18eb7a1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -23,7 +23,9 @@
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
@@ -125,7 +127,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_CAST;
+        return MetricsEvent.QS_CAST;
     }
 
     @Override
@@ -181,7 +183,7 @@
 
         @Override
         public int getMetricsCategory() {
-            return MetricsLogger.QS_CAST_DETAILS;
+            return MetricsEvent.QS_CAST_DETAILS;
         }
 
         @Override
@@ -255,7 +257,7 @@
         @Override
         public void onDetailItemClick(Item item) {
             if (item == null || item.tag == null) return;
-            MetricsLogger.action(mContext, MetricsLogger.QS_CAST_SELECT);
+            MetricsLogger.action(mContext, MetricsEvent.QS_CAST_SELECT);
             final CastDevice device = (CastDevice) item.tag;
             mController.startCasting(device);
         }
@@ -263,7 +265,7 @@
         @Override
         public void onDetailItemDisconnect(Item item) {
             if (item == null || item.tag == null) return;
-            MetricsLogger.action(mContext, MetricsLogger.QS_CAST_DISCONNECT);
+            MetricsLogger.action(mContext, MetricsEvent.QS_CAST_DISCONNECT);
             final CastDevice device = (CastDevice) item.tag;
             mController.stopCasting(device);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 1f8fae0..aacdbc9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -23,7 +23,9 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSIconView;
@@ -89,7 +91,7 @@
     protected void handleSecondaryClick() {
         boolean dataEnabled = mDataController.isMobileDataSupported()
                 && mDataController.isMobileDataEnabled();
-        MetricsLogger.action(mContext, MetricsLogger.QS_CELLULAR_TOGGLE, !dataEnabled);
+        MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, !dataEnabled);
         mDataController.setMobileDataEnabled(!dataEnabled);
     }
 
@@ -131,7 +133,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_CELLULAR;
+        return MetricsEvent.QS_CELLULAR;
     }
 
     // Remove the period from the network name
@@ -241,13 +243,13 @@
 
         @Override
         public void setToggleState(boolean state) {
-            MetricsLogger.action(mContext, MetricsLogger.QS_CELLULAR_TOGGLE, state);
+            MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, state);
             mDataController.setMobileDataEnabled(state);
         }
 
         @Override
         public int getMetricsCategory() {
-            return MetricsLogger.QS_DATAUSAGEDETAIL;
+            return MetricsEvent.QS_DATAUSAGEDETAIL;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 23a15b9..6e843e9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -17,7 +17,9 @@
 package com.android.systemui.qs.tiles;
 
 import android.provider.Settings.Secure;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.SecureSetting;
@@ -84,7 +86,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_COLORINVERSION;
+        return MetricsEvent.QS_COLORINVERSION;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 39eda6b..1f9f1c4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -30,7 +30,9 @@
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 import android.widget.Toast;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SysUIToast;
@@ -154,7 +156,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_DND;
+        return MetricsEvent.QS_DND;
     }
 
     @Override
@@ -229,7 +231,7 @@
 
         @Override
         public void setToggleState(boolean state) {
-            MetricsLogger.action(mContext, MetricsLogger.QS_DND_TOGGLE, state);
+            MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
             if (!state) {
                 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
                 showDetail(false);
@@ -238,7 +240,7 @@
 
         @Override
         public int getMetricsCategory() {
-            return MetricsLogger.QS_DND_DETAILS;
+            return MetricsEvent.QS_DND_DETAILS;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 39d9da1..1d9f15b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -17,7 +17,9 @@
 package com.android.systemui.qs.tiles;
 
 import android.app.ActivityManager;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.FlashlightController;
@@ -92,7 +94,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_FLASHLIGHT;
+        return MetricsEvent.QS_FLASHLIGHT;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 55aa32b..2f37943 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -16,7 +16,10 @@
 
 package com.android.systemui.qs.tiles;
 
+import android.os.UserManager;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.HotspotController;
@@ -65,6 +68,8 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         state.label = mContext.getString(R.string.quick_settings_hotspot_label);
 
+        state.disabledByPolicy = mController.isTetheringAllowed();
+        checkIfRestrictionEnforced(state, UserManager.DISALLOW_CONFIG_TETHERING);
         if (arg instanceof Boolean) {
             state.value = (boolean) arg;
         } else {
@@ -75,7 +80,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_HOTSPOT;
+        return MetricsEvent.QS_HOTSPOT;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 0883445..e1dc9f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -30,6 +30,7 @@
 import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.qs.QSTile;
 
 import java.util.Arrays;
@@ -155,7 +156,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_INTENT;
+        return MetricsEvent.QS_INTENT;
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index e79aabf..8328897 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -16,7 +16,10 @@
 
 package com.android.systemui.qs.tiles;
 
+import android.os.UserManager;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -84,6 +87,8 @@
         // bug is fixed, this should be reverted to only hiding it on secure lock screens:
         // state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
         state.value = locationEnabled;
+        state.disabledByPolicy = mController.isUserLocationRestricted();
+        checkIfRestrictionEnforced(state, UserManager.DISALLOW_SHARE_LOCATION);
         if (locationEnabled) {
             state.icon = mEnable;
             state.label = mContext.getString(R.string.quick_settings_location_label);
@@ -99,7 +104,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_LOCATION;
+        return MetricsEvent.QS_LOCATION;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 79155b2..f920d48 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -18,7 +18,9 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.RotationLockController;
@@ -108,7 +110,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_ROTATIONLOCK;
+        return MetricsEvent.QS_ROTATIONLOCK;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index b44ef0b..2c8a478 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -24,6 +24,7 @@
 import android.view.ViewGroup;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.PseudoGridView;
@@ -94,7 +95,7 @@
                         mContext, tag.enforcedAdmin);
                 mController.startActivity(intent);
             } else {
-                MetricsLogger.action(mContext, MetricsLogger.QS_SWITCH_USER);
+                MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
                 switchTo(tag);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index d29cae4..6eb0646 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -18,7 +18,7 @@
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.util.Pair;
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -52,7 +52,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_USER_TILE;
+        return MetricsEvent.QS_USER_TILE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 95ea3f8..42296f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -24,7 +24,9 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
@@ -162,7 +164,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_WIFI;
+        return MetricsEvent.QS_WIFI;
     }
 
     @Override
@@ -256,14 +258,14 @@
         @Override
         public void setToggleState(boolean state) {
             if (DEBUG) Log.d(TAG, "setToggleState " + state);
-            MetricsLogger.action(mContext, MetricsLogger.QS_WIFI_TOGGLE, state);
+            MetricsLogger.action(mContext, MetricsEvent.QS_WIFI_TOGGLE, state);
             mController.setWifiEnabled(state);
             showDetail(false);
         }
 
         @Override
         public int getMetricsCategory() {
-            return MetricsLogger.QS_WIFI_DETAILS;
+            return MetricsEvent.QS_WIFI_DETAILS;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 34ed37b..508490f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -24,7 +24,9 @@
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 
@@ -124,7 +126,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_WORKMODE;
+        return MetricsEvent.QS_WORKMODE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 189e8d3..c3b794d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -34,10 +34,11 @@
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
@@ -68,7 +69,6 @@
 import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
-import com.android.systemui.recents.history.RecentsHistoryView;
 import com.android.systemui.recents.misc.DozeTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.RecentsPackageMonitor;
@@ -80,8 +80,6 @@
 import com.android.systemui.recents.views.SystemBarScrimViews;
 import com.android.systemui.statusbar.BaseStatusBar;
 
-import java.util.ArrayList;
-
 /**
  * The main Recents activity that is started from AlternateRecentsComponent.
  */
@@ -103,8 +101,6 @@
     // Top level views
     private RecentsView mRecentsView;
     private SystemBarScrimViews mScrimViews;
-    private ViewStub mHistoryViewStub;
-    private RecentsHistoryView mHistoryView;
 
     // Search AppWidget
     private AppWidgetProviderInfo mSearchWidgetInfo;
@@ -125,12 +121,14 @@
      * just finishing the activity since we don't know what is behind Recents in the task stack.
      */
     class FinishRecentsRunnable implements Runnable {
+
         Intent mLaunchIntent;
+        ActivityOptions mOpts;
 
         /**
          * Creates a finish runnable that starts the specified intent.
          */
-        public FinishRecentsRunnable(Intent launchIntent) {
+        public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
             mLaunchIntent = launchIntent;
         }
 
@@ -139,13 +137,16 @@
             try {
                 RecentsActivityLaunchState launchState =
                         Recents.getConfiguration().getLaunchState();
-                ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
-                        launchState.launchedFromSearchHome ?
-                                R.anim.recents_to_search_launcher_enter :
-                                R.anim.recents_to_launcher_enter,
-                        launchState.launchedFromSearchHome ?
-                                R.anim.recents_to_search_launcher_exit :
-                                R.anim.recents_to_launcher_exit);
+                ActivityOptions opts = mOpts;
+                if (opts == null) {
+                    opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
+                            launchState.launchedFromSearchHome ?
+                                    R.anim.recents_to_search_launcher_enter :
+                                    R.anim.recents_to_launcher_enter,
+                            launchState.launchedFromSearchHome ?
+                                    R.anim.recents_to_search_launcher_exit :
+                                    R.anim.recents_to_launcher_exit);
+                }
                 startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
             } catch (Exception e) {
                 Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
@@ -203,12 +204,9 @@
         int launchTaskIndexInStack = launchTarget != null
                 ? stack.indexOfStackTask(launchTarget)
                 : 0;
-        boolean hasStatusBarScrim = taskCount > 0;
-        boolean animateStatusBarScrim = launchState.launchedFromHome;
         boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
         boolean animateNavBarScrim = true;
-        mScrimViews.prepareEnterRecentsAnimation(hasStatusBarScrim, animateStatusBarScrim,
-                hasNavBarScrim, animateNavBarScrim);
+        mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
 
         // Keep track of whether we launched from the nav bar button or via alt-tab
         if (launchState.launchedWithAltTab) {
@@ -232,8 +230,7 @@
      * Dismisses the history view back into the stack view.
      */
     boolean dismissHistory() {
-        // Try and hide the history view first
-        if (mHistoryView != null && mHistoryView.isVisible()) {
+        if (mRecentsView.isHistoryVisible()) {
             EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
             return true;
         }
@@ -285,9 +282,24 @@
      * Dismisses Recents directly to Home without checking whether it is currently visible.
      */
     void dismissRecentsToHome(boolean animateTaskViews) {
+        dismissRecentsToHome(animateTaskViews, null);
+    }
+
+    /**
+     * Dismisses Recents directly to Home without checking whether it is currently visible.
+     *
+     * @param overrideAnimation If not null, will override the default animation that is based on
+     *                          how Recents was launched.
+     */
+    void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
         DismissRecentsToHomeAnimationStarted dismissEvent =
                 new DismissRecentsToHomeAnimationStarted(animateTaskViews);
-        dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+        if (overrideAnimation != null) {
+            dismissEvent.addPostAnimationCallback(new FinishRecentsRunnable(
+                    mFinishLaunchHomeRunnable.mLaunchIntent, overrideAnimation));
+        } else {
+            dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+        }
         dismissEvent.addPostAnimationCallback(new Runnable() {
             @Override
             public void run() {
@@ -340,7 +352,6 @@
         mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-        mHistoryViewStub = (ViewStub) findViewById(R.id.history_view_stub);
         mScrimViews = new SystemBarScrimViews(this);
         getWindow().getAttributes().privateFlags |=
                 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -358,7 +369,7 @@
         homeIntent.addCategory(Intent.CATEGORY_HOME);
         homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
+        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, null);
 
         // Bind the search app widget when we first start up
         if (RecentsDebugFlags.Static.EnableSearchBar) {
@@ -402,7 +413,7 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
 
-        MetricsLogger.visible(this, MetricsLogger.OVERVIEW_ACTIVITY);
+        MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
 
         mRecentsView.getViewTreeObserver().addOnPreDrawListener(
                 new ViewTreeObserver.OnPreDrawListener() {
@@ -439,7 +450,7 @@
 
         // Reset some states
         mIgnoreAltTabRelease = false;
-        if (mHistoryView != null) {
+        if (mRecentsView.isHistoryVisible()) {
             EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
         }
 
@@ -460,7 +471,7 @@
         launchState.launchedHasConfigurationChanged = false;
         launchState.launchedViaDragGesture = false;
 
-        MetricsLogger.hidden(this, MetricsLogger.OVERVIEW_ACTIVITY);
+        MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
     }
 
     @Override
@@ -501,8 +512,7 @@
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE,
-                (mHistoryView != null) && mHistoryView.isVisible());
+        outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE, mRecentsView.isHistoryVisible());
     }
 
     @Override
@@ -633,7 +643,7 @@
             // Focus the next task
             EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
 
-            MetricsLogger.action(this, MetricsLogger.ACTION_OVERVIEW_PAGE);
+            MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
         }
     }
 
@@ -649,15 +659,12 @@
             }
         } else if (event.triggeredFromHomeKey) {
             // Otherwise, dismiss Recents to Home
-            if (mHistoryView != null && mHistoryView.isVisible()) {
-                HideHistoryEvent hideEvent = new HideHistoryEvent(true /* animate */);
-                hideEvent.addPostAnimationCallback(new Runnable() {
-                    @Override
-                    public void run() {
-                        dismissRecentsToHome(true /* animateTaskViews */);
-                    }
-                });
-                EventBus.getDefault().send(hideEvent);
+            if (mRecentsView.isHistoryVisible()) {
+                // If the history view is visible, then just cross-fade home
+                ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
+                                R.anim.recents_to_launcher_enter,
+                                R.anim.recents_to_launcher_exit);
+                dismissRecentsToHome(false /* animate */, opts);
 
             } else {
                 dismissRecentsToHome(true /* animateTaskViews */);
@@ -793,21 +800,6 @@
         mIgnoreAltTabRelease = true;
     }
 
-    public final void onBusEvent(ShowHistoryEvent event) {
-        if (mHistoryView == null) {
-            mHistoryView = (RecentsHistoryView) mHistoryViewStub.inflate();
-            // Since this history view is inflated by a view stub after the insets have already
-            // been applied, we have to set them ourselves initial from the insets that were last
-            // provided.
-            mHistoryView.setSystemInsets(mRecentsView.getSystemInsets());
-        }
-        mHistoryView.show(mRecentsView.getTaskStack(), event.getAnimationTrigger());
-    }
-
-    public final void onBusEvent(HideHistoryEvent event) {
-        mHistoryView.hide(event.animate, event.getAnimationTrigger());
-    }
-
     private void refreshSearchWidgetView() {
         if (mSearchWidgetInfo != null) {
             SystemServicesProxy ssp = Recents.getSystemServices();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index b78fd22..d1301cf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -19,10 +19,12 @@
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ITaskStackListener;
+import android.app.UiModeManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -87,7 +89,10 @@
 
     public final static String RECENTS_PACKAGE = "com.android.systemui";
     public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
+    public final static String RECENTS_TV_ACTIVITY = "com.android.systemui.recents.tv.RecentsTvActivity";
 
+    //Used to store tv or non-tv activty for use in creating intents.
+    private final String mRecentsIntentActivityName;
     /**
      * An implementation of ITaskStackListener, that allows us to listen for changes to the system
      * task stacks and update recents accordingly.
@@ -210,6 +215,14 @@
         launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize();
         launchOpts.onlyLoadForCache = true;
         loader.loadTasks(mContext, plan, launchOpts);
+
+        //Manager used to determine if we are running on tv or not
+        UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
+        if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
+            mRecentsIntentActivityName = RECENTS_TV_ACTIVITY;
+        } else {
+            mRecentsIntentActivityName = RECENTS_ACTIVITY;
+        }
     }
 
     public void onBootCompleted() {
@@ -906,10 +919,11 @@
         launchState.launchedViaDragGesture = mDraggingInRecents;
 
         Intent intent = new Intent();
-        intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
+        intent.setClassName(RECENTS_PACKAGE, mRecentsIntentActivityName);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                 | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+
         if (opts != null) {
             mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
         } else {
diff --git a/location/java/android/location/IGpsStatusProvider.aidl b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ClearHistoryEvent.java
similarity index 60%
copy from location/java/android/location/IGpsStatusProvider.aidl
copy to packages/SystemUI/src/com/android/systemui/recents/events/activity/ClearHistoryEvent.java
index cf277c8..98c0a69 100644
--- a/location/java/android/location/IGpsStatusProvider.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ClearHistoryEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,16 +14,13 @@
  * limitations under the License.
  */
 
-package android.location;
+package com.android.systemui.recents.events.activity;
 
-import android.location.IGpsStatusListener;
+import com.android.systemui.recents.events.EventBus;
 
 /**
- * An interface for location providers that provide GPS status information.
- *
- * {@hide}
+ * This is sent when the history is to be cleared
  */
-interface IGpsStatusProvider {
-    void addGpsStatusListener(IGpsStatusListener listener);
-    void removeGpsStatusListener(IGpsStatusListener listener);
+public class ClearHistoryEvent extends EventBus.AnimatedEvent {
+    // Simple event
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
index af3eeb0..bacf3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
@@ -21,7 +21,7 @@
 /**
  * This is sent when the history view will be closed.
  */
-public class HideHistoryEvent extends EventBus.AnimatedEvent {
+public class HideHistoryEvent extends EventBus.Event {
 
     public final boolean animate;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
index 7042537..ae803ea 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
@@ -22,5 +22,11 @@
  * This is sent when the history view button should be shown.
  */
 public class ShowHistoryButtonEvent extends EventBus.Event {
-    // Simple event
+
+    // Whether or not to translate the history button when showing it
+    public final boolean translate;
+
+    public ShowHistoryButtonEvent(boolean translate) {
+        this.translate = translate;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
index b39d645..469f336 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
@@ -21,7 +21,7 @@
 /**
  * This is sent when the history view button is clicked.
  */
-public class ShowHistoryEvent extends EventBus.AnimatedEvent {
+public class ShowHistoryEvent extends EventBus.Event {
 
     // Simple event
 
diff --git a/location/java/android/location/IGpsStatusProvider.aidl b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
similarity index 60%
copy from location/java/android/location/IGpsStatusProvider.aidl
copy to packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
index cf277c8..aaf77af 100644
--- a/location/java/android/location/IGpsStatusProvider.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-package android.location;
+package com.android.systemui.recents.events.activity;
 
-import android.location.IGpsStatusListener;
+import com.android.systemui.recents.events.EventBus;
 
 /**
- * An interface for location providers that provide GPS status information.
- *
- * {@hide}
+ * This is sent when the history view button is clicked.
  */
-interface IGpsStatusProvider {
-    void addGpsStatusListener(IGpsStatusListener listener);
-    void removeGpsStatusListener(IGpsStatusListener listener);
+public class ToggleHistoryEvent extends EventBus.AnimatedEvent {
+
+    // Simple event
+
 }
diff --git a/location/java/android/location/IGpsStatusProvider.aidl b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
similarity index 60%
copy from location/java/android/location/IGpsStatusProvider.aidl
copy to packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
index cf277c8..863f40b 100644
--- a/location/java/android/location/IGpsStatusProvider.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,16 +14,13 @@
  * limitations under the License.
  */
 
-package android.location;
+package com.android.systemui.recents.events.ui;
 
-import android.location.IGpsStatusListener;
+import com.android.systemui.recents.events.EventBus;
 
 /**
- * An interface for location providers that provide GPS status information.
- *
- * {@hide}
+ * This is sent to reset the background scrim back to the initial state.
  */
-interface IGpsStatusProvider {
-    void addGpsStatusListener(IGpsStatusListener listener);
-    void removeGpsStatusListener(IGpsStatusListener listener);
+public class ResetBackgroundScrimEvent extends EventBus.Event {
+    // Simple event
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
new file mode 100644
index 0000000..fdd4c67
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent to request an update to the background scrim.
+ */
+public class UpdateBackgroundScrimEvent extends EventBus.Event {
+
+    public final float alpha;
+
+    public UpdateBackgroundScrimEvent(float alpha) {
+        this.alpha = alpha;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index f6655c7..e288878 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -26,12 +26,15 @@
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.HideHistoryEvent;
+import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
@@ -74,6 +77,10 @@
             // This callback is only made for TaskRow view holders
             ImageView iv = (ImageView) content.findViewById(R.id.icon);
             iv.setImageDrawable(task.icon);
+            iv.animate()
+                    .alpha(1f)
+                    .setDuration(100)
+                    .start();
         }
 
         @Override
@@ -81,6 +88,7 @@
             // This callback is only made for TaskRow view holders
             ImageView iv = (ImageView) content.findViewById(R.id.icon);
             iv.setImageBitmap(null);
+            iv.animate().cancel();
         }
 
         @Override
@@ -132,7 +140,7 @@
             ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
                     ActivityOptions.makeBasic());
 
-            MetricsLogger.action(v.getContext(), MetricsLogger.ACTION_OVERVIEW_SELECT,
+            MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
                     task.key.getComponent().toString());
         }
 
@@ -164,14 +172,16 @@
         final List<Task> tasksMostRecent = new ArrayList<>(stack.getHistoricalTasks());
         Collections.reverse(tasksMostRecent);
         int prevDateKey = -1;
+        int taskCount = tasksMostRecent.size();
         mRows.clear();
         mTaskRowCount.clear();
-        for (Task task : tasksMostRecent) {
+        Calendar cal = Calendar.getInstance(l);
+        for (int i = 0; i < taskCount; i++) {
+            Task task = tasksMostRecent.get(i);
             if (task.isFreeformTask()) {
                 continue;
             }
 
-            Calendar cal = Calendar.getInstance(l);
             cal.setTimeInMillis(task.key.lastActiveTime);
             int dateKey = Objects.hash(cal.get(Calendar.YEAR), cal.get(Calendar.DAY_OF_YEAR));
             if (dateKey != prevDateKey) {
@@ -206,6 +216,23 @@
     }
 
     /**
+     * Removes all historical tasks.
+     */
+    public void removeAllTasks() {
+        for (int i = mRows.size() - 1; i >= 0; i--) {
+            Row row = mRows.get(i);
+            if (row.getViewType() == TASK_ROW_VIEW_TYPE) {
+                TaskRow taskRow = (TaskRow) row;
+                Task task = taskRow.task;
+                mStack.removeTask(task, TaskViewAnimation.IMMEDIATE);
+                EventBus.getDefault().send(new DeleteTaskDataEvent(task));
+                i = removeTaskRow(i);
+            }
+        }
+        dismissHistory();
+    }
+
+    /**
      * Returns the row at the given {@param position}.
      */
     public Row getRow(int position) {
@@ -243,8 +270,10 @@
                 taskRow.task.addCallback(holder);
                 TextView tv = (TextView) holder.content.findViewById(R.id.description);
                 tv.setText(taskRow.task.title);
+                ImageView iv = (ImageView) holder.content.findViewById(R.id.icon);
+                iv.setAlpha(0f);
                 holder.content.setOnClickListener(taskRow);
-                loader.loadTaskData(taskRow.task);
+                loader.loadTaskData(taskRow.task, false /* fetchAndInvalidateThumbnails */);
                 break;
             }
         }
@@ -253,19 +282,25 @@
     @Override
     public void onViewRecycled(ViewHolder holder) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
-
         int position = holder.getAdapterPosition();
         if (position != RecyclerView.NO_POSITION) {
             Row row = mRows.get(position);
             int viewType = row.getViewType();
             if (viewType == TASK_ROW_VIEW_TYPE) {
                 TaskRow taskRow = (TaskRow) row;
-                taskRow.task.removeCallback(holder);
                 loader.unloadTaskData(taskRow.task);
+                taskRow.task.removeCallback(holder);
             }
         }
     }
 
+    @Override
+    public boolean onFailedToRecycleView(ViewHolder holder) {
+        // Always recycle views, even if it is animating
+        onViewRecycled(holder);
+        return true;
+    }
+
     public void onTaskRemoved(Task task, int position) {
         // Since this is removed from the history, we need to update the stack as well to ensure
         // that the model is correct. Since the stack is hidden, we can update it immediately.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
index 39bb6ca..96b5cac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.history;
 
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
@@ -28,29 +29,37 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.LinearLayout;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.ClearHistoryEvent;
 import com.android.systemui.recents.events.activity.PackagesChangedEvent;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
+import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.AnimateableViewBounds;
 
 /**
  * A list of the recent tasks that are not in the stack.
  */
-public class RecentsHistoryView extends LinearLayout {
+public class RecentsHistoryView extends LinearLayout
+        implements ValueAnimator.AnimatorUpdateListener {
 
-    private static final String TAG = "RecentsHistoryView";
-    private static final boolean DEBUG = false;
+    private static final float TRANSLATION_Y_PCT = 0.25f;
+    private static final float BG_SCRIM_ALPHA = 0.625f;
 
     private RecyclerView mRecyclerView;
     private RecentsHistoryAdapter mAdapter;
     private RecentsHistoryItemTouchCallbacks mItemTouchHandler;
+    private AnimateableViewBounds mViewBounds;
     private boolean mIsVisible;
     private Rect mSystemInsets = new Rect();
+    private int mHeaderHeight;
 
     private Interpolator mFastOutSlowInInterpolator;
     private Interpolator mFastOutLinearInInterpolator;
@@ -79,68 +88,95 @@
                 com.android.internal.R.interpolator.fast_out_slow_in);
         mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_linear_in);
+        mViewBounds = new AnimateableViewBounds(this, 0);
+        setOutlineProvider(mViewBounds);
     }
 
     /**
      * Updates this history view with the recent tasks, and then shows it.
      */
-    public void show(TaskStack stack, ReferenceCountedTrigger postHideAnimationTrigger) {
+    public void show(TaskStack stack, int stackHeight, View clearAllButton) {
         setVisibility(View.VISIBLE);
         setAlpha(0f);
-        postHideAnimationTrigger.addLastDecrementRunnable(new Runnable() {
-            @Override
-            public void run() {
-                animate()
-                        .alpha(1f)
-                        .setDuration(mHistoryTransitionDuration)
-                        .setInterpolator(mFastOutSlowInInterpolator)
-                        .withLayer()
-                        .start();
-            }
-        });
+        setTranslationY(-stackHeight * TRANSLATION_Y_PCT);
+        animate()
+                .alpha(1f)
+                .translationY(0f)
+                .setDuration(mHistoryTransitionDuration)
+                .setInterpolator(mFastOutSlowInInterpolator)
+                .setUpdateListener(this)
+                .start();
+        clearAllButton.setVisibility(View.VISIBLE);
+        clearAllButton.setAlpha(0f);
+        clearAllButton.animate()
+                .alpha(1f)
+                .setDuration(mHistoryTransitionDuration)
+                .setInterpolator(mFastOutSlowInInterpolator)
+                .withLayer()
+                .start();
         mAdapter.updateTasks(getContext(), stack);
         mIsVisible = true;
+        EventBus.getDefault().send(new UpdateBackgroundScrimEvent(BG_SCRIM_ALPHA));
 
-        MetricsLogger.visible(mRecyclerView.getContext(), MetricsLogger.OVERVIEW_HISTORY);
+        MetricsLogger.visible(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
     }
 
     /**
      * Hides this history view.
      */
-    public void hide(boolean animate, final ReferenceCountedTrigger postAnimationTrigger) {
+    public void hide(boolean animate, int stackHeight, final View clearAllButton) {
         if (animate) {
             animate()
                     .alpha(0f)
+                    .translationY(-stackHeight * TRANSLATION_Y_PCT)
                     .setDuration(mHistoryTransitionDuration)
                     .setInterpolator(mFastOutLinearInInterpolator)
+                    .setUpdateListener(this)
                     .withEndAction(new Runnable() {
                         @Override
                         public void run() {
                             setVisibility(View.INVISIBLE);
-                            if (postAnimationTrigger != null) {
-                                postAnimationTrigger.decrement();
-                            }
+                        }
+                    })
+                    .start();
+            clearAllButton.animate()
+                    .alpha(0f)
+                    .translationY(0f)
+                    .setDuration(mHistoryTransitionDuration)
+                    .setInterpolator(mFastOutSlowInInterpolator)
+                    .withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            clearAllButton.setVisibility(View.INVISIBLE);
                         }
                     })
                     .withLayer()
                     .start();
-            if (postAnimationTrigger != null) {
-                postAnimationTrigger.increment();
-            }
         } else {
             setAlpha(0f);
             setVisibility(View.INVISIBLE);
+            clearAllButton.setAlpha(0f);
+            clearAllButton.setVisibility(View.INVISIBLE);
         }
         mIsVisible = false;
+        EventBus.getDefault().send(new ResetBackgroundScrimEvent());
 
-        MetricsLogger.hidden(mRecyclerView.getContext(), MetricsLogger.OVERVIEW_HISTORY);
+        MetricsLogger.hidden(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
     }
 
     /**
      * Updates the system insets of this history view to the provided values.
      */
     public void setSystemInsets(Rect systemInsets) {
-        mSystemInsets.set(systemInsets.left, systemInsets.top, systemInsets.right, systemInsets.bottom);
+        mSystemInsets.set(systemInsets);
+        requestLayout();
+    }
+
+    /**
+     * Updates the header height to account for the history button bar.
+     */
+    public void setHeaderHeight(int height) {
+        mHeaderHeight = height;
         requestLayout();
     }
 
@@ -175,7 +211,7 @@
         int stackHeightPadding = mContext.getResources().getDimensionPixelSize(
                 R.dimen.recents_stack_top_padding);
         mRecyclerView.setPadding(stackWidthPadding + mSystemInsets.left,
-                stackHeightPadding + mSystemInsets.top,
+                stackHeightPadding + mSystemInsets.top + mHeaderHeight,
                 stackWidthPadding + mSystemInsets.right, mSystemInsets.bottom);
 
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -199,9 +235,25 @@
         return insets;
     }
 
+    @Override
+    public void onAnimationUpdate(ValueAnimator animation) {
+        // Clip the top of the view by the header bar height
+        int top = Math.max(0, (int) -getTranslationY()) + mSystemInsets.top + mHeaderHeight;
+        mViewBounds.setClipTop(top);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
     /**** EventBus Events ****/
 
     public final void onBusEvent(PackagesChangedEvent event) {
         mAdapter.removeTasks(event.packageName, event.userId);
     }
+
+    public final void onBusEvent(ClearHistoryEvent event) {
+        mAdapter.removeAllTasks();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 2882cec..aa006d1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -81,6 +81,7 @@
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 
 /**
@@ -266,8 +267,9 @@
             ComponentName topActivity = topTask.topActivity;
 
             // Check if the front most activity is recents
-            if (topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE) &&
-                    topActivity.getClassName().equals(RecentsImpl.RECENTS_ACTIVITY)) {
+            if ((topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE) &&
+                    (topActivity.getClassName().equals(RecentsImpl.RECENTS_ACTIVITY) ||
+                    topActivity.getClassName().equals(RecentsImpl.RECENTS_TV_ACTIVITY)))) {
                 if (isHomeTopMost != null) {
                     isHomeTopMost.value = false;
                 }
@@ -356,6 +358,13 @@
     }
 
     /**
+     * Returns whether the given stack id is the pinned stack id.
+     */
+    public static boolean isPinnedStack(int stackId){
+        return stackId == PINNED_STACK_ID;
+    }
+
+    /**
      * Returns whether the given stack id is the docked stack id.
      */
     public static boolean isDockedStack(int stackId) {
@@ -968,4 +977,20 @@
     public void requestKeyboardShortcuts(Context context, KeyboardShortcutsReceiver receiver) {
         mWm.requestAppKeyboardShortcuts(receiver);
     }
+
+    public void focusPinnedStack() {
+        try {
+            mIam.setFocusedStack(PINNED_STACK_ID);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void focusHomeStack() {
+        try {
+            mIam.setFocusedStack(HOME_STACK_ID);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index d15828a..3029acf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -37,6 +37,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Formatter;
 import java.util.List;
 
 
@@ -130,6 +131,7 @@
         SparseIntArray affiliatedTaskCounts = new SparseIntArray();
         String dismissDescFormat = mContext.getString(
                 R.string.accessibility_recents_item_will_be_dismissed);
+        Formatter dismissDescFormatter = new Formatter();
         long lastStackActiveTime = Prefs.getLong(mContext,
                 Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
         if (RecentsDebugFlags.Static.EnableMockTasks) {
@@ -168,7 +170,8 @@
             // Load the title, icon, and color
             String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
             String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
-            String dismissDescription = String.format(dismissDescFormat, contentDescription);
+            String dismissDescription = dismissDescFormatter.format(dismissDescFormat,
+                    contentDescription).toString();
             Drawable icon = isStackTask
                     ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
                     : null;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 44ad239..5c77d8a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -334,10 +334,19 @@
         }
     }
 
-    /** Acquires the task resource data directly from the pool. */
-    public void loadTaskData(Task t) {
+    /**
+     * Acquires the task resource data directly from the cache, loading if necessary.
+     *
+     * @param fetchAndInvalidateThumbnails If set, will try loading thumbnails, invalidating them
+     *                                     in the cache and loading if necessary. Otherwise, do not
+     *                                     load the thumbnail unless the icon also has to be loaded.
+     */
+    public void loadTaskData(Task t, boolean fetchAndInvalidateThumbnails) {
         Drawable icon = mIconCache.getAndInvalidateIfModified(t.key);
-        Bitmap thumbnail = mThumbnailCache.getAndInvalidateIfModified(t.key);
+        Bitmap thumbnail = mDefaultThumbnail;
+        if (fetchAndInvalidateThumbnails) {
+            thumbnail = mThumbnailCache.getAndInvalidateIfModified(t.key);
+        }
 
         // Grab the thumbnail/icon from the cache, if either don't exist, then trigger a reload and
         // use the default assets in their place until they load
@@ -360,6 +369,8 @@
         mLoadQueue.removeTask(t);
         mThumbnailCache.remove(t.key);
         mIconCache.remove(t.key);
+        mActivityLabelCache.remove(t.key);
+        mContentDescriptionCache.remove(t.key);
         mActivityInfoCache.remove(t.key.getComponent());
         if (notifyTaskDataUnloaded) {
             t.notifyTaskDataUnloaded(null, mDefaultIcon);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
new file mode 100644
index 0000000..6593169
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewTreeObserver.OnPreDrawListener;
+import android.view.WindowManager;
+import com.android.systemui.R;
+import com.android.systemui.recents.*;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
+import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
+import com.android.systemui.recents.events.activity.HideRecentsEvent;
+import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
+import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
+import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
+import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
+import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
+import com.android.systemui.recents.events.ui.UserInteractionEvent;
+import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.RecentsPackageMonitor;
+import com.android.systemui.recents.model.RecentsTaskLoadPlan;
+import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.views.RecentsTvView;
+import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
+import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.tv.pip.PipManager;
+
+import java.util.ArrayList;
+/**
+ * The main TV recents activity started by the RecentsImpl.
+ */
+public class RecentsTvActivity extends Activity implements OnPreDrawListener {
+    private final static String TAG = "RecentsTvActivity";
+    private final static boolean DEBUG = false;
+
+    public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
+
+    private boolean mFinishedOnStartup;
+    private RecentsPackageMonitor mPackageMonitor;
+    private long mLastTabKeyEventTime;
+    private boolean mIgnoreAltTabRelease;
+
+    private RecentsTvView mRecentsView;
+    private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
+    private FinishRecentsRunnable mFinishLaunchHomeRunnable;
+
+
+    /**
+     * A common Runnable to finish Recents by launching Home with an animation depending on the
+     * last activity launch state.  Generally we always launch home when we exit Recents rather than
+     * just finishing the activity since we don't know what is behind Recents in the task stack.
+     */
+    class FinishRecentsRunnable implements Runnable {
+        Intent mLaunchIntent;
+
+        /**
+         * Creates a finish runnable that starts the specified intent.
+         */
+        public FinishRecentsRunnable(Intent launchIntent) {
+            mLaunchIntent = launchIntent;
+        }
+
+        @Override
+        public void run() {
+            try {
+                RecentsActivityLaunchState launchState =
+                        Recents.getConfiguration().getLaunchState();
+                ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsTvActivity.this,
+                        launchState.launchedFromSearchHome ?
+                                R.anim.recents_to_search_launcher_enter :
+                                R.anim.recents_to_launcher_enter,
+                        launchState.launchedFromSearchHome ?
+                                R.anim.recents_to_search_launcher_exit :
+                                R.anim.recents_to_launcher_exit);
+                startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
+            } catch (Exception e) {
+                Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
+            }
+        }
+    }
+
+    private void updateRecentsTasks() {
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
+        if (plan == null) {
+            plan = loader.createLoadPlan(this);
+        }
+
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        if (!plan.hasTasks()) {
+            loader.preloadTasks(plan, -1, launchState.launchedFromHome);
+        }
+        TaskStack stack = plan.getTaskStack();
+        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+        loadOpts.runningTaskId = launchState.launchedToTaskId;
+        loadOpts.numVisibleTasks = stack.getStackTaskCount();
+        loadOpts.numVisibleTaskThumbnails = stack.getStackTaskCount();
+        loader.loadTasks(this, plan, loadOpts);
+
+
+        mRecentsView.setTaskStack(stack);
+        if (mTaskStackViewAdapter == null) {
+            mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stack.getStackTasks());
+            mRecentsView.setTaskStackViewAdapter(mTaskStackViewAdapter);
+        } else {
+            mTaskStackViewAdapter.setNewStackTasks(stack.getStackTasks());
+        }
+
+        if (launchState.launchedToTaskId != -1) {
+            ArrayList<Task> tasks = stack.getStackTasks();
+            int taskCount = tasks.size();
+            for (int i = 0; i < taskCount; i++) {
+                Task t = tasks.get(i);
+                if (t.key.id == launchState.launchedToTaskId) {
+                    t.isLaunchTarget = true;
+                    break;
+                }
+            }
+        }
+    }
+
+    boolean dismissRecentsToLaunchTargetTaskOrHome() {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.isRecentsTopMost(ssp.getTopMostTask(), null)) {
+            // If we have a focused Task, launch that Task now
+            if (mRecentsView.launchPreviousTask()) return true;
+            // If none of the other cases apply, then just go Home
+            dismissRecentsToHome(true /* animateTaskViews */);
+        }
+        return false;
+    }
+
+    boolean dismissRecentsToFocusedTaskOrHome() {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.isRecentsTopMost(ssp.getTopMostTask(), null)) {
+            // If we have a focused Task, launch that Task now
+            if (mRecentsView.launchFocusedTask()) return true;
+            // If none of the other cases apply, then just go Home
+            dismissRecentsToHome(true /* animateTaskViews */);
+            return true;
+        }
+        return false;
+    }
+
+    void dismissRecentsToHome(boolean animateTaskViews) {
+        DismissRecentsToHomeAnimationStarted dismissEvent =
+                new DismissRecentsToHomeAnimationStarted(animateTaskViews);
+        dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+        dismissEvent.addPostAnimationCallback(new Runnable() {
+            @Override
+            public void run() {
+                Recents.getSystemServices().sendCloseSystemWindows(
+                        BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
+            }
+        });
+        EventBus.getDefault().send(dismissEvent);
+    }
+
+    boolean dismissRecentsToHomeIfVisible(boolean animated) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.isRecentsTopMost(ssp.getTopMostTask(), null)) {
+            // Return to Home
+            dismissRecentsToHome(animated);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mFinishedOnStartup = false;
+
+        // In the case that the activity starts up before the Recents component has initialized
+        // (usually when debugging/pushing the SysUI apk), just finish this activity.
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp == null) {
+            mFinishedOnStartup = true;
+            finish();
+            return;
+        }
+
+        // Register this activity with the event bus
+        EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
+
+        mPackageMonitor = new RecentsPackageMonitor();
+        mPackageMonitor.register(this);
+
+        // Set the Recents layout
+        setContentView(R.layout.recents_on_tv);
+
+        mRecentsView = (RecentsTvView) findViewById(R.id.recents_view);
+        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+
+        getWindow().getAttributes().privateFlags |=
+                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
+
+        // Create the home intent runnable
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        setIntent(intent);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        // Update the recent tasks
+        updateRecentsTasks();
+
+        // If this is a new instance from a configuration change, then we have to manually trigger
+        // the enter animation state, or if recents was relaunched by AM, without going through
+        // the normal mechanisms
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        boolean wasLaunchedByAm = !launchState.launchedFromHome &&
+                !launchState.launchedFromAppWithThumbnail;
+        if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
+            EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
+        }
+
+        // Notify that recents is now visible
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
+    }
+
+    @Override
+    public void onEnterAnimationComplete() {
+        super.onEnterAnimationComplete();
+        EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+
+        mIgnoreAltTabRelease = false;
+        // Notify that recents is now hidden
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, false));
+
+        // Workaround for b/22542869, if the RecentsActivity is started again, but without going
+        // through SystemUI, we need to reset the config launch flags to ensure that we do not
+        // wait on the system to send a signal that was never queued.
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        launchState.launchedFromHome = false;
+        launchState.launchedFromSearchHome = false;
+        launchState.launchedFromAppWithThumbnail = false;
+        launchState.launchedToTaskId = -1;
+        launchState.launchedWithAltTab = false;
+        launchState.launchedHasConfigurationChanged = false;
+        launchState.launchedViaDragGesture = false;
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+
+        // In the case that the activity finished on startup, just skip the unregistration below
+        if (mFinishedOnStartup) {
+            return;
+        }
+
+        // Unregister any broadcast receivers for the task loader
+        mPackageMonitor.unregister();
+
+        EventBus.getDefault().unregister(this);
+    }
+
+    @Override
+    public void onTrimMemory(int level) {
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        if (loader != null) {
+            loader.onTrimMemory(level);
+        }
+    }
+
+    @Override
+    public void onMultiWindowModeChanged(boolean multiWindowMode) {
+        super.onMultiWindowModeChanged(multiWindowMode);
+        if (!multiWindowMode) {
+            RecentsTaskLoader loader = Recents.getTaskLoader();
+            RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
+            launchOpts.loadIcons = false;
+            launchOpts.loadThumbnails = false;
+            launchOpts.onlyLoadForCache = true;
+            RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
+            loader.preloadTasks(loadPlan, -1, false);
+            loader.loadTasks(this, loadPlan, launchOpts);
+            EventBus.getDefault().send(new TaskStackUpdatedEvent(loadPlan.getTaskStack()));
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_UP: {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                PipManager.getInstance().showPipMenu();
+                ssp.focusPinnedStack();
+                return true;
+            }
+            case KeyEvent.KEYCODE_DPAD_DOWN: {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                PipManager.getInstance().showPipOverlay(false);
+                ssp.focusHomeStack();
+                return true;
+            }
+            case KeyEvent.KEYCODE_DEL:
+            case KeyEvent.KEYCODE_FORWARD_DEL: {
+                EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
+                return true;
+            }
+            default:
+                break;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public void onUserInteraction() {
+        EventBus.getDefault().send(new UserInteractionEvent());
+    }
+
+    @Override
+    public void onBackPressed() {
+        // Back behaves like the recents button so just trigger a toggle event
+        EventBus.getDefault().send(new ToggleRecentsEvent());
+    }
+
+    /**** EventBus events ****/
+
+    public final void onBusEvent(ToggleRecentsEvent event) {
+        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        if (launchState.launchedFromHome) {
+            dismissRecentsToHome(true /* animateTaskViews */);
+        } else {
+            dismissRecentsToLaunchTargetTaskOrHome();
+        }
+    }
+
+    public final void onBusEvent(HideRecentsEvent event) {
+        if (event.triggeredFromAltTab) {
+            // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
+            if (!mIgnoreAltTabRelease) {
+                dismissRecentsToFocusedTaskOrHome();
+            }
+        } else if (event.triggeredFromHomeKey) {
+                dismissRecentsToHome(true /* animateTaskViews */);
+        } else {
+            // Do nothing
+        }
+    }
+
+    public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
+        EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
+        mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
+        mRecentsView.invalidate();
+    }
+
+    public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
+        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        int launchToTaskId = launchState.launchedToTaskId;
+        if (launchToTaskId != -1 &&
+                (event.launchTask == null || launchToTaskId != event.launchTask.key.id)) {
+            SystemServicesProxy ssp = Recents.getSystemServices();
+            ssp.cancelWindowTransition(launchState.launchedToTaskId);
+            ssp.cancelThumbnailTransition(getTaskId());
+        }
+    }
+
+    public final void onBusEvent(DeleteTaskDataEvent event) {
+        // Remove any stored data from the loader
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        loader.deleteTaskData(event.task, false);
+
+        // Remove the task from activity manager
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        ssp.removeTask(event.task.key.id);
+    }
+
+    public final void onBusEvent(AllTaskViewsDismissedEvent event) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.hasDockedTask()) {
+            mRecentsView.showEmptyView();
+        } else {
+            // Just go straight home (no animation necessary because there are no more task views)
+            dismissRecentsToHome(false /* animateTaskViews */);
+        }
+    }
+
+    public final void onBusEvent(LaunchTaskFailedEvent event) {
+        // Return to Home
+        dismissRecentsToHome(true /* animateTaskViews */);
+    }
+
+    @Override
+    public boolean onPreDraw() {
+        mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
+        // We post to make sure that this information is delivered after this traversals is
+        // finished.
+        mRecentsView.post(new Runnable() {
+            @Override
+            public void run() {
+                Recents.getSystemServices().endProlongedAnimations();
+            }
+        });
+        return true;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
new file mode 100644
index 0000000..8212c73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv.animations;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.res.Resources;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
+import com.android.systemui.R;
+
+public class ViewFocusAnimator implements View.OnFocusChangeListener {
+    private final float mUnselectedScale;
+    private final float mSelectedScaleDelta;
+    private final float mUnselectedZ;
+    private final float mSelectedZDelta;
+    private final int mAnimDuration;
+    private final Interpolator mFocusInterpolator;
+
+    protected View mTargetView;
+    private float mFocusProgress;
+
+    ObjectAnimator mFocusAnimation;
+
+    public ViewFocusAnimator(View view) {
+        mTargetView = view;
+        final Resources res = view.getResources();
+
+        mTargetView.setOnFocusChangeListener(this);
+
+        TypedValue out = new TypedValue();
+        res.getValue(R.raw.unselected_scale, out, true);
+        mUnselectedScale = out.getFloat();
+        mSelectedScaleDelta = res.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1) -
+                mUnselectedScale;
+
+        mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z);
+        mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta);
+
+        mAnimDuration = res.getInteger(R.integer.item_scale_anim_duration);
+
+        mFocusInterpolator = new AccelerateDecelerateInterpolator();
+
+        mFocusAnimation = ObjectAnimator.ofFloat(this, "focusProgress", 0.0f);
+        mFocusAnimation.setDuration(mAnimDuration);
+        mFocusAnimation.setInterpolator(mFocusInterpolator);
+
+        setFocusProgress(0.0f);
+
+        mFocusAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mTargetView.setHasTransientState(true);
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mTargetView.setHasTransientState(false);
+            }
+        });
+    }
+
+    public void setFocusProgress(float level) {
+        mFocusProgress = level;
+
+        float scale = mUnselectedScale + (level * mSelectedScaleDelta);
+        float z = mUnselectedZ + (level * mSelectedZDelta);
+
+        mTargetView.setScaleX(scale);
+        mTargetView.setScaleY(scale);
+        mTargetView.setZ(z);
+    }
+
+    public float getFocusProgress() {
+        return mFocusProgress;
+    }
+
+    public void animateFocus(boolean focused) {
+        if (mFocusAnimation.isStarted()) {
+            mFocusAnimation.cancel();
+        }
+
+        float target = focused ? 1.0f : 0.0f;
+
+        if (getFocusProgress() != target) {
+            mFocusAnimation.setFloatValues(getFocusProgress(), target);
+            mFocusAnimation.start();
+        }
+    }
+
+    public void setFocusImmediate(boolean focused) {
+        if (mFocusAnimation.isStarted()) {
+            mFocusAnimation.cancel();
+        }
+
+        float target = focused ? 1.0f : 0.0f;
+
+        setFocusProgress(target);
+    }
+
+    @Override
+    public void onFocusChange(View v, boolean hasFocus) {
+        if (v != mTargetView) {
+            return;
+        }
+        changeSize(hasFocus);
+    }
+
+    protected void changeSize(boolean hasFocus) {
+        ViewGroup.LayoutParams lp = mTargetView.getLayoutParams();
+        int width = lp.width;
+        int height = lp.height;
+
+        if (width < 0 && height < 0) {
+            mTargetView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+            height = mTargetView.getMeasuredHeight();
+        }
+
+        if (mTargetView.isAttachedToWindow() && mTargetView.hasWindowFocus() &&
+                mTargetView.getVisibility() == View.VISIBLE) {
+            animateFocus(hasFocus);
+        } else {
+            setFocusImmediate(hasFocus);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
new file mode 100644
index 0000000..c4d5b2b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv.views;
+
+import android.content.Context;
+import android.graphics.Rect;
+
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowInsets;
+import android.widget.FrameLayout;
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsActivity;
+import com.android.systemui.recents.RecentsActivityLaunchState;
+import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
+/**
+ * Top level layout of recents for TV. This will show the TaskStacks using a HorizontalGridView.
+ */
+public class RecentsTvView extends FrameLayout {
+
+    private static final String TAG = "RecentsTvView";
+    private static final boolean DEBUG = false;
+
+    private TaskStack mStack;
+    private TaskStackHorizontalGridView mTaskStackHorizontalView;
+    private View mEmptyView;
+    private boolean mAwaitingFirstLayout = true;
+    private Rect mSystemInsets = new Rect();
+
+
+    public RecentsTvView(Context context) {
+        this(context, null);
+    }
+
+    public RecentsTvView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public RecentsTvView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public RecentsTvView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        setWillNotDraw(false);
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
+        addView(mEmptyView);
+    }
+
+    public void setTaskStack(TaskStack stack) {
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        mStack = stack;
+
+        if (mTaskStackHorizontalView != null) {
+            mTaskStackHorizontalView.reset();
+            mTaskStackHorizontalView.setStack(stack);
+        } else {
+            mTaskStackHorizontalView = (TaskStackHorizontalGridView) findViewById(R.id.task_list);
+            mTaskStackHorizontalView.setStack(stack);
+        }
+
+
+        if (stack.getStackTaskCount() > 0) {
+            hideEmptyView();
+        } else {
+            showEmptyView();
+        }
+
+        requestLayout();
+    }
+
+    public Task getNextTaskOrTopTask(Task taskToSearch) {
+        Task returnTask = null;
+        boolean found = false;
+        if (mTaskStackHorizontalView != null) {
+            TaskStack stack = mTaskStackHorizontalView.getStack();
+            ArrayList<Task> taskList = stack.getStackTasks();
+            // Iterate the stack views and try and find the focused task
+            for (int j = taskList.size() - 1; j >= 0; --j) {
+                Task task = taskList.get(j);
+                // Return the next task in the line.
+                if (found)
+                    return task;
+                // Remember the first possible task as the top task.
+                if (returnTask == null)
+                    returnTask = task;
+                if (task == taskToSearch)
+                    found = true;
+            }
+        }
+        return returnTask;
+    }
+
+    public boolean launchFocusedTask() {
+        if (mTaskStackHorizontalView != null) {
+            Task task = mTaskStackHorizontalView.getFocusedTask();
+            if (task != null) {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                ssp.startActivityFromRecents(getContext(), task.key.id, task.title, null);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Launches the task that recents was launched from if possible */
+    public boolean launchPreviousTask() {
+        if (mTaskStackHorizontalView != null) {
+            TaskStack stack = mTaskStackHorizontalView.getStack();
+            Task task = stack.getLaunchTarget();
+            if (task != null) {
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                ssp.startActivityFromRecents(getContext(), task.key.id, task.title, null);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Launches a given task. */
+    public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
+        if (mTaskStackHorizontalView != null) {
+            // Iterate the stack views and try and find the given task.
+            List<TaskCardView> taskViews = mTaskStackHorizontalView.getTaskViews();
+            int taskViewCount = taskViews.size();
+            for (int j = 0; j < taskViewCount; j++) {
+                TaskCardView tv = taskViews.get(j);
+                if (tv.getTask() == task) {
+                    SystemServicesProxy ssp = Recents.getSystemServices();
+                    ssp.startActivityFromRecents(getContext(), task.key.id, task.title, null);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Hides the task stack and shows the empty view.
+     */
+    public void showEmptyView() {
+        mEmptyView.setVisibility(View.VISIBLE);
+        mEmptyView.bringToFront();
+    }
+
+    /**
+     * Shows the task stack and hides the empty view.
+     */
+    public void hideEmptyView() {
+        mEmptyView.setVisibility(View.INVISIBLE);
+    }
+
+    /**
+     * Returns the last known system insets.
+     */
+    public Rect getSystemInsets() {
+        return mSystemInsets;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
+        super.onAttachedToWindow();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        EventBus.getDefault().unregister(this);
+    }
+
+    /**
+     * This is called with the full size of the window since we are handling our own insets.
+     */
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (mTaskStackHorizontalView != null && mTaskStackHorizontalView.getVisibility() != GONE) {
+            mTaskStackHorizontalView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
+        }
+
+        // Layout the empty view
+        mEmptyView.layout(left, top, right, bottom);
+    }
+
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        mSystemInsets.set(insets.getSystemWindowInsets());
+        requestLayout();
+        return insets;
+    }
+
+    /**** EventBus Events ****/
+
+    public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
+        // If we are going home, cancel the previous task's window transition
+        EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
+    }
+
+    public final void onBusEvent(TaskStackUpdatedEvent event) {
+        mStack.setTasks(event.stack.computeAllTasksList(), true /* notifyStackChanges */);
+        mStack.createAffiliatedGroupings(getContext());
+    }
+
+
+    public final void onBusEvent(RecentsVisibilityChangedEvent event) {
+        if (!event.visible) {
+            // Reset the view state
+            mAwaitingFirstLayout = true;
+        }
+    }
+
+
+    public void setTaskStackViewAdapter(TaskStackHorizontalViewAdapter taskStackViewAdapter) {
+        if(mTaskStackHorizontalView != null) {
+            mTaskStackHorizontalView.setAdapter(taskStackViewAdapter);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
new file mode 100644
index 0000000..b36a228
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import com.android.systemui.R;
+import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
+import com.android.systemui.recents.model.Task;
+
+public class TaskCardView extends RelativeLayout {
+
+    private ImageView mThumbnailView;
+    private TextView mTitleTextView;
+    private TextView mContentTextView;
+    private ImageView mBadgeView;
+    private Task mTask;
+
+    private ViewFocusAnimator mViewFocusAnimator;
+
+    public TaskCardView(Context context) {
+        this(context, null);
+    }
+
+    public TaskCardView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TaskCardView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mViewFocusAnimator = new ViewFocusAnimator(this);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
+        mTitleTextView = (TextView) findViewById(R.id.card_title_text);
+        mContentTextView = (TextView) findViewById(R.id.card_content_text);
+        mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
+    }
+
+    public void init(Task task) {
+        mTask = task;
+        mThumbnailView.setImageBitmap(task.thumbnail);
+        mTitleTextView.setText(task.title);
+        mContentTextView.setText(task.contentDescription);
+        mBadgeView.setImageDrawable(task.icon);
+    }
+
+    public Task getTask() {
+        return mTask;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
new file mode 100644
index 0000000..b505d65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv.views;
+
+
+import android.support.v17.leanback.widget.HorizontalGridView;
+import android.util.AttributeSet;
+import android.content.Context;
+import android.view.View;
+import com.android.systemui.R;
+import com.android.systemui.recents.RecentsActivity;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack.TaskStackCallbacks;
+import com.android.systemui.recents.views.TaskViewAnimation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Horizontal Grid View Implementation to show the Task Stack for TV.
+ */
+public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks{
+
+    private TaskStack mStack;
+    private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
+    private Task mFocusedTask;
+
+
+    public TaskStackHorizontalGridView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
+        setItemMargin((int) getResources().getDimension(R.dimen.recents_tv_gird_card_spacing));
+        setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        super.onAttachedToWindow();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        EventBus.getDefault().unregister(this);
+    }
+    /**
+     * Resets this view for reuse.
+     */
+    public void reset() {
+        // Reset the focused task
+        resetFocusedTask(getFocusedTask());
+        requestLayout();
+    }
+
+    /**
+     * @param task - Task to reset
+     */
+    private void resetFocusedTask(Task task) {
+        if (task != null) {
+            TaskCardView tv = getChildViewForTask(task);
+            if (tv != null) {
+                tv.requestFocus();
+            }
+        }
+        mFocusedTask = null;
+    }
+
+    /**
+     * Sets the task stack.
+     * @param stack
+     */
+    public void setStack(TaskStack stack) {
+        //Set new stack
+        mStack = stack;
+        if (mStack != null) {
+            mStack.setCallbacks(this);
+        }
+        //Layout with new stack
+        requestLayout();
+    }
+
+    /**
+     * @return Returns the task stack.
+     */
+    public TaskStack getStack() {
+        return mStack;
+    }
+
+    /**
+     * @return - The focused task.
+     */
+    public Task getFocusedTask() {
+        return mFocusedTask;
+    }
+
+    /**
+     * @param task
+     * @return Child view for given task
+     */
+    public TaskCardView getChildViewForTask(Task task) {
+        List<TaskCardView> taskViews = getTaskViews();
+        int taskViewCount = taskViews.size();
+        for (int i = 0; i < taskViewCount; i++) {
+            TaskCardView tv = taskViews.get(i);
+            if (tv.getTask() == task) {
+                return tv;
+            }
+        }
+        return null;
+    }
+
+    public List<TaskCardView> getTaskViews() {
+        return mTaskViews;
+    }
+
+    @Override
+    public void onStackTaskAdded(TaskStack stack, Task newTask){
+        getAdapter().notifyItemInserted(stack.getStackTasks().indexOf(newTask));
+    }
+
+    @Override
+    public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
+            Task newFrontMostTask, TaskViewAnimation animation) {
+        getAdapter().notifyItemRemoved(stack.getStackTasks().indexOf(removedTask));
+        if (mFocusedTask == removedTask) {
+            resetFocusedTask(removedTask);
+        }
+        // If there are no remaining tasks, then just close recents
+        if (mStack.getStackTaskCount() == 0) {
+            boolean shouldFinishActivity = (mStack.getStackTaskCount() == 0);
+            if (shouldFinishActivity) {
+                EventBus.getDefault().send(new AllTaskViewsDismissedEvent());
+            }
+        }
+    }
+
+    @Override
+    public void onHistoryTaskRemoved(TaskStack stack, Task removedTask, TaskViewAnimation animation) {
+        //No history task on tv
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
new file mode 100644
index 0000000..0ee7b49
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents.tv.views;
+
+import android.app.Activity;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.systemui.R;
+import com.android.systemui.recents.model.Task;
+import android.support.v7.widget.RecyclerView;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TaskStackHorizontalViewAdapter extends
+        RecyclerView.Adapter<TaskStackHorizontalViewAdapter.ViewHolder> {
+
+    private static final String TAG = "TaskStackHorizontalViewAdapter";
+    private List<Task> mTaskList;
+
+    static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
+        private TaskCardView mTaskCardView;
+        private Task mTask;
+        public ViewHolder(View v) {
+            super(v);
+            if(v instanceof TaskCardView) {
+                mTaskCardView = (TaskCardView) v;
+            }
+        }
+
+        public void init(Task task) {
+            mTaskCardView.init(task);
+            mTask = task;
+            mTaskCardView.setOnClickListener(this);
+        }
+
+        @Override
+        public void onClick(View v) {
+            try {
+                ActivityManagerNative.getDefault().startActivityFromRecents(mTask.key.id, null);
+                ((Activity)(v.getContext())).finish();
+            } catch (Exception e) {
+                Log.e(TAG, v.getContext()
+                        .getString(R.string.recents_launch_error_message, mTask.title), e);
+            }
+
+        }
+    }
+
+    public TaskStackHorizontalViewAdapter(List tasks) {
+        mTaskList = new ArrayList<>(tasks);
+    }
+
+    public void setNewStackTasks(List tasks) {
+        mTaskList.clear();
+        mTaskList.addAll(tasks);
+        notifyDataSetChanged();
+    }
+    @Override
+    public TaskStackHorizontalViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
+            int viewType) {
+        View view = LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.recents_task_card_view, parent, false);
+        ViewHolder viewHolder = new ViewHolder(view);
+        return viewHolder;
+    }
+
+    @Override
+    public void onBindViewHolder(ViewHolder holder, int position) {
+        holder.init(mTaskList.get(position));
+    }
+
+    @Override
+    public int getItemCount() {
+        return mTaskList.size();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 5a72897..5842095 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -48,10 +48,16 @@
     @Override
     public void getOutline(View view, Outline outline) {
         outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
-        outline.setRoundRect(mClipRect.left, mClipRect.top,
-                mSourceView.getWidth() - mClipRect.right,
-                mSourceView.getHeight() - mClipRect.bottom,
-                mCornerRadius);
+        if (mCornerRadius > 0) {
+            outline.setRoundRect(mClipRect.left, mClipRect.top,
+                    mSourceView.getWidth() - mClipRect.right,
+                    mSourceView.getHeight() - mClipRect.bottom,
+                    mCornerRadius);
+        } else {
+            outline.setRect(mClipRect.left, mClipRect.top,
+                    mSourceView.getWidth() - mClipRect.right,
+                    mSourceView.getHeight() - mClipRect.bottom);
+        }
     }
 
     /** Sets the view outline alpha. */
@@ -63,6 +69,17 @@
         }
     }
 
+    /** Sets the top clip. */
+    public void setClipTop(int top) {
+        mClipRect.top = top;
+        updateClipBounds();
+    }
+
+    /** Returns the top clip. */
+    public int getClipTop() {
+        return mClipRect.top;
+    }
+
     /** Sets the bottom clip. */
     public void setClipBottom(int bottom) {
         mClipRect.bottom = bottom;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index e448101..b59ff30 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -18,9 +18,13 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Outline;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.util.ArraySet;
@@ -28,13 +32,16 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewOutlineProvider;
 import android.view.ViewPropertyAnimator;
 import android.view.WindowInsets;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 import android.widget.TextView;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivity;
@@ -43,20 +50,25 @@
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.ClearHistoryEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.HideHistoryEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.ShowHistoryEvent;
 import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
+import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
+import com.android.systemui.recents.history.RecentsHistoryView;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
@@ -78,6 +90,8 @@
 public class RecentsView extends FrameLayout {
 
     private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
+    private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
+    private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
 
     private final Handler mHandler;
 
@@ -85,12 +99,18 @@
     private TaskStackView mTaskStackView;
     private RecentsAppWidgetHostView mSearchBar;
     private TextView mHistoryButton;
+    private TextView mHistoryClearAllButton;
     private View mEmptyView;
+    private RecentsHistoryView mHistoryView;
+
     private boolean mAwaitingFirstLayout = true;
     private boolean mLastTaskLaunchedWasFreeform;
     private Rect mSystemInsets = new Rect();
     private int mDividerSize;
 
+    private ColorDrawable mBackgroundScrim = new ColorDrawable(Color.BLACK);
+    private Animator mBackgroundScrimAnimator;
+
     private RecentsTransitionHelper mTransitionHelper;
     private RecentsViewTouchHandler mTouchHandler;
 
@@ -125,17 +145,28 @@
         mTouchHandler = new RecentsViewTouchHandler(this);
         mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
 
+        final float cornerRadius = context.getResources().getDimensionPixelSize(
+                R.dimen.recents_task_view_rounded_corners_radius);
         LayoutInflater inflater = LayoutInflater.from(context);
         mHistoryButton = (TextView) inflater.inflate(R.layout.recents_history_button, this, false);
         mHistoryButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                EventBus.getDefault().send(new ShowHistoryEvent());
+                EventBus.getDefault().send(new ToggleHistoryEvent());
             }
         });
         addView(mHistoryButton);
+        mHistoryButton.setClipToOutline(true);
+        mHistoryButton.setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), cornerRadius);
+            }
+        });
         mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
         addView(mEmptyView);
+
+        setBackground(mBackgroundScrim);
     }
 
     /** Set/get the bsp root node */
@@ -160,6 +191,15 @@
             addView(mTaskStackView);
         }
 
+        // If we are already occluded by the app, then just set the default background scrim now.
+        // Otherwise, defer until the enter animation completes to animate the scrim with the
+        // tasks for the home animation.
+        if (launchState.launchedFromAppWithThumbnail || mStack.getTaskCount() == 0) {
+            mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+        } else {
+            mBackgroundScrim.setAlpha(0);
+        }
+
         // Update the top level view's visibilities
         if (stack.getTaskCount() > 0) {
             hideEmptyView();
@@ -179,6 +219,13 @@
     }
 
     /**
+     * Returns whether the history is visible or not.
+     */
+    public boolean isHistoryVisible() {
+        return mHistoryView != null && mHistoryView.isVisible();
+    }
+
+    /**
      * Returns the currently set task stack.
      */
     public TaskStack getTaskStack() {
@@ -302,13 +349,6 @@
         mHistoryButton.bringToFront();
     }
 
-    /**
-     * Returns the last known system insets.
-     */
-    public Rect getSystemInsets() {
-        return mSystemInsets;
-    }
-
     @Override
     protected void onAttachedToWindow() {
         EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
@@ -350,17 +390,28 @@
             mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
         }
 
-        // Measure the empty view
-        measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+        // Measure the empty view to the full size of the screen
+        if (mEmptyView.getVisibility() != GONE) {
+            measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+        }
 
-        // Measure the history button with the full space above the stack, but width-constrained
-        // to the stack
+        // Measure the history view
+        if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
+            measureChild(mHistoryView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+        }
+
+        // Measure the history button within the constraints of the space above the stack
         Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
         measureChild(mHistoryButton,
-                MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(historyButtonRect.height(),
-                        MeasureSpec.EXACTLY));
+                MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.AT_MOST),
+                MeasureSpec.makeMeasureSpec(historyButtonRect.height(), MeasureSpec.AT_MOST));
+        if (mHistoryClearAllButton != null && mHistoryClearAllButton.getVisibility() != GONE) {
+            measureChild(mHistoryClearAllButton,
+                    MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(historyButtonRect.height(), MeasureSpec.AT_MOST));
+        }
 
         setMeasuredDimension(width, height);
     }
@@ -387,13 +438,41 @@
         }
 
         // Layout the empty view
-        mEmptyView.layout(left, top, right, bottom);
+        if (mEmptyView.getVisibility() != GONE) {
+            mEmptyView.layout(left, top, right, bottom);
+        }
 
-        // Layout the history button left-aligned with the stack, but offset from the top of the
-        // view
+        // Layout the history view
+        if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
+            mHistoryView.layout(left, top, right, bottom);
+        }
+
+        // Layout the history button such that its drawable is start-aligned with the stack,
+        // vertically centered in the available space above the stack
         Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
-        mHistoryButton.layout(historyButtonRect.left, historyButtonRect.top,
-                historyButtonRect.right, historyButtonRect.bottom);
+        int historyLeft = isLayoutRtl()
+                ? historyButtonRect.right + mHistoryButton.getPaddingStart()
+                        - mHistoryButton.getMeasuredWidth()
+                : historyButtonRect.left - mHistoryButton.getPaddingStart();
+        int historyTop = historyButtonRect.top +
+                (historyButtonRect.height() - mHistoryButton.getMeasuredHeight()) / 2;
+        mHistoryButton.layout(historyLeft, historyTop,
+                historyLeft + mHistoryButton.getMeasuredWidth(),
+                historyTop + mHistoryButton.getMeasuredHeight());
+
+        // Layout the history clear all button such that it is end-aligned with the stack,
+        // vertically centered in the available space above the stack
+        if (mHistoryClearAllButton != null && mHistoryClearAllButton.getVisibility() != GONE) {
+            int clearAllLeft = isLayoutRtl()
+                    ? historyButtonRect.left - mHistoryClearAllButton.getPaddingStart()
+                    : historyButtonRect.right + mHistoryClearAllButton.getPaddingStart()
+                            - mHistoryClearAllButton.getMeasuredWidth();
+            int clearAllTop = historyButtonRect.top +
+                    (historyButtonRect.height() - mHistoryClearAllButton.getMeasuredHeight()) / 2;
+            mHistoryClearAllButton.layout(clearAllLeft, clearAllTop,
+                    clearAllLeft + mHistoryClearAllButton.getMeasuredWidth(),
+                    clearAllTop + mHistoryClearAllButton.getMeasuredHeight());
+        }
 
         if (mAwaitingFirstLayout) {
             mAwaitingFirstLayout = false;
@@ -462,10 +541,8 @@
         // Hide the history button
         int taskViewExitToHomeDuration = getResources().getInteger(
                 R.integer.recents_task_exit_to_home_duration);
-        hideHistoryButton(taskViewExitToHomeDuration);
-
-        // If we are going home, cancel the previous task's window transition
-        EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
+        hideHistoryButton(taskViewExitToHomeDuration, false /* translate */);
+        animateBackgroundScrim(0f, taskViewExitToHomeDuration);
     }
 
     public final void onBusEvent(DragStartEvent event) {
@@ -537,8 +614,7 @@
                                 }
                             }));
 
-            MetricsLogger.action(mContext,
-                    MetricsLogger.ACTION_WINDOW_DOCK_DRAG_DROP);
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP);
         } else {
             // Animate the overlay alpha back to 0
             updateVisibleDockRegions(null, true /* isDefaultDockState */, -1,
@@ -571,57 +647,150 @@
         animator.start();
     }
 
-    public final void onBusEvent(ShowHistoryEvent event) {
-        // Hide the history button when the history view is shown
-        hideHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
-                event.getAnimationTrigger());
-        event.addPostAnimationCallback(new Runnable() {
-            @Override
-            public void run() {
-                setAlpha(0f);
-            }
-        });
-    }
-
-    public final void onBusEvent(HideHistoryEvent event) {
-        // Show the history button when the history view is hidden
-        setAlpha(1f);
-        showHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
-                event.getAnimationTrigger());
-    }
-
-    public final void onBusEvent(ShowHistoryButtonEvent event) {
-        showHistoryButton(150);
-    }
-
-    public final void onBusEvent(HideHistoryButtonEvent event) {
-        hideHistoryButton(100);
-    }
-
     public final void onBusEvent(TaskStackUpdatedEvent event) {
         mStack.setTasks(event.stack.computeAllTasksList(), true /* notifyStackChanges */);
         mStack.createAffiliatedGroupings(getContext());
     }
 
+    public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
+        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        if (!launchState.launchedFromAppWithThumbnail && mStack.getTaskCount() > 0) {
+            int taskViewEnterFromHomeDuration = getResources().getInteger(
+                    R.integer.recents_task_enter_from_home_duration);
+            animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, taskViewEnterFromHomeDuration);
+        }
+    }
+
+    public final void onBusEvent(UpdateBackgroundScrimEvent event) {
+        animateBackgroundScrim(event.alpha, DEFAULT_UPDATE_SCRIM_DURATION);
+    }
+
+    public final void onBusEvent(ResetBackgroundScrimEvent event) {
+        animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
+    }
+
+    public final void onBusEvent(RecentsVisibilityChangedEvent event) {
+        if (!event.visible) {
+            // Reset the view state
+            mAwaitingFirstLayout = true;
+            mLastTaskLaunchedWasFreeform = false;
+            hideHistoryButton(0, false /* translate */);
+        }
+    }
+
+    public final void onBusEvent(ToggleHistoryEvent event) {
+        if (mHistoryView != null && mHistoryView.isVisible()) {
+            EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
+        } else {
+            EventBus.getDefault().send(new ShowHistoryEvent());
+        }
+    }
+
+    public final void onBusEvent(ShowHistoryEvent event) {
+        if (mHistoryView == null) {
+            LayoutInflater inflater = LayoutInflater.from(getContext());
+            mHistoryView = (RecentsHistoryView) inflater.inflate(R.layout.recents_history, this,
+                    false);
+            addView(mHistoryView);
+
+            final float cornerRadius = getResources().getDimensionPixelSize(
+                    R.dimen.recents_task_view_rounded_corners_radius);
+            mHistoryClearAllButton = (TextView) inflater.inflate(
+                    R.layout.recents_history_clear_all_button, this, false);
+            mHistoryClearAllButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    EventBus.getDefault().send(new ClearHistoryEvent());
+                }
+            });
+            mHistoryClearAllButton.setClipToOutline(true);
+            mHistoryClearAllButton.setOutlineProvider(new ViewOutlineProvider() {
+                @Override
+                public void getOutline(View view, Outline outline) {
+                    outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), cornerRadius);
+                }
+            });
+            addView(mHistoryClearAllButton);
+
+            // Since this history view is inflated by a view stub after the insets have already
+            // been applied, we have to set them ourselves initial from the insets that were last
+            // provided.
+            mHistoryView.setSystemInsets(mSystemInsets);
+            mHistoryView.setHeaderHeight(mHistoryButton.getMeasuredHeight());
+            mHistoryButton.bringToFront();
+            mHistoryClearAllButton.bringToFront();
+        }
+
+        // Animate the empty view in parallel with the history view (the task view animations are
+        // handled in TaskStackView)
+        Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
+        if (mEmptyView.getVisibility() == View.VISIBLE) {
+            int historyTransitionDuration = getResources().getInteger(
+                    R.integer.recents_history_transition_duration);
+            mEmptyView.animate()
+                    .alpha(0f)
+                    .translationY(stackRect.height() / 2)
+                    .setDuration(historyTransitionDuration)
+                    .setInterpolator(mFastOutSlowInInterpolator)
+                    .withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            mEmptyView.setVisibility(View.INVISIBLE);
+                        }
+                    })
+                    .start();
+        }
+
+        mHistoryView.show(mStack, stackRect.height(), mHistoryClearAllButton);
+    }
+
+    public final void onBusEvent(HideHistoryEvent event) {
+        // Animate the empty view in parallel with the history view (the task view animations are
+        // handled in TaskStackView)
+        Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
+        if (mStack.getTaskCount() == 0) {
+            int historyTransitionDuration = getResources().getInteger(
+                    R.integer.recents_history_transition_duration);
+            mEmptyView.setVisibility(View.VISIBLE);
+            mEmptyView.animate()
+                    .alpha(1f)
+                    .translationY(0)
+                    .setDuration(historyTransitionDuration)
+                    .setInterpolator(mFastOutSlowInInterpolator)
+                    .start();
+        }
+
+        mHistoryView.hide(event.animate, stackRect.height(), mHistoryClearAllButton);
+    }
+
+    public final void onBusEvent(ShowHistoryButtonEvent event) {
+        showHistoryButton(150, event.translate);
+    }
+
+    public final void onBusEvent(HideHistoryButtonEvent event) {
+        hideHistoryButton(100, true /* translate */);
+    }
+
     /**
      * Shows the history button.
      */
-    private void showHistoryButton(final int duration) {
-        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
-        showHistoryButton(duration, postAnimationTrigger);
-        postAnimationTrigger.flushLastDecrementRunnables();
-    }
-
-    private void showHistoryButton(final int duration,
-            final ReferenceCountedTrigger postHideHistoryAnimationTrigger) {
-        mHistoryButton.setText(getContext().getString(R.string.recents_history_label_format,
-                mStack.getHistoricalTasks().size()));
+    private void showHistoryButton(final int duration, final boolean translate) {
+        final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
         if (mHistoryButton.getVisibility() == View.INVISIBLE) {
             mHistoryButton.setVisibility(View.VISIBLE);
             mHistoryButton.setAlpha(0f);
-            postHideHistoryAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            if (translate) {
+                mHistoryButton.setTranslationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+            } else {
+                mHistoryButton.setTranslationY(0f);
+            }
+            postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
                 @Override
                 public void run() {
+                    if (translate) {
+                        mHistoryButton.animate()
+                            .translationY(0f);
+                    }
                     mHistoryButton.animate()
                             .alpha(1f)
                             .setDuration(duration)
@@ -631,34 +800,42 @@
                 }
             });
         }
+        postAnimationTrigger.flushLastDecrementRunnables();
     }
 
     /**
      * Hides the history button.
      */
-    private void hideHistoryButton(int duration) {
-        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
-        hideHistoryButton(duration, postAnimationTrigger);
+    private void hideHistoryButton(int duration, boolean translate) {
+        final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
+        hideHistoryButton(duration, translate, postAnimationTrigger);
         postAnimationTrigger.flushLastDecrementRunnables();
     }
 
-    private void hideHistoryButton(int duration,
-            final ReferenceCountedTrigger postHideStackAnimationTrigger) {
+    /**
+     * Hides the history button.
+     */
+    private void hideHistoryButton(int duration, boolean translate,
+            final ReferenceCountedTrigger postAnimationTrigger) {
         if (mHistoryButton.getVisibility() == View.VISIBLE) {
+            if (translate) {
+                mHistoryButton.animate()
+                    .translationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+            }
             mHistoryButton.animate()
                     .alpha(0f)
                     .setDuration(duration)
-                    .setInterpolator(mFastOutLinearInInterpolator)
+                    .setInterpolator(mFastOutSlowInInterpolator)
                     .withEndAction(new Runnable() {
                         @Override
                         public void run() {
                             mHistoryButton.setVisibility(View.INVISIBLE);
-                            postHideStackAnimationTrigger.decrement();
+                            postAnimationTrigger.decrement();
                         }
                     })
                     .withLayer()
                     .start();
-            postHideStackAnimationTrigger.increment();
+            postAnimationTrigger.increment();
         }
     }
 
@@ -695,11 +872,18 @@
         }
     }
 
-    public final void onBusEvent(RecentsVisibilityChangedEvent event) {
-        if (!event.visible) {
-            // Reset the view state
-            mAwaitingFirstLayout = true;
-            mLastTaskLaunchedWasFreeform = false;
-        }
+    /**
+     * Animates the background scrim to the given {@param alpha}.
+     */
+    private void animateBackgroundScrim(float alpha, int duration) {
+        Utilities.cancelAnimationWithoutCallbacks(mBackgroundScrimAnimator);
+        int alphaInt = (int) (alpha * 255);
+        mBackgroundScrimAnimator = ObjectAnimator.ofInt(mBackgroundScrim, Utilities.DRAWABLE_ALPHA,
+                mBackgroundScrim.getAlpha(), alphaInt);
+        mBackgroundScrimAnimator.setDuration(duration);
+        mBackgroundScrimAnimator.setInterpolator(alphaInt > mBackgroundScrim.getAlpha()
+                ? PhoneStatusBar.ALPHA_OUT
+                : PhoneStatusBar.ALPHA_IN);
+        mBackgroundScrimAnimator.start();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 9618f212d..2254dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -30,12 +30,9 @@
 
     Context mContext;
 
-    View mStatusBarScrimView;
     View mNavBarScrimView;
 
     boolean mHasNavBarScrim;
-    boolean mShouldAnimateStatusBarScrim;
-    boolean mHasStatusBarScrim;
     boolean mShouldAnimateNavBarScrim;
 
     int mNavBarScrimEnterDuration;
@@ -45,7 +42,6 @@
 
     public SystemBarScrimViews(Activity activity) {
         mContext = activity;
-        mStatusBarScrimView = activity.findViewById(R.id.status_bar_scrim);
         mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
         mNavBarScrimEnterDuration = activity.getResources().getInteger(
                 R.integer.recents_nav_bar_scrim_enter_duration);
@@ -59,17 +55,12 @@
      * Prepares the scrim views for animating when entering Recents. This will be called before
      * the first draw.
      */
-    public void prepareEnterRecentsAnimation(boolean hasStatusBarScrim, boolean animateStatusBarScrim,
-            boolean hasNavBarScrim, boolean animateNavBarScrim) {
-        mHasNavBarScrim = hasStatusBarScrim;
-        mShouldAnimateStatusBarScrim = animateStatusBarScrim;
-        mHasStatusBarScrim = hasNavBarScrim;
+    public void prepareEnterRecentsAnimation(boolean hasNavBarScrim, boolean animateNavBarScrim) {
+        mHasNavBarScrim = hasNavBarScrim;
         mShouldAnimateNavBarScrim = animateNavBarScrim;
 
         mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
                 View.VISIBLE : View.INVISIBLE);
-        mStatusBarScrimView.setVisibility(mHasStatusBarScrim && !mShouldAnimateStatusBarScrim ?
-                View.VISIBLE : View.INVISIBLE);
     }
 
     /**** EventBus events ****/
@@ -78,20 +69,6 @@
      * Starts animating the scrim views when entering Recents.
      */
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
-        if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
-            mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
-            mStatusBarScrimView.animate()
-                    .translationY(0)
-                    .setDuration(mNavBarScrimEnterDuration)
-                    .setInterpolator(mQuintOutInterpolator)
-                    .withStartAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            mStatusBarScrimView.setVisibility(View.VISIBLE);
-                        }
-                    })
-                    .start();
-        }
         if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
             mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
             mNavBarScrimView.animate()
@@ -115,14 +92,6 @@
     public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
         int taskViewExitToAppDuration = mContext.getResources().getInteger(
                 R.integer.recents_task_exit_to_app_duration);
-        if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
-            mStatusBarScrimView.animate()
-                    .translationY(-mStatusBarScrimView.getMeasuredHeight())
-                    .setStartDelay(0)
-                    .setDuration(taskViewExitToAppDuration)
-                    .setInterpolator(mFastOutSlowInInterpolator)
-                    .start();
-        }
         if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
             mNavBarScrimView.animate()
                     .translationY(mNavBarScrimView.getMeasuredHeight())
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index ccbb329..d550d83 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -138,7 +138,7 @@
             } else if (launchState.launchedFromHome) {
                 // Move the task view off screen (below) so we can animate it in
                 RectF bounds = new RectF(mTmpTransform.rect);
-                bounds.offset(0, offscreenY);
+                bounds.offsetTo(bounds.left, offscreenY);
                 tv.setLeftTopRightBottom((int) bounds.left, (int) bounds.top, (int) bounds.right,
                         (int) bounds.bottom);
             }
@@ -259,7 +259,7 @@
 
             stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
                     null);
-            mTmpTransform.rect.offset(0, offscreenY);
+            mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
             mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
         }
     }
@@ -346,61 +346,58 @@
     }
 
     /**
-     * Starts the animation to hide the {@link TaskView}s when the history is shown.  The history
-     * view's animation will be deferred until all the {@link TaskView}s are finished animating.
+     * Starts the animation to hide the {@link TaskView}s when the history is shown.
      */
     public void startShowHistoryAnimation(ReferenceCountedTrigger postAnimationTrigger) {
         Resources res = mStackView.getResources();
         TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
         TaskStackViewScroller stackScroller = mStackView.getScroller();
 
+        int offscreenY = stackLayout.mStackRect.bottom;
         int historyTransitionDuration = res.getInteger(
                 R.integer.recents_history_transition_duration);
+        int startDelayIncr = 16;
 
         List<TaskView> taskViews = mStackView.getTaskViews();
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
             TaskView tv = taskViews.get(i);
             Task task = tv.getTask();
-            TaskViewAnimation taskAnimation = new TaskViewAnimation(
-                    historyTransitionDuration, PhoneStatusBar.ALPHA_OUT,
+            TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+                    historyTransitionDuration, mFastOutSlowInInterpolator,
                     postAnimationTrigger.decrementOnAnimationEnd());
             postAnimationTrigger.increment();
 
             stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
                     null);
             mTmpTransform.alpha = 0f;
+            mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
             mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
         }
     }
 
     /**
-     * Starts the animation to show the {@link TaskView}s when the history is hidden.  The
-     * {@link TaskView} animations will be deferred until the history view has been animated away.
+     * Starts the animation to show the {@link TaskView}s when the history is hidden.
      */
-    public void startHideHistoryAnimation(final ReferenceCountedTrigger postAnimationTrigger) {
-        final Resources res = mStackView.getResources();
-        final TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
-        final TaskStackViewScroller stackScroller = mStackView.getScroller();
+    public void startHideHistoryAnimation() {
+        Resources res = mStackView.getResources();
+        TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
+        TaskStackViewScroller stackScroller = mStackView.getScroller();
 
-        final int historyTransitionDuration = res.getInteger(
+        int historyTransitionDuration = res.getInteger(
                 R.integer.recents_history_transition_duration);
+        int startDelayIncr = 16;
 
         List<TaskView> taskViews = mStackView.getTaskViews();
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
-            final TaskView tv = taskViews.get(i);
-            postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
-                @Override
-                public void run() {
-                    TaskViewAnimation taskAnimation = new TaskViewAnimation(
-                            historyTransitionDuration, PhoneStatusBar.ALPHA_IN);
-                    stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
-                            mTmpTransform, null);
-                    mTmpTransform.alpha = 1f;
-                    mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
-                }
-            });
+            TaskView tv = taskViews.get(i);
+            TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+                    historyTransitionDuration, mFastOutSlowInInterpolator);
+            stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
+                    mTmpTransform, null);
+            mTmpTransform.alpha = 1f;
+            mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 93849dc..bb37c04 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -354,6 +354,7 @@
         mStackBottomOffset = mSystemInsets.bottom + heightPadding;
         state.computeRects(mFreeformRect, mStackRect, taskStackBounds, widthPadding, heightPadding,
                 mStackBottomOffset);
+        // The history button will take the full un-padded header space above the stack
         mHistoryButtonRect.set(mStackRect.left, mStackRect.top - heightPadding,
                 mStackRect.right, mStackRect.top + mFocusedPeekHeight);
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 7423b78..79f6381 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -74,6 +74,7 @@
 import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
 import com.android.systemui.recents.misc.DozeTrigger;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
@@ -1117,12 +1118,19 @@
         // We can get spurious measure passes with the old bounds when docking, and since we are
         // using the current stack bounds during drag and drop, don't overwrite them until we
         // actually get new bounds
+        boolean requiresLayout = false;
         if (!taskStackBounds.equals(mStableStackBounds)) {
             mStableStackBounds.set(taskStackBounds);
             mStackBounds.set(taskStackBounds);
+            requiresLayout = true;
         }
-        mLayoutAlgorithm.setSystemInsets(systemInsets);
-        requestLayout();
+        if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) {
+            mLayoutAlgorithm.setSystemInsets(systemInsets);
+            requiresLayout = true;
+        }
+        if (requiresLayout) {
+            requestLayout();
+        }
     }
 
     /**
@@ -1235,7 +1243,7 @@
         // Update the history button visibility
         if (shouldShowHistoryButton() &&
                 mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
-            EventBus.getDefault().send(new ShowHistoryButtonEvent());
+            EventBus.getDefault().send(new ShowHistoryButtonEvent(false /* translate */));
         } else {
             EventBus.getDefault().send(new HideHistoryButtonEvent());
         }
@@ -1409,7 +1417,7 @@
         tv.onTaskBound(task);
 
         // Load the task data
-        Recents.getTaskLoader().loadTaskData(task);
+        Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
 
         // If the doze trigger has already fired, then update the state for this task view
         tv.setNoUserInteractionState();
@@ -1468,13 +1476,15 @@
             relayoutTaskViewsOnNextFrame(animation);
         }
 
-        if (shouldShowHistoryButton() &&
-                prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
-                curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
-            EventBus.getDefault().send(new ShowHistoryButtonEvent());
-        } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
-                curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
-            EventBus.getDefault().send(new HideHistoryButtonEvent());
+        if (mEnterAnimationComplete) {
+            if (shouldShowHistoryButton() &&
+                    prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+                    curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+                EventBus.getDefault().send(new ShowHistoryButtonEvent(true /* translate */));
+            } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+                    curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+                EventBus.getDefault().send(new HideHistoryButtonEvent());
+            }
         }
     }
 
@@ -1753,11 +1763,19 @@
     }
 
     public final void onBusEvent(ShowHistoryEvent event) {
-        mAnimationHelper.startShowHistoryAnimation(event.getAnimationTrigger());
+        ReferenceCountedTrigger postAnimTrigger = new ReferenceCountedTrigger();
+        postAnimTrigger.addLastDecrementRunnable(new Runnable() {
+            @Override
+            public void run() {
+                setVisibility(View.INVISIBLE);
+            }
+        });
+        mAnimationHelper.startShowHistoryAnimation(postAnimTrigger);
     }
 
     public final void onBusEvent(HideHistoryEvent event) {
-        mAnimationHelper.startHideHistoryAnimation(event.getAnimationTrigger());
+        setVisibility(View.VISIBLE);
+        mAnimationHelper.startHideHistoryAnimation();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index e9f6f39..7019444 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -215,8 +215,11 @@
             case MotionEvent.ACTION_MOVE: {
                 int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                 int y = (int) ev.getY(activePointerIndex);
+                int x = (int) ev.getX(activePointerIndex);
                 if (!mIsScrolling) {
-                    if (Math.abs(y - mDownY) > mScrollTouchSlop) {
+                    int yDiff = Math.abs(y - mDownY);
+                    int xDiff = Math.abs(x - mDownX);
+                    if (Math.abs(y - mDownY) > mScrollTouchSlop && yDiff > xDiff) {
                         mIsScrolling = true;
 
                         // Disallow parents from intercepting touch events
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
index 363ad66..74b16d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
@@ -45,6 +45,10 @@
         this(0 /* startDelay */, duration, interpolator, listener);
     }
 
+    public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator) {
+        this(startDelay, duration, interpolator, null);
+    }
+
     public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator,
             Animator.AnimatorListener listener) {
         this.startDelay = startDelay;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index d5aea9d..36760f7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -47,7 +47,6 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index de96d9d..c3a0ac9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -27,8 +27,6 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.util.AttributeSet;
-import android.util.FloatProperty;
-import android.util.Property;
 import android.view.View;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 77c27fa..d5131be 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -31,6 +31,7 @@
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 
 import java.util.ArrayList;
 
@@ -205,7 +206,7 @@
         if (!mAutomatic) {
             final int val = value + mMinimumBacklight;
             if (stopTracking) {
-                MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS, val);
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);
             }
             setBrightness(val);
             if (!tracking) {
@@ -220,7 +221,7 @@
         } else {
             final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1;
             if (stopTracking) {
-                MetricsLogger.action(mContext, MetricsLogger.ACTION_BRIGHTNESS_AUTO, value);
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS_AUTO, value);
             }
             setBrightnessAdj(adj);
             if (!tracking) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index cef4d34..4952234 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -25,6 +25,7 @@
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 
 /** A dialog that provides controls for adjusting the screen brightness. */
@@ -53,13 +54,13 @@
     protected void onStart() {
         super.onStart();
         mBrightnessController.registerCallbacks();
-        MetricsLogger.visible(this, MetricsLogger.BRIGHTNESS_DIALOG);
+        MetricsLogger.visible(this, MetricsEvent.BRIGHTNESS_DIALOG);
     }
 
     @Override
     protected void onStop() {
         super.onStop();
-        MetricsLogger.hidden(this, MetricsLogger.BRIGHTNESS_DIALOG);
+        MetricsLogger.hidden(this, MetricsEvent.BRIGHTNESS_DIALOG);
         mBrightnessController.unregisterCallbacks();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index c0e1e44..dca7fd9 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -73,8 +73,6 @@
     private static final String TAG = "DividerView";
 
     private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
-    private static final float DIM_START_FRACTION = 0.5f;
-    private static final float DIM_DAMP_FACTOR = 1.7f;
 
     /**
      * Fraction of the divider position between two snap targets to switch to the full-screen
@@ -90,6 +88,8 @@
 
     private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
             new PathInterpolator(0.5f, 1f, 0.5f, 1f);
+    private static final PathInterpolator DIM_INTERPOLATOR =
+            new PathInterpolator(.23f, .87f, .52f, -0.11f);
 
     private DividerHandleView mHandle;
     private View mBackground;
@@ -497,8 +497,8 @@
             mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
         }
         float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
-        fraction = Math.max(0,
-                Math.min((fraction / DIM_START_FRACTION - 1f) / DIM_DAMP_FACTOR, 1f));
+        fraction = Math.max(0, Math.min(fraction, 1f));
+        fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
         mWindowManagerProxy.setResizeDimLayer(fraction != 0f,
                 getStackIdForDismissTarget(mSnapAlgorithm.getClosestDismissTarget(position)),
                 fraction);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 67bb58a..24ab506 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -97,7 +97,8 @@
         @Override
         public void run() {
             try {
-                ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true);
+                ActivityManagerNative.getDefault().resizeStack(DOCKED_STACK_ID, null, true, false,
+                        false);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed to resize stack: " + e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index efa56bc..4edb976 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -81,7 +81,9 @@
 import android.widget.RemoteViews;
 import android.widget.TextView;
 import android.widget.Toast;
+
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationColorUtil;
@@ -947,7 +949,7 @@
             final int appUidF = appUid;
             settingsButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
-                    MetricsLogger.action(mContext, MetricsLogger.ACTION_NOTE_INFO);
+                    MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
                     startAppNotificationSettingsActivity(pkg, appUidF);
                 }
             });
@@ -994,7 +996,7 @@
                     return false;
                 }
 
-                MetricsLogger.action(mContext, MetricsLogger.ACTION_NOTE_CONTROLS);
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
 
                 // ensure that it's layouted but not visible until actually laid out
                 guts.setVisibility(View.INVISIBLE);
@@ -1173,7 +1175,7 @@
     }
 
     protected void toggleKeyboardShortcuts() {
-        getKeyboardShortcuts().toggleKeyboardShortcuts(mContext);
+        getKeyboardShortcuts().toggleKeyboardShortcuts();
     }
 
     protected void cancelPreloadingRecents() {
@@ -1223,10 +1225,7 @@
             final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
                     mContext.getContentResolver(),
                     Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
-            final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */,
-                    userHandle);
-            final boolean allowedByDpm = (dpmFlags
-                    & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
+            final boolean allowedByDpm = adminAllowsUnredactedNotifications(userHandle);
             final boolean allowed = allowedByUser && allowedByDpm;
             mUsersAllowingPrivateNotifications.append(userHandle, allowed);
             return allowed;
@@ -1235,6 +1234,15 @@
         return mUsersAllowingPrivateNotifications.get(userHandle);
     }
 
+    private boolean adminAllowsUnredactedNotifications(int userHandle) {
+        if (userHandle == UserHandle.USER_ALL) {
+            return true;
+        }
+        final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */,
+                    userHandle);
+        return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
+    }
+
     /**
      * Returns true if we're on a secure lockscreen and the user wants to hide "sensitive"
      * notification data. If so, private notifications should show their (possibly
@@ -1510,7 +1518,7 @@
 
     protected KeyboardShortcuts getKeyboardShortcuts() {
         if (mKeyboardShortcuts == null) {
-            mKeyboardShortcuts = new KeyboardShortcuts();
+            mKeyboardShortcuts = new KeyboardShortcuts(mContext);
         }
 
         return mKeyboardShortcuts;
@@ -2045,6 +2053,21 @@
         entry.row.resetHeight();
     }
 
+    protected void updatePublicContentView(Entry entry,
+            StatusBarNotification sbn) {
+        final RemoteViews publicContentView = entry.cachedPublicContentView;
+        if (publicContentView != null && entry.getPublicContentView() != null) {
+            final boolean disabledByPolicy =
+                    !adminAllowsUnredactedNotifications(entry.notification.getUserId());
+            publicContentView.setTextViewText(android.R.id.title,
+                    mContext.getString(disabledByPolicy
+                            ? com.android.internal.R.string.notification_hidden_by_policy_text
+                            : com.android.internal.R.string.notification_hidden_text));
+            publicContentView.reapply(sbn.getPackageContext(mContext),
+                    entry.getPublicContentView(), mOnClickHandler);
+        }
+    }
+
     protected void notifyHeadsUpScreenOff() {
         maybeEscalateHeadsUp();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index b36fb7e..25e9a7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -19,25 +19,38 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.graphics.Color;
+import android.graphics.Typeface;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Handler;
+import android.os.Looper;
+import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.KeyEvent;
 import android.view.KeyboardShortcutGroup;
 import android.view.KeyboardShortcutInfo;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
-import android.view.WindowManager;
 import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
 
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import static android.content.Context.LAYOUT_INFLATER_SERVICE;
-import static android.graphics.Color.TRANSPARENT;
+import static android.graphics.Color.WHITE;
 import static android.view.Gravity.TOP;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
 
@@ -45,33 +58,44 @@
  * Contains functionality for handling keyboard shortcuts.
  */
 public class KeyboardShortcuts {
-    private static final String TAG = "KeyboardShortcuts";
+    private static final char SYSTEM_HOME_BASE_CHARACTER = '\u2386';
+    private static final char SYSTEM_BACK_BASE_CHARACTER = '\u007F';
+    private static final char SYSTEM_RECENTS_BASE_CHARACTER = '\u0009';
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final Context mContext;
+    private final OnClickListener dialogCloseListener =  new DialogInterface.OnClickListener() {
+        public void onClick(DialogInterface dialog, int id) {
+            dismissKeyboardShortcutsDialog();
+        }
+    };
 
     private Dialog mKeyboardShortcutsDialog;
 
-    public KeyboardShortcuts() {}
+    public KeyboardShortcuts(Context context) {
+        this.mContext = context;
+    }
 
-    public void toggleKeyboardShortcuts(final Context context) {
+    public void toggleKeyboardShortcuts() {
         if (mKeyboardShortcutsDialog == null) {
-            Recents.getSystemServices().requestKeyboardShortcuts(context,
+            Recents.getSystemServices().requestKeyboardShortcuts(mContext,
                 new KeyboardShortcutsReceiver() {
                     @Override
                     public void onKeyboardShortcutsReceived(
                             final List<KeyboardShortcutGroup> result) {
                         KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
-                            context.getString(R.string.keyboard_shortcut_group_system));
+                            mContext.getString(R.string.keyboard_shortcut_group_system), true);
                         systemGroup.addItem(new KeyboardShortcutInfo(
-                            context.getString(R.string.keyboard_shortcut_group_system_home),
-                            '\u2386', KeyEvent.META_META_ON));
+                            mContext.getString(R.string.keyboard_shortcut_group_system_home),
+                            SYSTEM_HOME_BASE_CHARACTER, KeyEvent.META_META_ON));
                         systemGroup.addItem(new KeyboardShortcutInfo(
-                            context.getString(R.string.keyboard_shortcut_group_system_back),
-                            '\u007F', KeyEvent.META_META_ON));
+                            mContext.getString(R.string.keyboard_shortcut_group_system_back),
+                            SYSTEM_BACK_BASE_CHARACTER, KeyEvent.META_META_ON));
                         systemGroup.addItem(new KeyboardShortcutInfo(
-                            context.getString(R.string.keyboard_shortcut_group_system_recents),
-                            '\u0009', KeyEvent.META_ALT_ON));
+                            mContext.getString(R.string.keyboard_shortcut_group_system_recents),
+                            SYSTEM_RECENTS_BASE_CHARACTER, KeyEvent.META_ALT_ON));
                         result.add(systemGroup);
-                        Log.i(TAG, "Keyboard shortcuts received: " + String.valueOf(result));
-                        showKeyboardShortcutsDialog(context);
+                        showKeyboardShortcutsDialog(result);
                     }
                 });
         } else {
@@ -79,33 +103,6 @@
         }
     }
 
-    private void showKeyboardShortcutsDialog(Context context) {
-        // Create dialog.
-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
-                LAYOUT_INFLATER_SERVICE);
-        final View keyboardShortcutsView = inflater.inflate(
-                R.layout.keyboard_shortcuts_view, null);
-
-        populateKeyboardShortcuts(keyboardShortcutsView.findViewById(
-                R.id.keyboard_shortcuts_wrapper));
-        dialogBuilder.setView(keyboardShortcutsView);
-        mKeyboardShortcutsDialog = dialogBuilder.create();
-        mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
-
-        // Setup window.
-        Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
-        keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
-        keyboardShortcutsWindow.setBackgroundDrawable(
-                new ColorDrawable(TRANSPARENT));
-        keyboardShortcutsWindow.setGravity(TOP);
-        keyboardShortcutsView.post(new Runnable() {
-            public void run() {
-                mKeyboardShortcutsDialog.show();
-            }
-        });
-    }
-
     public void dismissKeyboardShortcutsDialog() {
         if (mKeyboardShortcutsDialog != null) {
             mKeyboardShortcutsDialog.dismiss();
@@ -113,11 +110,99 @@
         }
     }
 
-    /**
-     * @return {@code true} if the keyboard shortcuts have been successfully populated.
-     */
-    private boolean populateKeyboardShortcuts(View keyboardShortcutsLayout) {
-        // TODO: Populate shortcuts.
-        return true;
+    private void showKeyboardShortcutsDialog(
+            final List<KeyboardShortcutGroup> keyboardShortcutGroups) {
+        // Need to post on the main thread.
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                // TODO: break all this code out into a handleShowKeyboard...
+                // Might add more things posted; should consider adding a custom handler so
+                // you can send the keyboardShortcutsGroups as part of the message.
+                AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                        LAYOUT_INFLATER_SERVICE);
+                final View keyboardShortcutsView = inflater.inflate(
+                        R.layout.keyboard_shortcuts_view, null);
+                DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
+                ScrollView scrollView = (ScrollView) keyboardShortcutsView.findViewById(
+                        R.id.keyboard_shortcuts_scroll_view);
+                // TODO: find a better way to set the height.
+                scrollView.setLayoutParams(new LinearLayout.LayoutParams(
+                        LayoutParams.WRAP_CONTENT,
+                        (int) (dm.heightPixels * dm.density)));
+
+                populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById(
+                        R.id.keyboard_shortcuts_container), keyboardShortcutGroups);
+                dialogBuilder.setView(keyboardShortcutsView);
+                dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener);
+                mKeyboardShortcutsDialog = dialogBuilder.create();
+                mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
+
+                // Setup window.
+                Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
+                keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
+                keyboardShortcutsWindow.setBackgroundDrawable(
+                        mContext.getDrawable(R.color.ksh_dialog_background_color));
+                keyboardShortcutsWindow.setGravity(TOP);
+                mKeyboardShortcutsDialog.show();
+            }
+        });
+    }
+
+    private void populateKeyboardShortcuts(LinearLayout keyboardShortcutsLayout,
+            List<KeyboardShortcutGroup> keyboardShortcutGroups) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
+        for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
+            KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
+            TextView categoryTitle = (TextView) inflater.inflate(
+                    R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false);
+            categoryTitle.setText(group.getLabel());
+            categoryTitle.setTextColor(group.isSystemGroup()
+                    ? mContext.getColor(R.color.ksh_system_group_color)
+                    : mContext.getColor(R.color.ksh_application_group_color));
+            keyboardShortcutsLayout.addView(categoryTitle);
+
+            LinearLayout shortcutWrapper = (LinearLayout) inflater.inflate(
+                    R.layout.keyboard_shortcuts_wrapper, null);
+            final int itemsSize = group.getItems().size();
+            for (int j = 0; j < itemsSize; j++) {
+                KeyboardShortcutInfo info = group.getItems().get(j);
+                View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item, null);
+                TextView textView = (TextView) shortcutView
+                        .findViewById(R.id.keyboard_shortcuts_keyword);
+                textView.setText(info.getLabel());
+
+                List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
+                final int shortcutKeysSize = shortcutKeys.size();
+                for (int k = 0; k < shortcutKeysSize; k++) {
+                    String shortcutKey = shortcutKeys.get(k);
+                    TextView shortcutKeyView = (TextView) inflater.inflate(
+                            R.layout.keyboard_shortcuts_key_view, null);
+                    shortcutKeyView.setText(shortcutKey);
+                    LinearLayout shortcutItemsContainer = (LinearLayout) shortcutView
+                            .findViewById(R.id.keyboard_shortcuts_item_container);
+                    shortcutItemsContainer.addView(shortcutKeyView);
+                }
+                shortcutWrapper.addView(shortcutView);
+            }
+
+            // TODO: merge container and wrapper into one xml file - wrapper is always a child of
+            // container.
+            LinearLayout shortcutsContainer = (LinearLayout) inflater.inflate(
+                    R.layout.keyboard_shortcuts_container, null);
+            shortcutsContainer.addView(shortcutWrapper);
+            keyboardShortcutsLayout.addView(shortcutsContainer);
+        }
+    }
+
+    private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+        // TODO: fix the shortcuts. Find or build an util which can produce human readable
+        // names of the baseCharacter and the modifiers.
+        List<String> shortcutKeys = new ArrayList<>();
+        shortcutKeys.add(KeyEvent.metaStateToString(info.getModifiers()).toUpperCase());
+        shortcutKeys.add(Character.getName(info.getBaseCharacter()).toUpperCase());
+        return shortcutKeys;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 635e66d..00b9888 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -19,7 +19,6 @@
 import android.app.Notification;
 import android.app.RemoteInput;
 import android.content.Context;
-import android.graphics.Outline;
 import android.graphics.Rect;
 import android.os.Build;
 import android.service.notification.StatusBarNotification;
@@ -27,7 +26,6 @@
 import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
 
@@ -53,6 +51,7 @@
 
     private final Rect mClipBounds = new Rect();
     private final int mMinContractedHeight;
+    private final int mNotificationContentMarginEnd;
     private final OnLayoutChangeListener mLayoutUpdater = new OnLayoutChangeListener() {
         @Override
         public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -109,6 +108,8 @@
         mHybridViewManager = new HybridNotificationViewManager(getContext(), this);
         mMinContractedHeight = getResources().getDimensionPixelSize(
                 R.dimen.min_notification_layout_height);
+        mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_end);
         reset(true);
     }
 
@@ -128,6 +129,19 @@
             maxSize = MeasureSpec.getSize(heightMeasureSpec);
         }
         int maxChildHeight = 0;
+        if (mExpandedChild != null) {
+            int size = Math.min(maxSize, mNotificationMaxHeight);
+            ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
+            if (layoutParams.height >= 0) {
+                // An actual height is set
+                size = Math.min(maxSize, layoutParams.height);
+            }
+            int spec = size == Integer.MAX_VALUE
+                    ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
+                    : MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
+            mExpandedChild.measure(widthMeasureSpec, spec);
+            maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
+        }
         if (mContractedChild != null) {
             int heightSpec;
             if (shouldContractedBeFixedSize()) {
@@ -143,19 +157,9 @@
                 mContractedChild.measure(widthMeasureSpec, heightSpec);
             }
             maxChildHeight = Math.max(maxChildHeight, measuredHeight);
-        }
-        if (mExpandedChild != null) {
-            int size = Math.min(maxSize, mNotificationMaxHeight);
-            ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
-            if (layoutParams.height >= 0) {
-                // An actual height is set
-                size = Math.min(maxSize, layoutParams.height);
+            if (updateContractedHeaderWidth()) {
+                mContractedChild.measure(widthMeasureSpec, heightSpec);
             }
-            int spec = size == Integer.MAX_VALUE
-                    ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
-                    : MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
-            mExpandedChild.measure(widthMeasureSpec, spec);
-            maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
         }
         if (mHeadsUpChild != null) {
             int size = Math.min(maxSize, mHeadsUpHeight);
@@ -178,6 +182,44 @@
         setMeasuredDimension(width, ownHeight);
     }
 
+    private boolean updateContractedHeaderWidth() {
+        // We need to update the expanded and the collapsed header to have exactly the same with to
+        // have the expand buttons laid out at the same location.
+        NotificationHeaderView contractedHeader = mContractedWrapper.getNotificationHeader();
+        if (contractedHeader != null) {
+            if (mExpandedChild != null
+                    && mExpandedWrapper.getNotificationHeader() != null) {
+                NotificationHeaderView expandedHeader = mExpandedWrapper.getNotificationHeader();
+                int expandedSize = expandedHeader.getMeasuredWidth()
+                        - expandedHeader.getPaddingEnd();
+                int collapsedSize = contractedHeader.getMeasuredWidth()
+                        - expandedHeader.getPaddingEnd();
+                if (expandedSize != collapsedSize) {
+                    int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
+                    contractedHeader.setPadding(
+                            isLayoutRtl() ? paddingEnd : contractedHeader.getPaddingLeft(),
+                            contractedHeader.getPaddingTop(),
+                            isLayoutRtl() ? contractedHeader.getPaddingLeft() : paddingEnd,
+                            contractedHeader.getPaddingBottom());
+                    contractedHeader.setShowWorkBadgeAtEnd(true);
+                    return true;
+                }
+            } else {
+                int paddingEnd = mNotificationContentMarginEnd;
+                if (contractedHeader.getPaddingEnd() != paddingEnd) {
+                    contractedHeader.setPadding(
+                            isLayoutRtl() ? paddingEnd : contractedHeader.getPaddingLeft(),
+                            contractedHeader.getPaddingTop(),
+                            isLayoutRtl() ? contractedHeader.getPaddingLeft() : paddingEnd,
+                            contractedHeader.getPaddingBottom());
+                    contractedHeader.setShowWorkBadgeAtEnd(false);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     private boolean shouldContractedBeFixedSize() {
         return mBeforeN && mContractedWrapper instanceof NotificationCustomViewWrapper;
     }
@@ -460,16 +502,16 @@
         if (mDark == dark || mContractedChild == null) return;
         mDark = dark;
         dark = dark && !mShowingLegacyBackground;
-        if (mVisibleType == VISIBLE_TYPE_CONTRACTED) {
+        if (mVisibleType == VISIBLE_TYPE_CONTRACTED || !dark) {
             mContractedWrapper.setDark(dark, fade, delay);
         }
-        if (mVisibleType == VISIBLE_TYPE_EXPANDED) {
+        if (mVisibleType == VISIBLE_TYPE_EXPANDED || (mExpandedChild != null && !dark)) {
             mExpandedWrapper.setDark(dark, fade, delay);
         }
-        if (mVisibleType == VISIBLE_TYPE_HEADSUP) {
+        if (mVisibleType == VISIBLE_TYPE_HEADSUP || (mHeadsUpChild != null && !dark)) {
             mHeadsUpWrapper.setDark(dark, fade, delay);
         }
-        if (mSingleLineView != null && mVisibleType == VISIBLE_TYPE_SINGLELINE) {
+        if (mSingleLineView != null && (mVisibleType == VISIBLE_TYPE_SINGLELINE || !dark)) {
             mSingleLineView.setDark(dark, fade, delay);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index 4e3ecb1..dba7130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -170,12 +170,13 @@
             invalidate();
             return;
         }
-        area.left = Math.max(area.left, 0);
-        area.top = Math.max(area.top, 0);
-        area.right = Math.min(area.right, getWidth());
-        area.bottom = Math.min(area.bottom, getHeight());
-        mExcludedRect.set(area);
-        mHasExcludedArea = area.left < area.right && area.top < area.bottom;
+
+        int left = Math.max(area.left, 0);
+        int top = Math.max(area.top, 0);
+        int right = Math.min(area.right, getWidth());
+        int bottom = Math.min(area.bottom, getHeight());
+        mExcludedRect.set(left, top, right, bottom);
+        mHasExcludedArea = left < right && top < bottom;
         invalidate();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index bed64a3..eb30120 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -30,6 +30,7 @@
 
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -62,8 +63,8 @@
     private SimpleArrayMap<String, Integer> mFacetPackageMap
             = new SimpleArrayMap<String, Integer>();
 
-    private List<Intent> mIntents = new ArrayList<Intent>();
-    private List<Intent> mLongPressIntents = new ArrayList<Intent>();
+    private List<Intent> mIntents;
+    private List<Intent> mLongPressIntents;
 
     private List<CarNavigationButton> mNavButtons = new ArrayList<CarNavigationButton>();
 
@@ -112,16 +113,19 @@
             throw new RuntimeException("car_facet array lengths do not match");
         }
 
+        mIntents = createEmptyIntentList(icons.length());
+        mLongPressIntents = createEmptyIntentList(icons.length());
+
         for (int i = 0; i < icons.length(); i++) {
             Drawable icon = icons.getDrawable(i);
             try {
-                mIntents.add(i,
+                mIntents.set(i,
                         Intent.parseUri(intents.getString(i), Intent.URI_INTENT_SCHEME));
 
                 String longpressUri = longpressIntents.getString(i);
                 boolean hasLongpress = !longpressUri.isEmpty();
                 if (hasLongpress) {
-                    mLongPressIntents.add(i,
+                    mLongPressIntents.set(i,
                             Intent.parseUri(longpressUri, Intent.URI_INTENT_SCHEME));
                 }
 
@@ -299,4 +303,8 @@
         setCurrentFacet(index);
         startActivity(mLongPressIntents.get(index));
     }
+
+    private List<Intent> createEmptyIntentList(int size) {
+        return Arrays.asList(new Intent[size]);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
index bf291d3..81483c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
@@ -30,6 +30,8 @@
     private static Pools.SimplePool<HeaderTransformState> sInstancePool
             = new Pools.SimplePool<>(40);
     private View mExpandButton;
+    private View mWorkProfileIcon;
+    private TransformState mWorkProfileState;
 
     @Override
     public void initFrom(View view) {
@@ -37,13 +39,16 @@
         if (view instanceof NotificationHeaderView) {
             NotificationHeaderView header = (NotificationHeaderView) view;
             mExpandButton = header.getExpandButton();
+            mWorkProfileState = TransformState.obtain();
+            mWorkProfileIcon = header.getWorkProfileIcon();
+            mWorkProfileState.initFrom(mWorkProfileIcon);
         }
     }
 
     @Override
     public boolean transformViewTo(TransformState otherState, Runnable endRunnable) {
         // if the transforming notification has a header, we have ensured that it looks the same
-        // but the expand button, so lets fade just that one.
+        // but the expand button, so lets fade just that one and transform the work profile icon.
         if (!(mTransformedView instanceof NotificationHeaderView)) {
             return false;
         }
@@ -66,7 +71,7 @@
     @Override
     public void transformViewFrom(TransformState otherState) {
         // if the transforming notification has a header, we have ensured that it looks the same
-        // but the expand button, so lets fade just that one.
+        // but the expand button, so lets fade just that one and transform the work profile icon.
         if (!(mTransformedView instanceof NotificationHeaderView)) {
             return;
         }
@@ -79,10 +84,14 @@
             if (headerChild.getVisibility() == View.GONE) {
                 continue;
             }
-            if (headerChild != mExpandButton) {
-                headerChild.setVisibility(View.VISIBLE);
-            } else {
+            if (headerChild == mExpandButton) {
                 CrossFadeHelper.fadeIn(mExpandButton);
+            } else {
+                headerChild.setVisibility(View.VISIBLE);
+                if (headerChild == mWorkProfileIcon) {
+                    mWorkProfileState.animateViewFrom(
+                            ((HeaderTransformState) otherState).mWorkProfileState);
+                }
             }
         }
         return;
@@ -99,6 +108,9 @@
     @Override
     public void recycle() {
         super.recycle();
+        if (mWorkProfileState != null) {
+            mWorkProfileState.recycle();
+        }
         sInstancePool.release(this);
     }
 
@@ -106,6 +118,7 @@
     protected void reset() {
         super.reset();
         mExpandButton = null;
+        mWorkProfileState = null;
     }
 
     public void setVisible(boolean visible) {
@@ -125,6 +138,10 @@
             if (headerChild == mExpandButton) {
                 headerChild.setAlpha(visible ? 1.0f : 0.0f);
             }
+            if (headerChild == mWorkProfileIcon) {
+                headerChild.setTranslationX(0);
+                headerChild.setTranslationY(0);
+            }
         }
     }
 
@@ -144,6 +161,10 @@
             headerChild.animate().cancel();
             headerChild.setVisibility(View.VISIBLE);
             headerChild.setAlpha(1.0f);
+            if (headerChild == mWorkProfileIcon) {
+                headerChild.setTranslationX(0);
+                headerChild.setTranslationY(0);
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 97bf4b4..60c1911 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -35,6 +35,10 @@
 
     @Override
     public void setDark(boolean dark, boolean fade, long delay) {
+        if (dark == mDark) {
+            return;
+        }
+        super.setDark(dark, fade, delay);
         if (fade) {
             mInvertHelper.fade(dark, delay);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index f43a5d0..85f789c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -95,6 +95,7 @@
 
     @Override
     public void notifyContentUpdated(StatusBarNotification notification) {
+        super.notifyContentUpdated(notification);
         // Reinspect the notification.
         resolveHeaderViews();
         updateInvertHelper();
@@ -150,6 +151,10 @@
 
     @Override
     public void setDark(boolean dark, boolean fade, long delay) {
+        if (dark == mDark) {
+            return;
+        }
+        super.setDark(dark, fade, delay);
         if (fade) {
             mInvertHelper.fade(dark, delay);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 3475d13..9910dee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -172,6 +172,9 @@
 
     @Override
     public void setDark(boolean dark, boolean fade, long delay) {
+        if (dark == mDark) {
+            return;
+        }
         super.setDark(dark, fade, delay);
         setPictureGrayscale(dark, fade, delay);
         setProgressBarDark(dark, fade, delay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index a1cf07e..f50b976 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -31,6 +31,7 @@
 public abstract class NotificationViewWrapper implements TransformableView {
 
     protected final View mView;
+    protected boolean mDark;
 
     public static NotificationViewWrapper wrap(Context ctx, View v) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -56,13 +57,17 @@
      * @param fade whether to animate the transition if the mode changes
      * @param delay if fading, the delay of the animation
      */
-    public abstract void setDark(boolean dark, boolean fade, long delay);
+    public void setDark(boolean dark, boolean fade, long delay) {
+        mDark = dark;
+    }
 
     /**
      * Notifies this wrapper that the content of the view might have changed.
      * @param notification
      */
-    public void notifyContentUpdated(StatusBarNotification notification) {};
+    public void notifyContentUpdated(StatusBarNotification notification) {
+        mDark = false;
+    };
 
     /**
      * Update the appearance of the expand button.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 3e1c40a..870abb7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -286,6 +286,9 @@
     }
 
     public void setVisible(boolean visible) {
+        if (mTransformedView.getVisibility() == View.GONE) {
+            return;
+        }
         mTransformedView.animate().cancel();
         mTransformedView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
         mTransformedView.setAlpha(visible ? 1.0f : 0.0f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index 92288a3..786e64d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -27,6 +27,7 @@
 import android.view.ViewConfiguration;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.stackdivider.Divider;
@@ -218,8 +219,7 @@
                         mDivider.getView().startDragging(false /* animate */, true /* touching*/);
                     }
                     mDockWindowTouchSlopExceeded = true;
-                    MetricsLogger.action(mContext,
-                            MetricsLogger.ACTION_WINDOW_DOCK_SWIPE);
+                    MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_SWIPE);
 
                     return true;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 7395a33..6cfd715 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -14,10 +14,14 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -27,8 +31,10 @@
 import android.widget.LinearLayout;
 import android.widget.Space;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.tuner.TunerService;
 
+import java.io.File;
 import java.util.Objects;
 
 public class NavigationBarInflaterView extends FrameLayout implements TunerService.Tunable {
@@ -37,20 +43,30 @@
 
     public static final String NAV_BAR_VIEWS = "sysui_nav_bar";
 
-    private static final String MENU_IME = "menu_ime";
-    private static final String BACK = "back";
-    private static final String HOME = "home";
-    private static final String RECENT = "recent";
-    private static final String NAVSPACE = "space";
+    public static final String MENU_IME = "menu_ime";
+    public static final String BACK = "back";
+    public static final String HOME = "home";
+    public static final String RECENT = "recent";
+    public static final String NAVSPACE = "space";
+    public static final String CLIPBOARD = "clipboard";
+    public static final String KEY = "key";
 
     public static final String GRAVITY_SEPARATOR = ";";
     public static final String BUTTON_SEPARATOR = ",";
 
-    private final LayoutInflater mLayoutInflater;
-    private final LayoutInflater mLandscapeInflater;
+    public static final String SIZE_MOD_START = "[";
+    public static final String SIZE_MOD_END = "]";
 
-    private FrameLayout mRot0;
-    private FrameLayout mRot90;
+    public static final String KEY_CODE_START = "(";
+    public static final String KEY_IMAGE_DELIM = ":";
+    public static final String KEY_CODE_END = ")";
+
+    protected final LayoutInflater mLayoutInflater;
+    protected final LayoutInflater mLandscapeInflater;
+
+    protected FrameLayout mRot0;
+    protected FrameLayout mRot90;
+
     private SparseArray<ButtonDispatcher> mButtonDispatchers;
     private String mCurrentLayout;
 
@@ -72,7 +88,7 @@
         inflateLayout(getDefaultLayout());
     }
 
-    private String getDefaultLayout() {
+    protected String getDefaultLayout() {
         return mContext.getString(R.string.config_navBarLayout);
     }
 
@@ -128,9 +144,9 @@
         }
     }
 
-    private void inflateLayout(String newLayout) {
+    protected void inflateLayout(String newLayout) {
         mCurrentLayout = newLayout;
-        String[] sets = newLayout.split(GRAVITY_SEPARATOR);
+        String[] sets = newLayout.split(GRAVITY_SEPARATOR, 3);
         String[] start = sets[0].split(BUTTON_SEPARATOR);
         String[] center = sets[1].split(BUTTON_SEPARATOR);
         String[] end = sets[2].split(BUTTON_SEPARATOR);
@@ -165,6 +181,8 @@
     }
 
     private void copyToLightsout(View view, ViewGroup lightsOutParent) {
+        if (view == null) return;
+
         if (view instanceof FrameLayout) {
             // The only ViewGroup we support in here is a FrameLayout, so copy those manually.
             FrameLayout original = (FrameLayout) view;
@@ -202,40 +220,88 @@
         return new LayoutParams(layoutParams.width, layoutParams.height);
     }
 
-    private View inflateButton(String button, ViewGroup parent, boolean landscape) {
+    @Nullable
+    protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
+        LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
+        float size = extractSize(buttonSpec);
+        String button = extractButton(buttonSpec);
         View v = null;
         if (HOME.equals(button)) {
-            v = (landscape ? mLandscapeInflater : mLayoutInflater)
-                    .inflate(R.layout.home, parent, false);
+            v = inflater.inflate(R.layout.home, parent, false);
             if (landscape && isSw600Dp()) {
                 setupLandButton(v);
             }
         } else if (BACK.equals(button)) {
-            v = (landscape ? mLandscapeInflater : mLayoutInflater)
-                    .inflate(R.layout.back, parent, false);
+            v = inflater.inflate(R.layout.back, parent, false);
             if (landscape && isSw600Dp()) {
                 setupLandButton(v);
             }
         } else if (RECENT.equals(button)) {
-            v = (landscape ? mLandscapeInflater : mLayoutInflater)
-                    .inflate(R.layout.recent_apps, parent, false);
+            v = inflater.inflate(R.layout.recent_apps, parent, false);
             if (landscape && isSw600Dp()) {
                 setupLandButton(v);
             }
         } else if (MENU_IME.equals(button)) {
-            v = (landscape ? mLandscapeInflater : mLayoutInflater)
-                    .inflate(R.layout.menu_ime, parent, false);
+            v = inflater.inflate(R.layout.menu_ime, parent, false);
         } else if (NAVSPACE.equals(button)) {
-            v = (landscape ? mLandscapeInflater : mLayoutInflater)
-                    .inflate(R.layout.nav_key_space, parent, false);
+            v = inflater.inflate(R.layout.nav_key_space, parent, false);
+        } else if (CLIPBOARD.equals(button)) {
+            v = inflater.inflate(R.layout.clipboard, parent, false);
+        } else if (button.startsWith(KEY)) {
+            String uri = extractImage(button);
+            int code = extractKeycode(button);
+            v = inflater.inflate(R.layout.custom_key, parent, false);
+            ((KeyButtonView) v).setCode(code);
+            if (uri != null) {
+                ((KeyButtonView) v).loadAsync(uri);
+            }
         } else {
-            throw new IllegalArgumentException("Unknown button " + button);
+            return null;
+        }
+
+        if (size != 0) {
+            ViewGroup.LayoutParams params = v.getLayoutParams();
+            params.width = (int) (params.width * size);
         }
         parent.addView(v);
         addToDispatchers(v);
         return v;
     }
 
+    public static String extractImage(String buttonSpec) {
+        if (!buttonSpec.contains(KEY_IMAGE_DELIM)) {
+            return null;
+        }
+        final int start = buttonSpec.indexOf(KEY_IMAGE_DELIM);
+        String subStr = buttonSpec.substring(start + 1, buttonSpec.indexOf(KEY_CODE_END));
+        return subStr;
+    }
+
+    public static int extractKeycode(String buttonSpec) {
+        if (!buttonSpec.contains(KEY_CODE_START)) {
+            return 1;
+        }
+        final int start = buttonSpec.indexOf(KEY_CODE_START);
+        String subStr = buttonSpec.substring(start + 1, buttonSpec.indexOf(KEY_IMAGE_DELIM));
+        return Integer.parseInt(subStr);
+    }
+
+    public static float extractSize(String buttonSpec) {
+        if (!buttonSpec.contains(SIZE_MOD_START)) {
+            return 1;
+        }
+        final int sizeStart = buttonSpec.indexOf(SIZE_MOD_START);
+        String sizeStr = buttonSpec.substring(sizeStart + 1, buttonSpec.indexOf(SIZE_MOD_END));
+        return Float.parseFloat(sizeStr);
+    }
+
+    public static String extractButton(String buttonSpec) {
+        if (!buttonSpec.contains(SIZE_MOD_START)) {
+            return buttonSpec;
+        }
+        return buttonSpec.substring(0, buttonSpec.indexOf(SIZE_MOD_START));
+    }
+
     private void addToDispatchers(View v) {
         if (mButtonDispatchers != null) {
             final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 6fa1f5df..a6ebab3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -94,6 +94,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
@@ -752,7 +753,7 @@
         mDismissView.setOnButtonClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                MetricsLogger.action(mContext, MetricsLogger.ACTION_DISMISS_ALL_NOTES);
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_DISMISS_ALL_NOTES);
                 clearAllNotifications();
             }
         });
@@ -1122,8 +1123,7 @@
                         ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
                         initialBounds);
                 if (docked) {
-                    MetricsLogger.action(mContext,
-                            MetricsLogger.ACTION_WINDOW_DOCK_LONGPRESS);
+                    MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS);
                     return true;
                 }
             }
@@ -1138,7 +1138,7 @@
             if (shouldDisableNavbarGestures()) {
                 return false;
             }
-            MetricsLogger.action(mContext, MetricsLogger.ACTION_ASSIST_LONG_PRESS);
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_ASSIST_LONG_PRESS);
             mAssistManager.startAssist(new Bundle() /* args */);
             awakenDreams();
             if (mNavigationBarView != null) {
@@ -1373,6 +1373,9 @@
             boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey());
             boolean sensitive = (sensitiveNote && hideSensitive) || sensitivePackage;
             boolean showingPublic = sensitive && isLockscreenPublicMode();
+            if (showingPublic) {
+                updatePublicContentView(ent, ent.notification);
+            }
             ent.row.setSensitive(sensitive);
             if (ent.autoRedacted && ent.legacy) {
                 // TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 9c2159be..b8cd7fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -51,6 +51,7 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.DisplayController;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -101,6 +102,7 @@
     private final TileServices mServices;
 
     private final List<Callback> mCallbacks = new ArrayList<>();
+    private final DisplayController mDisplayController;
     private View mHeader;
 
     public QSTileHost(Context context, PhoneStatusBar statusBar,
@@ -127,6 +129,7 @@
         mSecurity = security;
         mBattery = battery;
         mIconController = iconController;
+        mDisplayController = new DisplayController(mContext);
 
         final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
                 Process.THREAD_PRIORITY_BACKGROUND);
@@ -277,6 +280,10 @@
         return mIconController;
     }
 
+    public DisplayController getDisplayController() {
+        return mDisplayController;
+    }
+
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (!TILES_SETTING.equals(key)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
index 4f33d82..fd3c96e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -174,6 +174,7 @@
         float halfW = getWidth() / 2f;
         float halfH = getHeight() / 2f;
         float halfSW = Math.min(halfH, halfW);
+        updateDrawableIfDisabled();
         if (mBitmap != null && mScale > 0) {
             int saveCount = canvas.getSaveCount();
             canvas.save();
@@ -249,22 +250,25 @@
             return;
         }
         mIsDisabled = disabled;
+        invalidate();
+    }
+
+    private void updateDrawableIfDisabled() {
         int disabledColor = getContext().getColor(R.color.qs_tile_disabled_color);
         PorterDuffColorFilter filter = new PorterDuffColorFilter(disabledColor,
                 PorterDuff.Mode.SRC_ATOP);
         if (mBitmap != null) {
-            if (disabled) {
+            if (mIsDisabled) {
                 mBitmapPaint.setColorFilter(filter);
             } else {
                 mBitmapPaint.setColorFilter(null);
             }
         } else if (mDrawable != null) {
-            if (disabled) {
+            if (mIsDisabled) {
                 mDrawable.setColorFilter(filter);
             } else {
                 mDrawable.setColorFilter(null);
             }
         }
-        invalidate();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
index 8fa9c7e..e7e2ac2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothController.java
@@ -33,6 +33,7 @@
     Collection<CachedBluetoothDevice> getDevices();
     void connect(CachedBluetoothDevice device);
     void disconnect(CachedBluetoothDevice device);
+    boolean canConfigBluetooth();
 
     public interface Callback {
         void onBluetoothStateChange(boolean enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index a04edf7..6439bea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -16,11 +16,14 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.app.ActivityManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Log;
 
 import com.android.settingslib.bluetooth.BluetoothCallback;
@@ -39,6 +42,8 @@
 
     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final LocalBluetoothManager mLocalBluetoothManager;
+    private final UserManager mUserManager;
+    private final int mCurrentUser;
 
     private boolean mEnabled;
     private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
@@ -54,6 +59,14 @@
             onBluetoothStateChanged(
                     mLocalBluetoothManager.getBluetoothAdapter().getBluetoothState());
         }
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mCurrentUser = ActivityManager.getCurrentUser();
+    }
+
+    @Override
+    public boolean canConfigBluetooth() {
+        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH,
+                UserHandle.of(mCurrentUser));
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java
new file mode 100644
index 0000000..e5d244f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DisplayController.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.provider.Settings;
+import com.android.systemui.R;
+import com.android.systemui.tuner.TunerService;
+import libcore.util.Objects;
+
+import java.util.ArrayList;
+
+public class DisplayController implements TunerService.Tunable {
+
+    public static final String COLOR_MATRIX_CUSTOM_ENABLED = "tuner_color_custom_enabled";
+    public static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values";
+
+    public static final String COLOR_STATE = "sysui_color_matrix_state";
+
+    public static final int COLOR_STATE_DISABLED = 0;
+    public static final int COLOR_STATE_ENABLED = 1;
+    public static final int COLOR_STATE_AUTO = 2;
+
+    public static final String AUTO_STRING = "auto_mode";
+    public static final String NONE_STRING = "none";
+
+    public static final int AUTO_INDEX = 2;
+    public static final int CUSTOM_INDEX = 3;
+
+    // Night mode ~= 3400 K
+    private static final float[] NIGHT_VALUES = new float[] {
+        1, 0,     0,     0,
+        0, .754f, 0,     0,
+        0, 0,     .516f, 0,
+        0, 0,     0,     1,
+    };
+    public static final float[] IDENTITY_MATRIX = new float[] {
+        1, 0, 0, 0,
+        0, 1, 0, 0,
+        0, 0, 1, 0,
+        0, 0, 0, 1,
+    };
+
+    private final ArrayList<Listener> mListeners = new ArrayList<>();
+
+    private final Context mContext;
+
+    private String mCurrentValue;
+    private boolean mListening;
+
+    public DisplayController(Context context) {
+        mContext = context;
+        TunerService.get(mContext).addTunable(this, COLOR_STATE,
+                Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX);
+    }
+
+    public void addListener(Listener listener) {
+        mListeners.add(listener);
+        listener.onCurrentMatrixChanged();
+    }
+
+    public void removeListener(Listener listener) {
+        mListeners.remove(listener);
+    }
+
+    public boolean isEnabled() {
+        return TunerService.get(mContext).getValue(COLOR_STATE, COLOR_STATE_DISABLED)
+                != COLOR_STATE_DISABLED;
+    }
+
+    public boolean isAuto() {
+        return mListening;
+    }
+
+    public void setAuto(boolean auto) {
+        TunerService.get(mContext).setValue(COLOR_STATE, auto ? COLOR_STATE_AUTO
+                : COLOR_STATE_DISABLED);
+    }
+
+    public boolean isCustomSet() {
+        return isCustomEnabled() && Objects.equal(getCurrentMatrix(), getCustomValues());
+    }
+
+    public String getCurrentMatrix() {
+        return mCurrentValue;
+    }
+
+    public String getCustomValues() {
+        return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_VALUES);
+    }
+
+    public boolean isCustomEnabled() {
+        return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_ENABLED, 0) != 0;
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX.equals(key)) {
+            mCurrentValue = newValue;
+            for (int i = 0; i < mListeners.size(); i++) {
+                mListeners.get(i).onCurrentMatrixChanged();
+            }
+        } else if (COLOR_STATE.equals(key)) {
+            final boolean listening = newValue != null
+                    && Integer.parseInt(newValue) == COLOR_STATE_AUTO;
+            if (listening && !mListening) {
+                mListening = true;
+                mContext.registerReceiver(mReceiver,
+                        new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
+                updateNightMode();
+            } else if (!listening && mListening) {
+                mListening = false;
+                mContext.unregisterReceiver(mReceiver);
+            }
+            for (int i = 0; i < mListeners.size(); i++) {
+                mListeners.get(i).onCurrentMatrixChanged();
+            }
+        }
+    }
+
+    private void updateNightMode() {
+        final int uiMode = mContext.getResources().getConfiguration().uiMode;
+        final boolean isNightMode = (uiMode & Configuration.UI_MODE_NIGHT_MASK)
+                == Configuration.UI_MODE_NIGHT_YES;
+        String value = null;
+        if (isNightMode) {
+            value = toString(NIGHT_VALUES);
+        }
+        TunerService.get(mContext).setValue(Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
+                value);
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
+                updateNightMode();
+            }
+        }
+    };
+
+    public interface Listener {
+        void onCurrentMatrixChanged();
+    }
+
+    public static String[] getColorTransforms(Context context) {
+        return new String[] {
+                NONE_STRING,
+                toString(NIGHT_VALUES),
+                AUTO_STRING, // Blank spot for auto values
+                null, // Blank spot for custom values
+        };
+    }
+
+    public static CharSequence[] getColorTitles(Context context) {
+        // TODO: Move to string array resource.
+        return new CharSequence[]{
+                context.getString(R.string.color_matrix_none),
+                context.getString(R.string.color_matrix_night),
+                context.getString(R.string.color_matrix_auto),
+                context.getString(R.string.color_matrix_custom),
+        };
+    }
+
+    public static String toString(float[] values) {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < values.length; i++) {
+            if (builder.length() != 0) {
+                builder.append(',');
+            }
+            builder.append(values[i]);
+        }
+        return builder.toString();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 7ca91a5..b036936 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -22,6 +22,7 @@
     boolean isHotspotEnabled();
     boolean isHotspotSupported();
     void setHotspotEnabled(boolean enabled);
+    boolean isTetheringAllowed();
 
     public interface Callback {
         void onHotspotChanged(boolean enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 5719f76..61d26c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -16,12 +16,15 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Log;
 
 import com.android.settingslib.TetherUtil;
@@ -39,13 +42,17 @@
     private final Receiver mReceiver = new Receiver();
     private final ConnectivityManager mConnectivityManager;
     private final Context mContext;
+    private final UserManager mUserManager;
+    private final int mCurrentUser;
 
     private int mHotspotState;
 
     public HotspotControllerImpl(Context context) {
         mContext = context;
-        mConnectivityManager = (ConnectivityManager)context.getSystemService(
+        mConnectivityManager = (ConnectivityManager) context.getSystemService(
                 Context.CONNECTIVITY_SERVICE);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mCurrentUser = ActivityManager.getCurrentUser();
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -95,6 +102,12 @@
         return TetherUtil.isTetheringSupported(mContext);
     }
 
+    @Override
+    public boolean isTetheringAllowed() {
+        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING,
+                UserHandle.of(mCurrentUser));
+    }
+
     static final class OnStartTetheringCallback extends
             ConnectivityManager.OnStartTetheringCallback {
         @Override
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 ba284c9..6e7cf19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -20,8 +20,12 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.hardware.input.InputManager;
 import android.media.AudioManager;
+import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -99,6 +103,24 @@
         setBackground(new KeyButtonRipple(context, this));
     }
 
+    public void setCode(int code) {
+        mCode = code;
+    }
+
+    public void loadAsync(String uri) {
+        new AsyncTask<String, Void, Drawable>() {
+            @Override
+            protected Drawable doInBackground(String... params) {
+                return Icon.createWithContentUri(params[0]).loadDrawable(mContext);
+            }
+
+            @Override
+            protected void onPostExecute(Drawable drawable) {
+                setImageDrawable(drawable);
+            }
+        }.execute(uri);
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 29a8981..401943e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -21,6 +21,7 @@
     boolean setLocationEnabled(boolean enabled);
     void addSettingsChangedCallback(LocationSettingsChangeCallback cb);
     void removeSettingsChangedCallback(LocationSettingsChangeCallback cb);
+    boolean isUserLocationRestricted();
 
     /**
      * A callback for change in location settings (the user has enabled/disabled location).
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 7517f97..436a40d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -52,6 +52,7 @@
 
     private AppOpsManager mAppOpsManager;
     private StatusBarManager mStatusBarManager;
+    private final int mCurrentUser;
 
     private boolean mAreActiveLocationRequests;
 
@@ -73,6 +74,7 @@
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         mStatusBarManager
                 = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
+        mCurrentUser = ActivityManager.getCurrentUser();
 
         // Examine the current location state and initialize the status view.
         updateActiveLocationRequests();
@@ -103,10 +105,6 @@
      * @return true if attempt to change setting was successful.
      */
     public boolean setLocationEnabled(boolean enabled) {
-        int currentUserId = ActivityManager.getCurrentUser();
-        if (isUserLocationRestricted(currentUserId)) {
-            return false;
-        }
         final ContentResolver cr = mContext.getContentResolver();
         // When enabling location, a user consent dialog will pop up, and the
         // setting won't be fully enabled until the user accepts the agreement.
@@ -115,7 +113,7 @@
         // QuickSettings always runs as the owner, so specifically set the settings
         // for the current foreground user.
         return Settings.Secure
-                .putIntForUser(cr, Settings.Secure.LOCATION_MODE, mode, currentUserId);
+                .putIntForUser(cr, Settings.Secure.LOCATION_MODE, mode, mCurrentUser);
     }
 
     /**
@@ -133,11 +131,10 @@
     /**
      * Returns true if the current user is restricted from using location.
      */
-    private boolean isUserLocationRestricted(int userId) {
+    public boolean isUserLocationRestricted() {
         final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        return um.hasUserRestriction(
-                UserManager.DISALLOW_SHARE_LOCATION,
-                new UserHandle(userId));
+        return um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION,
+                UserHandle.of(mCurrentUser));
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ad8e3bd..8fd4d9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -206,7 +206,8 @@
 
         // Show icon in QS when we are connected or need to show roaming.
         boolean showDataIcon = mCurrentState.dataConnected
-                || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+                || mCurrentState.iconGroup == TelephonyIcons.ROAMING
+                || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
         IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
                 getCurrentIconId(), contentDescription);
 
@@ -227,7 +228,8 @@
                         && !mCurrentState.carrierNetworkChangeMode
                         && mCurrentState.activityOut;
         showDataIcon &= mCurrentState.isDefault
-                || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+                || mCurrentState.iconGroup == TelephonyIcons.ROAMING
+                || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
         mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
@@ -385,6 +387,8 @@
             mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
         } else if (isRoaming()) {
             mCurrentState.iconGroup = TelephonyIcons.ROAMING;
+        } else if (isDataDisabled()) {
+            mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
         }
         if (isEmergencyOnly() != mCurrentState.isEmergency) {
             mCurrentState.isEmergency = isEmergencyOnly();
@@ -399,6 +403,10 @@
         notifyListenersIfNecessary();
     }
 
+    private boolean isDataDisabled() {
+        return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId());
+    }
+
     @VisibleForTesting
     void setActivity(int activity) {
         mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 83e0446..6ff8f77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -208,6 +208,8 @@
     static final int ICON_CARRIER_NETWORK_CHANGE =
             R.drawable.stat_sys_signal_carrier_network_change_animation;
 
+    static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
+
     static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte;
     static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
     static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
@@ -215,6 +217,8 @@
     static final int QS_ICON_CARRIER_NETWORK_CHANGE =
             R.drawable.ic_qs_signal_carrier_network_change_animation;
 
+    static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
+
     static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
             "CARRIER_NETWORK_CHANGE",
             TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE,
@@ -373,5 +377,20 @@
             false,
             TelephonyIcons.QS_DATA_R
             );
+
+    static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
+            "DataDisabled",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_cell_data_off,
+            TelephonyIcons.ICON_DATA_DISABLED,
+            false,
+            TelephonyIcons.QS_ICON_DATA_DISABLED
+            );
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 05d9626..f5869b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -49,7 +49,7 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.systemui.BitmapHelper;
@@ -622,7 +622,7 @@
 
     private void checkIfAddUserDisallowed(UserRecord record) {
         EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
-                UserManager.DISALLOW_ADD_USER, UserHandle.myUserId());
+                UserManager.DISALLOW_ADD_USER, ActivityManager.getCurrentUser());
         if (admin != null) {
             record.isDisabledByAdmin = true;
             record.enforcedAdmin = admin;
@@ -724,7 +724,7 @@
 
         @Override
         public int getMetricsCategory() {
-            return MetricsLogger.QS_USERDETAIL;
+            return MetricsEvent.QS_USERDETAIL;
         }
     };
 
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 d5b57ac..60dca99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1649,8 +1649,8 @@
                 bottom = Math.min(bottom, getHeight());
             }
         }
-        mBackgroundBounds.top = top;
-        mBackgroundBounds.bottom = bottom;
+        mBackgroundBounds.top = Math.max(0, top);
+        mBackgroundBounds.bottom = Math.min(getHeight(), bottom);
     }
 
     private ActivatableNotificationView getFirstPinnedHeadsUp() {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClipboardView.java b/packages/SystemUI/src/com/android/systemui/tuner/ClipboardView.java
new file mode 100644
index 0000000..63ed912
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ClipboardView.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import com.android.systemui.R;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.ClipboardManager.OnPrimaryClipChangedListener;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.DragEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+
+public class ClipboardView extends ImageView implements OnPrimaryClipChangedListener {
+
+    private static final int TARGET_COLOR = 0x4dffffff;
+    private final ClipboardManager mClipboardManager;
+    private ClipData mCurrentClip;
+
+    public ClipboardView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mClipboardManager = context.getSystemService(ClipboardManager.class);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        startListening();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        stopListening();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN && mCurrentClip != null) {
+            startPocketDrag();
+        }
+        return super.onTouchEvent(ev);
+    }
+
+    @Override
+    public boolean onDragEvent(DragEvent event) {
+        switch (event.getAction()) {
+            case DragEvent.ACTION_DRAG_ENTERED:
+                setBackgroundDragTarget(true);
+                break;
+            case DragEvent.ACTION_DROP:
+                mClipboardManager.setPrimaryClip(event.getClipData());
+            case DragEvent.ACTION_DRAG_EXITED:
+            case DragEvent.ACTION_DRAG_ENDED:
+                setBackgroundDragTarget(false);
+                break;
+        }
+        return true;
+    }
+
+    private void setBackgroundDragTarget(boolean isTarget) {
+        setBackgroundColor(isTarget ? TARGET_COLOR : 0);
+    }
+
+    public void startPocketDrag() {
+        startDragAndDrop(mCurrentClip, new View.DragShadowBuilder(this), null,
+                View.DRAG_FLAG_GLOBAL);
+    }
+
+    public void startListening() {
+        mClipboardManager.addPrimaryClipChangedListener(this);
+        onPrimaryClipChanged();
+    }
+
+    public void stopListening() {
+        mClipboardManager.removePrimaryClipChangedListener(this);
+    }
+
+    @Override
+    public void onPrimaryClipChanged() {
+        mCurrentClip = mClipboardManager.getPrimaryClip();
+        setImageResource(mCurrentClip != null
+                ? R.drawable.clipboard_full : R.drawable.clipboard_empty);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java
index 8ed1b06..dfacd03 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixFragment.java
@@ -19,6 +19,7 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
@@ -28,15 +29,15 @@
 import android.support.v7.preference.DropDownPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.Switch;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.policy.DisplayController;
 
 import java.util.Objects;
 
@@ -44,21 +45,6 @@
 
     private static final String TAG = "ColorMatrixFragment";
 
-    public static final int CUSTOM_INDEX = 2;
-
-    // Night mode ~= 3400 K
-    private static final float[] NIGHT_VALUES = new float[] {
-        1, 0,     0,     0,
-        0, .754f, 0,     0,
-        0, 0,     .516f, 0,
-        0, 0,     0,     1,
-    };
-    public static final float[] IDENTITY_MATRIX = new float[]{
-            1, 0, 0, 0,
-            0, 1, 0, 0,
-            0, 0, 1, 0,
-            0, 0, 0, 1,
-    };
     private static final long RESET_DELAY = 10000;
 
     private boolean mCustomEnabled;
@@ -67,20 +53,29 @@
     private String mCustomValues;
     private SwitchPreference mEnableCustomPreference;
     private MatrixPreference mCustomPreference;
-    private SwitchPreference mShowQs;
-    private String mTiles;
+    private int mState;
+    private Switch mSwitch;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         Context context = getContext();
-        TunerService.get(context).addTunable(this, ColorMatrixTile.COLOR_MATRIX_CUSTOM_ENABLED,
-                ColorMatrixTile.COLOR_MATRIX_CUSTOM_VALUES, QSTileHost.TILES_SETTING,
+        TunerService.get(context).addTunable(this, DisplayController.COLOR_MATRIX_CUSTOM_ENABLED,
+                DisplayController.COLOR_MATRIX_CUSTOM_VALUES, DisplayController.COLOR_STATE,
                 Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX);
     }
 
     @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View view = LayoutInflater.from(getContext()).inflate(
+                R.layout.color_matrix_settings, container, false);
+        ((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
+        return view;
+    }
+
+    @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         final Context context = getPreferenceManager().getContext();
         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(context));
@@ -88,40 +83,33 @@
         mSelectPreference = new DropDownPreference(context);
         mSelectPreference.setTitle(R.string.color_transform);
         mSelectPreference.setSummary("%s");
-        mSelectPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+        mSelectPreference.setOnPreferenceChangeListener(
+                new Preference.OnPreferenceChangeListener() {
             @Override
             public boolean onPreferenceChange(Preference preference, Object newValue) {
-                int index = Integer.parseInt((String) newValue);
+                if (Objects.equals(newValue, DisplayController.AUTO_STRING)) {
+                    Settings.Secure.putInt(context.getContentResolver(),
+                            DisplayController.COLOR_STATE,
+                            DisplayController.COLOR_STATE_AUTO);
+                    return true;
+                }
+                if (Objects.equals(newValue, DisplayController.NONE_STRING)) {
+                    Settings.Secure.putString(context.getContentResolver(),
+                            Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
+                    return true;
+                }
+                Settings.Secure.putInt(context.getContentResolver(),
+                        DisplayController.COLOR_STATE,
+                        DisplayController.COLOR_STATE_ENABLED);
+                final String value = (String) newValue;
                 Settings.Secure.putString(context.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, getValues()[index]);
+                        Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
+                        value);
                 return true;
             }
         });
         getPreferenceScreen().addPreference(mSelectPreference);
 
-        mShowQs = new SwitchPreference(context);
-        mShowQs.setTitle(R.string.color_matrix_show_qs);
-        mShowQs.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                boolean showTile = (Boolean) newValue;
-                String newTiles;
-                if (showTile) {
-                    newTiles = mTiles != null ? mTiles + "," + ColorMatrixTile.COLOR_MATRIX_SPEC
-                            : "default," + ColorMatrixTile.COLOR_MATRIX_SPEC;
-                } else {
-                    newTiles =
-                            mTiles.replace(mTiles.contains(ColorMatrixTile.COLOR_MATRIX_SPEC+ ",")
-                            ? ColorMatrixTile.COLOR_MATRIX_SPEC + ","
-                            : "," + ColorMatrixTile.COLOR_MATRIX_SPEC, "");
-                }
-                Settings.Secure.putString(context.getContentResolver(), QSTileHost.TILES_SETTING,
-                        newTiles);
-                return true;
-            }
-        });
-        getPreferenceScreen().addPreference(mShowQs);
-
         mEnableCustomPreference = new SwitchPreference(context);
         mEnableCustomPreference.setTitle(R.string.color_enable_custom);
         mEnableCustomPreference.setOnPreferenceChangeListener(
@@ -129,8 +117,12 @@
             @Override
             public boolean onPreferenceChange(Preference preference, Object newValue) {
                 boolean enabled = (Boolean) newValue;
+                if (!enabled && Objects.equals(mCurrentValue, mCustomValues)) {
+                    Settings.Secure.putString(context.getContentResolver(),
+                            Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
+                }
                 Settings.Secure.putInt(context.getContentResolver(),
-                        ColorMatrixTile.COLOR_MATRIX_CUSTOM_ENABLED, enabled ? 1 : 0);
+                        DisplayController.COLOR_MATRIX_CUSTOM_ENABLED, enabled ? 1 : 0);
                 return true;
             }
         });
@@ -141,6 +133,38 @@
     }
 
     @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        View switchBar = view.findViewById(R.id.switch_bar);
+        mSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget);
+        mSwitch.setChecked(mState != DisplayController.COLOR_STATE_DISABLED);
+        switchBar.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                int newState = mState != DisplayController.COLOR_STATE_DISABLED
+                        ? DisplayController.COLOR_STATE_DISABLED
+                        : DisplayController.COLOR_STATE_ENABLED;
+                ContentResolver contentResolver = getContext().getContentResolver();
+                if (newState == DisplayController.COLOR_STATE_DISABLED) {
+                    String tiles = Settings.Secure.getString(contentResolver,
+                            QSTileHost.TILES_SETTING);
+                    if (tiles != null) {
+                        if (tiles.contains(",colors")) {
+                            tiles = tiles.replace(",colors", "");
+                        } else if (tiles.contains("colors,")) {
+                            tiles = tiles.replace("colors,", "");
+                        }
+                        Settings.Secure.putString(contentResolver, QSTileHost.TILES_SETTING,
+                                tiles);
+                    }
+                }
+                Settings.Secure.putInt(contentResolver,
+                        DisplayController.COLOR_STATE, newState);
+            }
+        });
+    }
+
+    @Override
     public void onDestroy() {
         super.onDestroy();
         TunerService.get(getContext()).removeTunable(this);
@@ -148,20 +172,28 @@
 
     @Override
     public void onTuningChanged(String key, String newValue) {
-        if (ColorMatrixTile.COLOR_MATRIX_CUSTOM_ENABLED.equals(key)) {
+        if (DisplayController.COLOR_MATRIX_CUSTOM_ENABLED.equals(key)) {
             mCustomEnabled = newValue != null && Integer.parseInt(newValue) != 0;
             mEnableCustomPreference.setChecked(mCustomEnabled);
-            mCustomPreference.setEnabled(mCustomEnabled);
+            mCustomPreference.setEnabled(mCustomEnabled
+                    && mState != DisplayController.COLOR_STATE_DISABLED);
             updateSelectOptions();
-        } else if (ColorMatrixTile.COLOR_MATRIX_CUSTOM_VALUES.equals(key)) {
+        } else if (DisplayController.COLOR_MATRIX_CUSTOM_VALUES.equals(key)) {
             mCustomValues = newValue;
+            if (mCustomValues == null) {
+                mCustomValues = DisplayController.toString(DisplayController.IDENTITY_MATRIX);
+            }
             mCustomPreference.setValues(mCustomValues);
             updateSelectOptions();
-        } else if (QSTileHost.TILES_SETTING.equals(key)) {
-            mTiles = newValue;
-            boolean hasTile = newValue != null
-                    && newValue.contains(ColorMatrixTile.COLOR_MATRIX_SPEC);
-            mShowQs.setChecked(hasTile);
+        } else if (DisplayController.COLOR_STATE.equals(key)) {
+            mState = newValue != null ? Integer.parseInt(newValue) : 0;
+            if (mSwitch != null) {
+                mSwitch.setChecked(mState != DisplayController.COLOR_STATE_DISABLED);
+            }
+            mSelectPreference.setEnabled(mState != DisplayController.COLOR_STATE_DISABLED);
+            mEnableCustomPreference.setEnabled(mState != DisplayController.COLOR_STATE_DISABLED);
+            mCustomPreference.setEnabled(mCustomEnabled
+                    && mState != DisplayController.COLOR_STATE_DISABLED);
         } else {
             mCurrentValue = newValue;
             updateSelectOptions();
@@ -169,41 +201,38 @@
     }
 
     private void updateSelectOptions() {
-        final int N = CUSTOM_INDEX + (mCustomEnabled ? 1 : 0);
+        final int N = DisplayController.CUSTOM_INDEX + (mCustomEnabled ? 1 : 0);
         String[] values = new String[N];
-        CharSequence[] totalNames = getColorTitles(getContext());
         CharSequence[] names = new CharSequence[N];
+        CharSequence[] totalNames = DisplayController.getColorTitles(getContext());
+        String[] entries = DisplayController.getColorTransforms(getContext());
+        entries[DisplayController.CUSTOM_INDEX] = mCustomValues != null ? mCustomValues : "";
         for (int i = 0; i < N; i++) {
-            values[i] = String.valueOf(i);
+            values[i] = entries[i];
             names[i] = totalNames[i];
         }
         mSelectPreference.setEntries(names);
         mSelectPreference.setEntryValues(values);
-        String[] entries = getValues();
-        for (int i = 0; i < values.length; i++) {
-            if (Objects.equals(entries[i], mCurrentValue)) {
-                mSelectPreference.setValueIndex(i);
-                return;
-            }
+        int index = 0;
+        if (mState == DisplayController.COLOR_STATE_AUTO) {
+            index = DisplayController.AUTO_INDEX;
+        } else if (mCustomValues != null && Objects.equals(mCurrentValue, mCustomValues)) {
+            index = DisplayController.CUSTOM_INDEX;
+        } else if (Objects.equals(mCurrentValue, entries[1])) {
+            index = 1;
         }
-        mSelectPreference.setSummary(R.string.color_matrix_unknown);
+        mSelectPreference.setValueIndex(index);
+        mSelectPreference.setSummary("%s");
         return;
     }
 
-    private String[] getValues() {
-        String[] ret = getColorTransforms();
-        // Fill in custom based on tuner settings.
-        ret[CUSTOM_INDEX] = mCustomValues;
-        return ret;
-    }
-
     private void startRevertTimer() {
         getView().postDelayed(mResetColorMatrix, RESET_DELAY);
     }
 
     private void onApply() {
         Settings.Secure.putString(getContext().getContentResolver(),
-                ColorMatrixTile.COLOR_MATRIX_CUSTOM_VALUES, mCurrentValue);
+                DisplayController.COLOR_MATRIX_CUSTOM_VALUES, mCurrentValue);
         getView().removeCallbacks(mResetColorMatrix);
     }
 
@@ -212,35 +241,6 @@
         mResetColorMatrix.run();
     }
 
-    public static String[] getColorTransforms() {
-        return new String[] {
-                null,
-                toString(NIGHT_VALUES),
-                null, // Blank spot for custom values
-                null, // Unknown
-        };
-    }
-
-    public static CharSequence[] getColorTitles(Context context) {
-        return new CharSequence[] {
-                context.getString(R.string.color_matrix_none),
-                context.getString(R.string.color_matrix_night),
-                context.getString(R.string.color_matrix_custom),
-                context.getString(R.string.color_matrix_unknown),
-        };
-    }
-
-    private static String toString(float[] values) {
-        StringBuilder builder = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if (builder.length() != 0) {
-                builder.append(',');
-            }
-            builder.append(values[i]);
-        }
-        return builder.toString();
-    }
-
     private final Runnable mResetColorMatrix = new Runnable() {
         @Override
         public void run() {
@@ -259,14 +259,10 @@
         }
 
         public void setValues(String customValues) {
-            if (customValues == null) {
-                mValues = IDENTITY_MATRIX;
-            } else {
-                String[] strValues = customValues.split(",");
-                mValues = new float[strValues.length];
-                for (int i = 0; i < mValues.length; i++) {
-                    mValues[i] = Float.parseFloat(strValues[i]);
-                }
+            String[] strValues = customValues.split(",");
+            mValues = new float[strValues.length];
+            for (int i = 0; i < mValues.length; i++) {
+                mValues[i] = Float.parseFloat(strValues[i]);
             }
             notifyChanged();
         }
@@ -274,48 +270,38 @@
         @Override
         public void onBindViewHolder(PreferenceViewHolder holder) {
             super.onBindViewHolder(holder);
-            ViewGroup vg = (ViewGroup) holder.itemView.findViewById(R.id.edit_group);
-            if (mValues == null) {
-                return;
-            }
-            int childIndex = 0;
-            for (int i = 0; i < mValues.length; i++) {
-                final int index = i;
-                while (!(vg.getChildAt(childIndex) instanceof EditText)) {
-                    childIndex++;
+            bindView(holder.findViewById(R.id.r_group), 0);
+            bindView(holder.findViewById(R.id.g_group), 5);
+            bindView(holder.findViewById(R.id.b_group), 10);
+            holder.findViewById(R.id.apply).setOnClickListener(this);
+        }
+
+        private void bindView(View view, final int index) {
+            SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+            seekBar.setMax(1000);
+            seekBar.setProgress((int) (1000 * mValues[index]));
+            seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+                @Override
+                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                    mValues[index] = progress / 1000f;
                 }
-                final EditText editText = (EditText) vg.getChildAt(childIndex++);
-                editText.setText(String.valueOf(mValues[i]));
-                editText.addTextChangedListener(new TextWatcher() {
-                    @Override
-                    public void afterTextChanged(Editable s) {
-                        if (TextUtils.isEmpty(s.toString())) {
-                            return;
-                        }
-                        try {
-                            mValues[index] = Float.parseFloat(s.toString());
-                        } catch (NumberFormatException e) {
-                            mValues[index] = 0;
-                        }
-                    }
 
-                    @Override
-                    public void onTextChanged(CharSequence s, int start, int before, int count) {
-                    }
+                @Override
+                public void onStartTrackingTouch(SeekBar seekBar) {
+                }
 
-                    @Override
-                    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-                    }
-                });
-            }
-            ((Button) holder.itemView.findViewById(R.id.apply)).setOnClickListener(this);
+                @Override
+                public void onStopTrackingTouch(SeekBar seekBar) {
+                }
+            });
         }
 
         @Override
         public void onClick(View v) {
+            startRevertTimer();
             Settings.Secure.putString(getContext().getContentResolver(),
                     Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
-                    ColorMatrixFragment.toString(mValues));
+                    DisplayController.toString(mValues));
             RevertWarning.show(ColorMatrixFragment.this);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
index 1fd2352..1933c15 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
@@ -17,18 +17,20 @@
 
 import android.app.ActivityManager;
 import android.provider.Settings;
-import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
-import libcore.util.Objects;
+import com.android.systemui.statusbar.policy.DisplayController;
 
-public class ColorMatrixTile extends QSTile<QSTile.State> implements TunerService.Tunable {
+import java.util.Objects;
 
-    public static final String COLOR_MATRIX_CUSTOM_ENABLED = "tuner_color_custom_enabled";
-    public static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values";
+
+public class ColorMatrixTile extends QSTile<QSTile.State> implements DisplayController.Listener {
 
     public static final String COLOR_MATRIX_SPEC = "colors";
 
+    private final DisplayController mDisplayController;
+
     private int mIndex;
     private String mCurrentValue;
 
@@ -38,18 +40,17 @@
 
     public ColorMatrixTile(Host host) {
         super(host);
+        mDisplayController = host.getDisplayController();
     }
 
     @Override
     public void setListening(boolean listening) {
         if (listening) {
-            mValues = ColorMatrixFragment.getColorTransforms();
-            mValueTitles = ColorMatrixFragment.getColorTitles(mContext);
-            TunerService.get(mContext).addTunable(this, COLOR_MATRIX_CUSTOM_ENABLED,
-                    COLOR_MATRIX_CUSTOM_VALUES,
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX);
+            mValues = DisplayController.getColorTransforms(mContext);
+            mValueTitles = DisplayController.getColorTitles(mContext);
+            mDisplayController.addListener(this);
         } else {
-            TunerService.get(mContext).removeTunable(this);
+            mDisplayController.removeListener(this);
         }
     }
 
@@ -61,47 +62,45 @@
     @Override
     protected void handleClick() {
         mIndex++;
-        if (!mCustomEnabled && (mIndex == ColorMatrixFragment.CUSTOM_INDEX)) {
-            mIndex++;
-        }
-        if (mIndex == mValues.length - 1) {
-            mIndex = 0;
-        }
-        Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, mValues[mIndex],
-                ActivityManager.getCurrentUser());
-        refreshState();
-    }
-
-    @Override
-    public void onTuningChanged(String key, String newValue) {
-        if (COLOR_MATRIX_CUSTOM_ENABLED.equals(key)) {
-            mCustomEnabled = newValue != null && Integer.parseInt(newValue) != 0;
-        } else if (COLOR_MATRIX_CUSTOM_VALUES.equals(key)) {
-            mValues[ColorMatrixFragment.CUSTOM_INDEX] = newValue;
+        if (mIndex == DisplayController.AUTO_INDEX) {
+            mDisplayController.setAuto(true);
         } else {
-            mCurrentValue = newValue;
-        }
-        // Last value is unknown, default to that.
-        mIndex = mValues.length - 1;
-        for (int i = 0; i < mValues.length - 1; i++) {
-            if (Objects.equal(mCurrentValue, mValues[i])) {
-                mIndex = i;
-                break;
+            mDisplayController.setAuto(false);
+            if (!mDisplayController.isCustomEnabled()
+                    && (mIndex == DisplayController.CUSTOM_INDEX)) {
+                mIndex++;
             }
+            if (mIndex == mValues.length - 1) {
+                mIndex = 0;
+            }
+            Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, mValues[mIndex],
+                    ActivityManager.getCurrentUser());
         }
         refreshState();
     }
 
     @Override
     protected void handleUpdateState(State state, Object arg) {
+        if (mDisplayController.isAuto()) {
+            mIndex = DisplayController.AUTO_INDEX;
+        } else if (mDisplayController.isCustomSet()) {
+            mIndex = DisplayController.CUSTOM_INDEX;
+        } else {
+            mIndex = Objects.equals(mDisplayController.getCurrentMatrix(), mValues[1]) ? 1 : 0;
+        }
         state.icon = ResourceIcon.get(R.drawable.ic_colorize);
         state.label = mValueTitles[mIndex];
         state.contentDescription = mValueTitles[mIndex];
     }
 
     @Override
+    public void onCurrentMatrixChanged() {
+        refreshState();
+    }
+
+    @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_COLOR_MATRIX;
+        return MetricsEvent.QS_COLOR_MATRIX;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index f1de234..f801963 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -31,6 +31,7 @@
 import android.view.MenuItem;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.DemoMode;
 import com.android.systemui.R;
 
@@ -94,13 +95,13 @@
     @Override
     public void onResume() {
         super.onResume();
-        MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, true);
+        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_DEMO_MODE, true);
     }
 
     @Override
     public void onPause() {
         super.onPause();
-        MetricsLogger.visibility(getContext(), MetricsLogger.TUNER_DEMO_MODE, false);
+        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_DEMO_MODE, false);
     }
 
     @Override
@@ -131,10 +132,10 @@
                 mOnSwitch.setChecked(false);
                 stopDemoMode();
             }
-            MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ENABLED, enabled);
+            MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ENABLED, enabled);
             setGlobal(DemoMode.DEMO_MODE_ALLOWED, enabled ? 1 : 0);
         } else if (preference == mOnSwitch) {
-            MetricsLogger.action(getContext(), MetricsLogger.TUNER_DEMO_MODE_ON, enabled);
+            MetricsLogger.action(getContext(), MetricsEvent.TUNER_DEMO_MODE_ON, enabled);
             if (enabled) {
                 startDemoMode();
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/KeycodeSelectionHelper.java b/packages/SystemUI/src/com/android/systemui/tuner/KeycodeSelectionHelper.java
new file mode 100644
index 0000000..e6073ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/KeycodeSelectionHelper.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.util.Pair;
+import android.view.KeyEvent;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import com.android.systemui.R;
+
+public class KeycodeSelectionHelper {
+
+    private static final ArrayList<String> mKeycodeStrings = new ArrayList<>();
+    private static final ArrayList<Integer> mKeycodes = new ArrayList<>();
+
+    private static final String KEYCODE_STRING = "KEYCODE_";
+
+    static {
+        Class<KeyEvent> cls = KeyEvent.class;
+        for (Field field : cls.getDeclaredFields()) {
+            if (Modifier.isStatic(field.getModifiers())
+                    && field.getName().startsWith(KEYCODE_STRING)
+                    && field.getType().equals(int.class)) {
+                try {
+                    mKeycodeStrings.add(formatString(field.getName()));
+                    mKeycodes.add((Integer) field.get(null));
+                } catch (IllegalAccessException e) {
+                }
+            }
+        }
+    }
+
+    // Force the string into something somewhat readable.
+    private static String formatString(String name) {
+        StringBuilder str = new StringBuilder(name.replace(KEYCODE_STRING, "").replace("_", " ")
+                .toLowerCase());
+        for (int i = 0; i < str.length(); i++) {
+            if (i == 0 || str.charAt(i - 1) == ' ') {
+                str.setCharAt(i, Character.toUpperCase(str.charAt(i)));
+            }
+        }
+        return str.toString();
+    }
+
+    public static void showKeycodeSelect(Context context, final OnSelectionComplete listener) {
+        new AlertDialog.Builder(context)
+                .setTitle(R.string.select_keycode)
+                .setItems(mKeycodeStrings.toArray(new String[0]),
+                        new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        listener.onSelectionComplete(mKeycodes.get(which));
+                    }
+                }).show();
+    }
+
+    public static Intent getSelectImageIntent() {
+        return new Intent(Intent.ACTION_OPEN_DOCUMENT).addCategory(Intent.CATEGORY_OPENABLE)
+                .setType("image/*");
+    }
+
+    public interface OnSelectionComplete {
+        void onSelectionComplete(int code);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
new file mode 100644
index 0000000..6fba9dc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import com.android.systemui.R;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.CLIPBOARD;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.SIZE_MOD_END;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.SIZE_MOD_START;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractButton;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractSize;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.BACK;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.BUTTON_SEPARATOR;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.GRAVITY_SEPARATOR;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.HOME;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.RECENT;
+
+public class NavBarTuner extends Fragment implements TunerService.Tunable {
+
+    private static final int SAVE = Menu.FIRST + 1;
+    private static final int RESET = Menu.FIRST + 2;
+    private static final int READ_REQUEST = 42;
+
+    private static final float PREVIEW_SCALE = .95f;
+    private static final float PREVIEW_SCALE_LANDSCAPE = .75f;
+
+    private NavBarAdapter mNavBarAdapter;
+    private PreviewNavInflater mPreview;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+            Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.nav_bar_tuner, container, false);
+        inflatePreview((ViewGroup) view.findViewById(R.id.nav_preview_frame));
+        return view;
+    }
+
+    private void inflatePreview(ViewGroup view) {
+        Display display = getActivity().getWindowManager().getDefaultDisplay();
+        boolean isRotated = display.getRotation() == Surface.ROTATION_90
+                || display.getRotation() == Surface.ROTATION_270;
+
+        Configuration config = new Configuration(getContext().getResources().getConfiguration());
+        boolean isPhoneLandscape = isRotated && (config.smallestScreenWidthDp < 600);
+        final float scale = isPhoneLandscape ? PREVIEW_SCALE_LANDSCAPE : PREVIEW_SCALE;
+        config.densityDpi = (int) (config.densityDpi * scale);
+
+        mPreview = (PreviewNavInflater) LayoutInflater.from(getContext().createConfigurationContext(
+                config)).inflate(R.layout.nav_bar_tuner_inflater, view, false);
+        final ViewGroup.LayoutParams layoutParams = mPreview.getLayoutParams();
+        layoutParams.width = (int) ((isPhoneLandscape ? display.getHeight() : display.getWidth())
+                * scale);
+        // Not sure why, but the height dimen is not being scaled with the dp, set it manually
+        // for now.
+        layoutParams.height = (int) (layoutParams.height * scale);
+        if (isPhoneLandscape) {
+            int width = layoutParams.width;
+            layoutParams.width = layoutParams.height;
+            layoutParams.height = width;
+        }
+        view.addView(mPreview);
+
+        if (isRotated) {
+            mPreview.findViewById(R.id.rot0).setVisibility(View.GONE);
+            final View rot90 = mPreview.findViewById(R.id.rot90);
+            rot90.findViewById(R.id.ends_group_lightsout).setVisibility(View.GONE);
+            rot90.findViewById(R.id.center_group_lightsout).setVisibility(View.GONE);
+        } else {
+            mPreview.findViewById(R.id.rot90).setVisibility(View.GONE);
+            final View rot0 = mPreview.findViewById(R.id.rot0);
+            rot0.findViewById(R.id.ends_group_lightsout).setVisibility(View.GONE);
+            rot0.findViewById(R.id.center_group_lightsout).setVisibility(View.GONE);
+        }
+    }
+
+    private void notifyChanged() {
+        mPreview.onTuningChanged(NAV_BAR_VIEWS, mNavBarAdapter.getNavString());
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        RecyclerView recyclerView = (RecyclerView) view.findViewById(android.R.id.list);
+        final Context context = getContext();
+        recyclerView.setLayoutManager(new LinearLayoutManager(context));
+        mNavBarAdapter = new NavBarAdapter(context);
+        recyclerView.setAdapter(mNavBarAdapter);
+        recyclerView.addItemDecoration(new Dividers(context));
+        final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mNavBarAdapter.mCallbacks);
+        mNavBarAdapter.setTouchHelper(itemTouchHelper);
+        itemTouchHelper.attachToRecyclerView(recyclerView);
+
+        TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS);
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        TunerService.get(getContext()).removeTunable(this);
+    }
+
+    @Override
+    public void onTuningChanged(String key, String navLayout) {
+        if (!NAV_BAR_VIEWS.equals(key)) return;
+        Context context = getContext();
+        if (navLayout == null) {
+            navLayout = context.getString(R.string.config_navBarLayout);
+        }
+        String[] views = navLayout.split(GRAVITY_SEPARATOR);
+        String[] groups = new String[] { NavBarAdapter.START, NavBarAdapter.CENTER,
+                NavBarAdapter.END};
+        CharSequence[] groupLabels = new String[] { getString(R.string.start),
+                getString(R.string.center), getString(R.string.end) };
+        mNavBarAdapter.clear();
+        for (int i = 0; i < 3; i++) {
+            mNavBarAdapter.addButton(groups[i], groupLabels[i]);
+            for (String button : views[i].split(BUTTON_SEPARATOR)) {
+                mNavBarAdapter.addButton(button, getLabel(button, context));
+            }
+        }
+        mNavBarAdapter.addButton(NavBarAdapter.ADD, getString(R.string.add_button));
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+        // TODO: Show save button conditionally, only when there are changes.
+        menu.add(Menu.NONE, SAVE, Menu.NONE, getString(R.string.save))
+                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        menu.add(Menu.NONE, RESET, Menu.NONE, getString(R.string.reset));
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == SAVE) {
+            if (!mNavBarAdapter.hasHomeButton()) {
+                new AlertDialog.Builder(getContext())
+                        .setTitle(R.string.no_home_title)
+                        .setMessage(R.string.no_home_message)
+                        .setPositiveButton(android.R.string.ok, null)
+                        .show();
+            } else {
+                Settings.Secure.putString(getContext().getContentResolver(),
+                        NAV_BAR_VIEWS, mNavBarAdapter.getNavString());
+            }
+            return true;
+        } else if (item.getItemId() == RESET) {
+            Settings.Secure.putString(getContext().getContentResolver(),
+                    NAV_BAR_VIEWS, null);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    private static CharSequence getLabel(String button, Context context) {
+        if (button.startsWith(HOME)) {
+            return context.getString(R.string.accessibility_home);
+        } else if (button.startsWith(BACK)) {
+            return context.getString(R.string.accessibility_back);
+        } else if (button.startsWith(RECENT)) {
+            return context.getString(R.string.accessibility_recent);
+        } else if (button.startsWith(NAVSPACE)) {
+            return context.getString(R.string.space);
+        } else if (button.startsWith(MENU_IME)) {
+            return context.getString(R.string.menu_ime);
+        } else if (button.startsWith(CLIPBOARD)) {
+            return context.getString(R.string.clipboard);
+        } else if (button.startsWith(KEY)) {
+            return context.getString(R.string.keycode);
+        }
+        return button;
+    }
+
+    private static class Holder extends RecyclerView.ViewHolder {
+        private TextView title;
+
+        public Holder(View itemView) {
+            super(itemView);
+            title = (TextView) itemView.findViewById(android.R.id.title);
+        }
+    }
+
+    private static class Dividers extends RecyclerView.ItemDecoration {
+        private final Drawable mDivider;
+
+        public Dividers(Context context) {
+            TypedValue value = new TypedValue();
+            context.getTheme().resolveAttribute(android.R.attr.listDivider, value, true);
+            mDivider = context.getDrawable(value.resourceId);
+        }
+
+        @Override
+        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+            super.onDraw(c, parent, state);
+            final int left = parent.getPaddingLeft();
+            final int right = parent.getWidth() - parent.getPaddingRight();
+
+            final int childCount = parent.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                final View child = parent.getChildAt(i);
+                final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+                        .getLayoutParams();
+                final int top = child.getBottom() + params.bottomMargin;
+                final int bottom = top + mDivider.getIntrinsicHeight();
+                mDivider.setBounds(left, top, right, bottom);
+                mDivider.draw(c);
+            }
+        }
+    }
+
+    private void selectImage() {
+        startActivityForResult(KeycodeSelectionHelper.getSelectImageIntent(), READ_REQUEST);
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == READ_REQUEST && resultCode == Activity.RESULT_OK && data != null) {
+            final Uri uri = data.getData();
+            final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            getContext().getContentResolver().takePersistableUriPermission(uri, takeFlags);
+            mNavBarAdapter.onImageSelected(uri);
+        } else {
+            super.onActivityResult(requestCode, resultCode, data);
+        }
+    }
+
+    private class NavBarAdapter extends RecyclerView.Adapter<Holder>
+            implements View.OnClickListener {
+
+        private static final String START = "start";
+        private static final String CENTER = "center";
+        private static final String END = "end";
+        private static final String ADD = "add";
+
+        private static final int ADD_ID = 0;
+        private static final int BUTTON_ID = 1;
+        private static final int CATEGORY_ID = 2;
+
+        private List<String> mButtons = new ArrayList<>();
+        private List<CharSequence> mLabels = new ArrayList<>();
+        private int mCategoryLayout;
+        private int mButtonLayout;
+        private ItemTouchHelper mTouchHelper;
+
+        // Stored keycode while we wait for image selection on a KEY.
+        private int mKeycode;
+
+        public NavBarAdapter(Context context) {
+            TypedArray attrs = context.getTheme().obtainStyledAttributes(null,
+                    android.R.styleable.Preference, android.R.attr.preferenceStyle, 0);
+            mButtonLayout = attrs.getResourceId(android.R.styleable.Preference_layout, 0);
+            attrs = context.getTheme().obtainStyledAttributes(null,
+                    android.R.styleable.Preference, android.R.attr.preferenceCategoryStyle, 0);
+            mCategoryLayout = attrs.getResourceId(android.R.styleable.Preference_layout, 0);
+        }
+
+        public void setTouchHelper(ItemTouchHelper itemTouchHelper) {
+            mTouchHelper = itemTouchHelper;
+        }
+
+        public void clear() {
+            mButtons.clear();
+            mLabels.clear();
+            notifyDataSetChanged();
+        }
+
+        public void addButton(String button, CharSequence label) {
+            mButtons.add(button);
+            mLabels.add(label);
+            notifyItemInserted(mLabels.size() - 1);
+            notifyChanged();
+        }
+
+        public boolean hasHomeButton() {
+            final int N = mButtons.size();
+            for (int i = 0; i < N; i++) {
+                if (mButtons.get(i).startsWith(HOME)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public String getNavString() {
+            StringBuilder builder = new StringBuilder();
+            for (int i = 1; i < mButtons.size() - 1; i++) {
+                String button = mButtons.get(i);
+                if (button.equals(CENTER) || button.equals(END)) {
+                    if (builder.length() == 0 || builder.toString().endsWith(GRAVITY_SEPARATOR)) {
+                        // No start or center buttons, fill with a space.
+                        builder.append(NAVSPACE);
+                    }
+                    builder.append(GRAVITY_SEPARATOR);
+                    continue;
+                } else if (builder.length() != 0 && !builder.toString().endsWith(
+                        GRAVITY_SEPARATOR)) {
+                    builder.append(BUTTON_SEPARATOR);
+                }
+                builder.append(button);
+            }
+            if (builder.toString().endsWith(GRAVITY_SEPARATOR)) {
+                // No end buttons, fill with space.
+                builder.append(NAVSPACE);
+            }
+            return builder.toString();
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            String button = mButtons.get(position);
+            if (button.equals(START) || button.equals(CENTER) || button.equals(END)) {
+                return CATEGORY_ID;
+            }
+            if (button.equals(ADD)) {
+                return ADD_ID;
+            }
+            return BUTTON_ID;
+        }
+
+        @Override
+        public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
+            final Context context = parent.getContext();
+            final LayoutInflater inflater = LayoutInflater.from(context);
+            final View view = inflater.inflate(getLayoutId(viewType), parent, false);
+            if (viewType == BUTTON_ID) {
+                inflater.inflate(R.layout.nav_control_widget,
+                        (ViewGroup) view.findViewById(android.R.id.widget_frame));
+            }
+            return new Holder(view);
+        }
+
+        private int getLayoutId(int viewType) {
+            if (viewType == CATEGORY_ID) {
+                return mCategoryLayout;
+            }
+            return mButtonLayout;
+        }
+
+        @Override
+        public void onBindViewHolder(Holder holder, int position) {
+            holder.title.setText(mLabels.get(position));
+            if (holder.getItemViewType() == BUTTON_ID) {
+                bindButton(holder, position);
+            } else if (holder.getItemViewType() == ADD_ID) {
+                bindAdd(holder);
+            }
+        }
+
+        private void bindAdd(Holder holder) {
+            TypedValue value = new TypedValue();
+            final Context context = holder.itemView.getContext();
+            context.getTheme().resolveAttribute(android.R.attr.colorAccent, value, true);
+            final ImageView icon = (ImageView) holder.itemView.findViewById(android.R.id.icon);
+            icon.setImageResource(R.drawable.ic_add);
+            icon.setImageTintList(ColorStateList.valueOf(context.getColor(value.resourceId)));
+            holder.itemView.findViewById(android.R.id.summary).setVisibility(View.GONE);
+            holder.itemView.setClickable(true);
+            holder.itemView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    showAddDialog(v.getContext());
+                }
+            });
+        }
+
+        private void bindButton(final Holder holder, int position) {
+            holder.itemView.findViewById(android.R.id.icon_frame).setVisibility(View.GONE);
+            holder.itemView.findViewById(android.R.id.summary).setVisibility(View.GONE);
+            bindClick(holder.itemView.findViewById(R.id.close), holder);
+            bindClick(holder.itemView.findViewById(R.id.width), holder);
+            holder.itemView.findViewById(R.id.drag).setOnTouchListener(new View.OnTouchListener() {
+                @Override
+                public boolean onTouch(View v, MotionEvent event) {
+                    mTouchHelper.startDrag(holder);
+                    return true;
+                }
+            });
+        }
+
+        private void showAddDialog(final Context context) {
+            final String[] options = new String[] {
+                    BACK, HOME, RECENT, MENU_IME, NAVSPACE, CLIPBOARD, KEY,
+            };
+            final CharSequence[] labels = new CharSequence[options.length];
+            for (int i = 0; i < options.length; i++) {
+                labels[i] = getLabel(options[i], context);
+            }
+            new AlertDialog.Builder(context)
+                    .setTitle(R.string.select_button)
+                    .setItems(labels, new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            if (KEY.equals(options[which])) {
+                                showKeyDialogs(context);
+                            } else {
+                                int index = mButtons.size() - 1;
+                                showAddedMessage(context, options[which]);
+                                mButtons.add(index, options[which]);
+                                mLabels.add(index, labels[which]);
+
+                                notifyItemInserted(index);
+                                notifyChanged();
+                            }
+                        }
+                    }).setNegativeButton(android.R.string.cancel, null)
+                    .show();
+        }
+
+        private void onImageSelected(Uri uri) {
+            int index = mButtons.size() - 1;
+            mButtons.add(index, KEY + KEY_CODE_START + mKeycode + KEY_IMAGE_DELIM + uri.toString()
+                    + KEY_CODE_END);
+            mLabels.add(index, getLabel(KEY, getContext()));
+
+            notifyItemInserted(index);
+            notifyChanged();
+        }
+
+        private void showKeyDialogs(final Context context) {
+            final KeycodeSelectionHelper.OnSelectionComplete listener =
+                    new KeycodeSelectionHelper.OnSelectionComplete() {
+                        @Override
+                        public void onSelectionComplete(int code) {
+                            mKeycode = code;
+                            selectImage();
+                        }
+                    };
+            new AlertDialog.Builder(context)
+                    .setTitle(R.string.keycode)
+                    .setMessage(R.string.keycode_description)
+                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            KeycodeSelectionHelper.showKeycodeSelect(context, listener);
+                        }
+                    }).show();
+        }
+
+        private void showAddedMessage(Context context, String button) {
+            if (CLIPBOARD.equals(button)) {
+                new AlertDialog.Builder(context)
+                        .setTitle(R.string.clipboard)
+                        .setMessage(R.string.clipboard_description)
+                        .setPositiveButton(android.R.string.ok, null)
+                        .show();
+            }
+        }
+
+        private void bindClick(View view, Holder holder) {
+            view.setOnClickListener(this);
+            view.setTag(holder);
+        }
+
+        @Override
+        public void onClick(View v) {
+            Holder holder = (Holder) v.getTag();
+            if (v.getId() == R.id.width) {
+                showWidthDialog(holder, v.getContext());
+            } else if (v.getId() == R.id.close) {
+                int position = holder.getAdapterPosition();
+                mButtons.remove(position);
+                mLabels.remove(position);
+                notifyItemRemoved(position);
+                notifyChanged();
+            }
+        }
+
+        private void showWidthDialog(final Holder holder, Context context) {
+            final String buttonSpec = mButtons.get(holder.getAdapterPosition());
+            float amount = extractSize(buttonSpec);
+            final AlertDialog dialog = new AlertDialog.Builder(context)
+                    .setTitle(R.string.adjust_button_width)
+                    .setView(R.layout.nav_width_view)
+                    .setNegativeButton(android.R.string.cancel, null).create();
+            dialog.setButton(DialogInterface.BUTTON_POSITIVE,
+                    context.getString(android.R.string.ok),
+                    new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface d, int which) {
+                            final String button = extractButton(buttonSpec);
+                            SeekBar seekBar = (SeekBar) dialog.findViewById(R.id.seekbar);
+                            if (seekBar.getProgress() == 75) {
+                                mButtons.set(holder.getAdapterPosition(), button);
+                            } else {
+                                float amount = (seekBar.getProgress() + 25) / 100f;
+                                mButtons.set(holder.getAdapterPosition(), button
+                                        + SIZE_MOD_START + amount + SIZE_MOD_END);
+                            }
+                            notifyChanged();
+                        }
+                    });
+            dialog.show();
+            SeekBar seekBar = (SeekBar) dialog.findViewById(R.id.seekbar);
+            // Range is .25 - 1.75.
+            seekBar.setMax(150);
+            seekBar.setProgress((int) ((amount - .25f) * 100));
+        }
+
+        @Override
+        public int getItemCount() {
+            return mButtons.size();
+        }
+
+        private final ItemTouchHelper.Callback mCallbacks = new ItemTouchHelper.Callback() {
+            @Override
+            public boolean isLongPressDragEnabled() {
+                return false;
+            }
+
+            @Override
+            public boolean isItemViewSwipeEnabled() {
+                return false;
+            }
+
+            @Override
+            public int getMovementFlags(RecyclerView recyclerView,
+                    RecyclerView.ViewHolder viewHolder) {
+                if (viewHolder.getItemViewType() != BUTTON_ID) {
+                    return makeMovementFlags(0, 0);
+                }
+                int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
+                return makeMovementFlags(dragFlags, 0);
+            }
+
+            @Override
+            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
+                    RecyclerView.ViewHolder target) {
+                int from = viewHolder.getAdapterPosition();
+                int to = target.getAdapterPosition();
+                if (to == 0) {
+                    // Can't go above the top.
+                    return false;
+                }
+                move(from, to, mButtons);
+                move(from, to, mLabels);
+                notifyChanged();
+                notifyItemMoved(from, to);
+                return true;
+            }
+
+            private <T> void move(int from, int to, List<T> list) {
+                list.add(from > to ? to : to + 1, list.get(from));
+                list.remove(from > to ? from + 1 : from);
+            }
+
+            @Override
+            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
+                // Don't care.
+            }
+        };
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PreviewNavInflater.java b/packages/SystemUI/src/com/android/systemui/tuner/PreviewNavInflater.java
new file mode 100644
index 0000000..b30ca5c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PreviewNavInflater.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.tuner;
+
+import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+public class PreviewNavInflater extends NavigationBarInflaterView {
+
+    public PreviewNavInflater(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        // Immediately remove tuner listening, since this is a preview, all values will be injected
+        // manually.
+        TunerService.get(getContext()).removeTunable(this);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        // Only a preview, not interactable.
+        return true;
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (NAV_BAR_VIEWS.equals(key)) {
+            // Since this is a preview we might get a bunch of random stuff, validate before sending
+            // for inflation.
+            if (isValidLayout(newValue)) {
+                super.onTuningChanged(key, newValue);
+            }
+        } else {
+            super.onTuningChanged(key, newValue);
+        }
+    }
+
+    private boolean isValidLayout(String newValue) {
+        if (newValue == null) {
+            return true;
+        }
+        int separatorCount = 0;
+        int lastGravitySeparator = 0;
+        for (int i = 0; i < newValue.length(); i++) {
+            if (newValue.charAt(i) == GRAVITY_SEPARATOR.charAt(0)) {
+                if (i == 0 || (i - lastGravitySeparator) == 1) {
+                    return false;
+                }
+                lastGravitySeparator = i;
+                separatorCount++;
+            }
+        }
+        return separatorCount == 2 && (newValue.length() - lastGravitySeparator) != 1;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index 920ec75..f2f0382 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -24,6 +24,7 @@
 import android.util.AttributeSet;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -63,14 +64,14 @@
         if (!value) {
             // If not enabled add to blacklist.
             if (!mBlacklist.contains(getKey())) {
-                MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_DISABLE,
+                MetricsLogger.action(getContext(), MetricsEvent.TUNER_STATUS_BAR_DISABLE,
                         getKey());
                 mBlacklist.add(getKey());
                 setList(mBlacklist);
             }
         } else {
             if (mBlacklist.remove(getKey())) {
-                MetricsLogger.action(getContext(), MetricsLogger.TUNER_STATUS_BAR_ENABLE, getKey());
+                MetricsLogger.action(getContext(), MetricsEvent.TUNER_STATUS_BAR_ENABLE, getKey());
                 setList(mBlacklist);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 4173ecc..4225b48 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -30,11 +30,15 @@
         PreferenceFragment.OnPreferenceStartFragmentCallback,
         PreferenceFragment.OnPreferenceStartScreenCallback {
 
+    private static final String TAG_TUNER = "tuner";
+
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        getFragmentManager().beginTransaction().replace(R.id.content_frame, new TunerFragment())
-                .commit();
+        if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) {
+            getFragmentManager().beginTransaction().replace(R.id.content_frame, new TunerFragment(),
+                    TAG_TUNER).commit();
+        }
     }
 
     @Override
@@ -43,6 +47,7 @@
             Class<?> cls = Class.forName(pref.getFragment());
             Fragment fragment = (Fragment) cls.newInstance();
             FragmentTransaction transaction = getFragmentManager().beginTransaction();
+            setTitle(pref.getTitle());
             transaction.replace(R.id.content_frame, fragment);
             transaction.addToBackStack("PreferenceFragment");
             transaction.commit();
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index a3fe6bb..e4d7be7 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -36,6 +36,7 @@
 import android.view.MenuItem;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 
 import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
@@ -60,11 +61,16 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
         setHasOptionsMenu(true);
     }
 
     @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
+    }
+
+    @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         addPreferencesFromResource(R.xml.tuner_prefs);
 
@@ -80,11 +86,12 @@
     @Override
     public void onResume() {
         super.onResume();
+        getActivity().setTitle(R.string.system_ui_tuner);
         updateBatteryPct();
         getContext().getContentResolver().registerContentObserver(
                 System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
 
-        MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, true);
+        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, true);
     }
 
     @Override
@@ -92,7 +99,7 @@
         super.onPause();
         getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
 
-        MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false);
+        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, false);
     }
 
     @Override
@@ -141,7 +148,7 @@
         @Override
         public boolean onPreferenceChange(Preference preference, Object newValue) {
             final boolean v = (Boolean) newValue;
-            MetricsLogger.action(getContext(), MetricsLogger.TUNER_BATTERY_PERCENTAGE, v);
+            MetricsLogger.action(getContext(), MetricsEvent.TUNER_BATTERY_PERCENTAGE, v);
             System.putInt(getContext().getContentResolver(), SHOW_PERCENT_SETTING, v ? 1 : 0);
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 47a4667..abaa628 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -76,6 +76,22 @@
         mUserTracker.startTracking();
     }
 
+    public String getValue(String setting) {
+        return Settings.Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
+    }
+
+    public void setValue(String setting, String value) {
+         Settings.Secure.putStringForUser(mContentResolver, setting, value, mCurrentUser);
+    }
+
+    public int getValue(String setting, int def) {
+        return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
+    }
+
+    public void setValue(String setting, int value) {
+         Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
+    }
+
     public void addTunable(Tunable tunable, String... keys) {
         for (String key : keys) {
             addTunable(tunable, key);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index 893c939..8e0f9b8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -23,6 +23,7 @@
 import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.volume.VolumeDialogController.State;
 
 import java.util.Arrays;
@@ -111,33 +112,33 @@
             sb.append(" ");
             switch (tag) {
                 case EVENT_SHOW_DIALOG:
-                    MetricsLogger.visible(context, MetricsLogger.VOLUME_DIALOG);
+                    MetricsLogger.visible(context, MetricsEvent.VOLUME_DIALOG);
                     MetricsLogger.histogram(context, "volume_from_keyguard",
                             (Boolean) list[1] ? 1 : 0);
                     sb.append(SHOW_REASONS[(Integer) list[0]]).append(" keyguard=").append(list[1]);
                     break;
                 case EVENT_EXPAND:
-                    MetricsLogger.visibility(context, MetricsLogger.VOLUME_DIALOG_DETAILS,
+                    MetricsLogger.visibility(context, MetricsEvent.VOLUME_DIALOG_DETAILS,
                             (Boolean) list[0]);
                     sb.append(list[0]);
                     break;
                 case EVENT_DISMISS_DIALOG:
-                    MetricsLogger.hidden(context, MetricsLogger.VOLUME_DIALOG);
+                    MetricsLogger.hidden(context, MetricsEvent.VOLUME_DIALOG);
                     sb.append(DISMISS_REASONS[(Integer) list[0]]);
                     break;
                 case EVENT_ACTIVE_STREAM_CHANGED:
-                    MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_STREAM,
+                    MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_STREAM,
                             (Integer) list[0]);
                     sb.append(AudioSystem.streamToString((Integer) list[0]));
                     break;
                 case EVENT_ICON_CLICK:
-                    MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_ICON,
+                    MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_ICON,
                             (Integer) list[1]);
                     sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
                             .append(iconStateToString((Integer) list[1]));
                     break;
                 case EVENT_TOUCH_LEVEL_DONE:
-                    MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_SLIDER,
+                    MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_SLIDER,
                             (Integer) list[1]);
                     // fall through
                 case EVENT_TOUCH_LEVEL_CHANGED:
@@ -147,13 +148,13 @@
                             .append(list[1]);
                     break;
                 case EVENT_KEY:
-                    MetricsLogger.action(context, MetricsLogger.ACTION_VOLUME_KEY,
+                    MetricsLogger.action(context, MetricsEvent.ACTION_VOLUME_KEY,
                             (Integer) list[1]);
                     sb.append(AudioSystem.streamToString((Integer) list[0])).append(' ')
                             .append(list[1]);
                     break;
                 case EVENT_EXTERNAL_RINGER_MODE_CHANGED:
-                    MetricsLogger.action(context, MetricsLogger.ACTION_RINGER_MODE,
+                    MetricsLogger.action(context, MetricsEvent.ACTION_RINGER_MODE,
                             (Integer) list[0]);
                     // fall through
                 case EVENT_INTERNAL_RINGER_MODE_CHANGED:
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index b005a2b..5dc468b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -254,7 +254,7 @@
         if (D.BUG) Log.d(TAG, "updateWindowWidth dm.w=" + dm.widthPixels);
         int w = dm.widthPixels;
         final int max = mContext.getResources()
-                .getDimensionPixelSize(R.dimen.standard_notification_panel_width);
+                .getDimensionPixelSize(R.dimen.volume_dialog_panel_width);
         if (w > max) {
             w = max;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index f73ba6f..e9594a3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -51,6 +51,7 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -620,7 +621,7 @@
                         if (childTag == null || childTag == tag) continue;
                         childTag.rb.setChecked(false);
                     }
-                    MetricsLogger.action(mContext, MetricsLogger.QS_DND_CONDITION_SELECT);
+                    MetricsLogger.action(mContext, MetricsEvent.QS_DND_CONDITION_SELECT);
                     select(tag.condition);
                     announceConditionSelection(tag);
                 }
@@ -725,7 +726,7 @@
     }
 
     private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
-        MetricsLogger.action(mContext, MetricsLogger.QS_DND_TIME, up);
+        MetricsLogger.action(mContext, MetricsEvent.QS_DND_TIME, up);
         Condition newCondition = null;
         final int N = MINUTE_BUCKETS.length;
         if (mBucketIndex == -1) {
@@ -928,7 +929,7 @@
             if (value != null && mZenButtons.isShown() && isAttachedToWindow()) {
                 final int zen = (Integer) value;
                 if (fromClick) {
-                    MetricsLogger.action(mContext, MetricsLogger.QS_DND_ZEN_SELECT, zen);
+                    MetricsLogger.action(mContext, MetricsEvent.QS_DND_ZEN_SELECT, zen);
                 }
                 if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + zen);
                 final Uri realConditionId = getRealConditionId(mSessionExitCondition);
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index b7a41e2..964688b 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -17,12 +17,15 @@
 
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_JACK_FLAGS := --multi-dex native
+
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 LOCAL_PROTOC_FLAGS := -I$(LOCAL_PATH)/..
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
 
 LOCAL_AAPT_FLAGS := --auto-add-overlay \
-    --extra-packages com.android.systemui:com.android.keyguard:android.support.v14.preference:android.support.v7.preference:android.support.v7.appcompat:android.support.v7.recyclerview
+    --extra-packages com.android.systemui:com.android.keyguard:android.support.v14.preference:android.support.v7.preference:android.support.v7.appcompat:android.support.v7.recyclerview \
+    --extra-packages android.support.v17.leanback
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     $(call all-Iaidl-files-under, src) \
@@ -35,6 +38,7 @@
     frameworks/support/v14/preference/res \
     frameworks/support/v7/appcompat/res \
     frameworks/support/v7/recyclerview/res \
+    frameworks/support/v17/leanback/res \
     frameworks/base/packages/SystemUI/res \
     frameworks/base/packages/Keyguard/res
 
@@ -48,7 +52,8 @@
     android-support-v7-recyclerview \
     android-support-v7-preference \
     android-support-v7-appcompat \
-    android-support-v14-preference
+    android-support-v14-preference \
+    android-support-v17-leanback
 
 # sign this with platform cert, so this test is allowed to inject key events into
 # UI it doesn't own. This is necessary to allow screenshots to be taken
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index a71ba636..8c78a3a 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -55,12 +55,16 @@
  **/
 
 public class Allocation extends BaseObj {
+    private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
+
     Type mType;
     Bitmap mBitmap;
     int mUsage;
     Allocation mAdaptedAllocation;
     int mSize;
+    MipmapControl mMipmapControl;
 
+    long mTimeStamp = -1;
     boolean mReadAllowed = true;
     boolean mWriteAllowed = true;
     boolean mAutoPadding = false;
@@ -278,6 +282,17 @@
     }
 
     /**
+     * @hide
+     * Get the Mipmap control flag of the Allocation.
+     *
+     * @return the Mipmap control flag of the Allocation
+     *
+     */
+    public MipmapControl getMipmap() {
+        return mMipmapControl;
+    }
+
+    /**
      * Enable/Disable AutoPadding for Vec3 elements.
      * By default: Diabled.
      *
@@ -359,6 +374,11 @@
         }
     }
 
+    Allocation(long id, RenderScript rs, Type t, int usage, MipmapControl mips) {
+        this(id, rs, t, usage);
+        mMipmapControl = mips;
+    }
+
     protected void finalize() throws Throwable {
         RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
         super.finalize();
@@ -521,7 +541,7 @@
                     "Can only receive if IO_INPUT usage specified.");
             }
             mRS.validate();
-            mRS.nAllocationIoReceive(getID(mRS));
+            mTimeStamp = mRS.nAllocationIoReceive(getID(mRS));
         } finally {
             Trace.traceEnd(RenderScript.TRACE_TAG);
         }
@@ -1890,7 +1910,7 @@
             if (id == 0) {
                 throw new RSRuntimeException("Allocation creation failed.");
             }
-            return new Allocation(id, rs, type, usage);
+            return new Allocation(id, rs, type, usage, mips);
         } finally {
             Trace.traceEnd(RenderScript.TRACE_TAG);
         }
@@ -1948,7 +1968,7 @@
             if (id == 0) {
                 throw new RSRuntimeException("Allocation creation failed.");
             }
-            return new Allocation(id, rs, t, usage);
+            return new Allocation(id, rs, t, usage, MipmapControl.MIPMAP_NONE);
         } finally {
             Trace.traceEnd(RenderScript.TRACE_TAG);
         }
@@ -2037,7 +2057,7 @@
                 }
 
                 // keep a reference to the Bitmap around to prevent GC
-                Allocation alloc = new Allocation(id, rs, t, usage);
+                Allocation alloc = new Allocation(id, rs, t, usage, mips);
                 alloc.setBitmap(b);
                 return alloc;
             }
@@ -2047,14 +2067,13 @@
             if (id == 0) {
                 throw new RSRuntimeException("Load failed.");
             }
-            return new Allocation(id, rs, t, usage);
+            return new Allocation(id, rs, t, usage, mips);
         } finally {
             Trace.traceEnd(RenderScript.TRACE_TAG);
         }
     }
 
     /**
-     * @hide
      * Gets or creates a ByteBuffer that contains the raw data of the current Allocation.
      * If the Allocation is created with USAGE_IO_INPUT, the returned ByteBuffer
      * would contain the up-to-date data as READ ONLY.
@@ -2089,7 +2108,107 @@
     }
 
     /**
-     * @hide
+     * Creates a new Allocation Array with the given {@link
+     * android.renderscript.Type}, and usage flags.
+     * Note: If the input allocation is of usage: USAGE_IO_INPUT,
+     * the created Allocation will be sharing the same BufferQueue.
+     *
+     * @param rs RenderScript context
+     * @param t RenderScript type describing data layout
+     * @param usage bit field specifying how the Allocation is
+     *              utilized
+     * @param numAlloc Number of Allocations in the array.
+     * @return Allocation[]
+     */
+    public static Allocation[] createAllocations(RenderScript rs, Type t, int usage, int numAlloc) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createAllocations");
+            rs.validate();
+            if (t.getID(rs) == 0) {
+                throw new RSInvalidStateException("Bad Type");
+            }
+
+            Allocation[] mAllocationArray = new Allocation[numAlloc];
+            mAllocationArray[0] = createTyped(rs, t, usage);
+            if ((usage & USAGE_IO_INPUT) != 0) {
+                if (numAlloc > MAX_NUMBER_IO_INPUT_ALLOC) {
+                    throw new RSIllegalArgumentException("Exceeds the max number of Allocations allowed: " +
+                                                         MAX_NUMBER_IO_INPUT_ALLOC);
+                }
+                mAllocationArray[0].setupBufferQueue(numAlloc);;
+            }
+
+            for (int i=1; i<numAlloc; i++) {
+                mAllocationArray[i] = createFromAllcation(rs, mAllocationArray[0]);
+            }
+            return mAllocationArray;
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Creates a new Allocation with the given {@link
+     * android.renderscript.Allocation}. The same data layout of
+     * the input Allocation will be applied.
+     * If the input allocation is of usage: USAGE_IO_INPUT, the created
+     * Allocation will be sharing the same BufferQueue.
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param alloc RenderScript Allocation describing data layout.
+     * @return Allocation sharing the same data structure.
+     */
+    static Allocation createFromAllcation(RenderScript rs, Allocation alloc) {
+        try {
+            Trace.traceBegin(RenderScript.TRACE_TAG, "createFromAllcation");
+            rs.validate();
+            if (alloc.getID(rs) == 0) {
+                throw new RSInvalidStateException("Bad input Allocation");
+            }
+
+            Type type = alloc.getType();
+            int usage = alloc.getUsage();
+            MipmapControl mips = alloc.getMipmap();
+            long id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
+            if (id == 0) {
+                throw new RSRuntimeException("Allocation creation failed.");
+            }
+            Allocation outAlloc = new Allocation(id, rs, type, usage, mips);
+            if ((usage & USAGE_IO_INPUT) != 0) {
+                outAlloc.shareBufferQueue(alloc);
+            }
+            return outAlloc;
+        } finally {
+            Trace.traceEnd(RenderScript.TRACE_TAG);
+        }
+    }
+
+    /**
+     * Initialize BufferQueue with specified max number of buffers.
+     */
+    void setupBufferQueue(int numAlloc) {
+        mRS.validate();
+        if ((mUsage & USAGE_IO_INPUT) == 0) {
+            throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+        }
+        mRS.nAllocationSetupBufferQueue(getID(mRS), numAlloc);
+    }
+
+    /**
+     * Share the BufferQueue with another {@link #USAGE_IO_INPUT} Allocation.
+     *
+     * @param alloc Allocation to associate with allocation
+     */
+    void shareBufferQueue(Allocation alloc) {
+        mRS.validate();
+        if ((mUsage & USAGE_IO_INPUT) == 0) {
+            throw new RSInvalidStateException("Allocation is not USAGE_IO_INPUT.");
+        }
+        mGetSurfaceSurface = alloc.getSurface();
+        mRS.nAllocationShareBufferQueue(getID(mRS), alloc.getID(mRS));
+    }
+
+    /**
      * Gets the stride of the Allocation.
      * For a 2D or 3D Allocation, the raw data maybe padded so that each row of
      * the Allocation has certain alignment. The size of each row including such
@@ -2107,6 +2226,26 @@
     }
 
     /**
+     * Get the timestamp for the most recent buffer held by this Allocation.
+     * The timestamp is guaranteed to be unique and monotonically increasing.
+     * Default value: -1. The timestamp will be updated after each {@link
+     * #ioReceive ioReceive()} call.
+     *
+     * It can be used to identify the images by comparing the unique timestamps
+     * when used with {@link android.hardware.camera2} APIs.
+     * Example steps:
+     *   1. Save {@link android.hardware.camera2.TotalCaptureResult} when the
+     *      capture is completed.
+     *   2. Get the timestamp after {@link #ioReceive ioReceive()} call.
+     *   3. Comparing totalCaptureResult.get(CaptureResult.SENSOR_TIMESTAMP) with
+     *      alloc.getTimeStamp().
+     * @return long Timestamp associated with the buffer held by the Allocation.
+     */
+    public long getTimeStamp() {
+        return mTimeStamp;
+    }
+
+    /**
      * Returns the handle to a raw buffer that is being managed by the screen
      * compositor. This operation is only valid for Allocations with {@link
      * #USAGE_IO_INPUT}.
@@ -2210,7 +2349,7 @@
         if(id == 0) {
             throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
         }
-        return new Allocation(id, rs, t, usage);
+        return new Allocation(id, rs, t, usage, mips);
     }
 
     /**
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 4788223..51fc7dd 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -484,7 +484,6 @@
         rsnAllocationCopyToBitmap(mContext, alloc, bmp);
     }
 
-
     native void rsnAllocationSyncAll(long con, long alloc, int src);
     synchronized void nAllocationSyncAll(long alloc, int src) {
         validate();
@@ -497,6 +496,16 @@
         return rsnAllocationGetByteBuffer(mContext, alloc, stride, xBytesSize, dimY, dimZ);
     }
 
+    native void rsnAllocationSetupBufferQueue(long con, long alloc, int numAlloc);
+    synchronized void nAllocationSetupBufferQueue(long alloc, int numAlloc) {
+        validate();
+        rsnAllocationSetupBufferQueue(mContext, alloc, numAlloc);
+    }
+    native void rsnAllocationShareBufferQueue(long con, long alloc1, long alloc2);
+    synchronized void nAllocationShareBufferQueue(long alloc1, long alloc2) {
+        validate();
+        rsnAllocationShareBufferQueue(mContext, alloc1, alloc2);
+    }
     native Surface rsnAllocationGetSurface(long con, long alloc);
     synchronized Surface nAllocationGetSurface(long alloc) {
         validate();
@@ -512,13 +521,12 @@
         validate();
         rsnAllocationIoSend(mContext, alloc);
     }
-    native void rsnAllocationIoReceive(long con, long alloc);
-    synchronized void nAllocationIoReceive(long alloc) {
+    native long rsnAllocationIoReceive(long con, long alloc);
+    synchronized long nAllocationIoReceive(long alloc) {
         validate();
-        rsnAllocationIoReceive(mContext, alloc);
+        return rsnAllocationIoReceive(mContext, alloc);
     }
 
-
     native void rsnAllocationGenerateMipmaps(long con, long alloc);
     synchronized void nAllocationGenerateMipmaps(long alloc) {
         validate();
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 398d89b..3dff37b 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1223,6 +1223,27 @@
     rsAllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits);
 }
 
+static void
+nAllocationSetupBufferQueue(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint numAlloc)
+{
+    if (kLogApi) {
+        ALOGD("nAllocationSetupBufferQueue, con(%p), alloc(%p), numAlloc(%d)", (RsContext)con,
+              (RsAllocation)alloc, numAlloc);
+    }
+    rsAllocationSetupBufferQueue((RsContext)con, (RsAllocation)alloc, (uint32_t)numAlloc);
+}
+
+static void
+nAllocationShareBufferQueue(JNIEnv *_env, jobject _this, jlong con, jlong alloc1, jlong alloc2)
+{
+    if (kLogApi) {
+        ALOGD("nAllocationShareBufferQueue, con(%p), alloc1(%p), alloc2(%p)", (RsContext)con,
+              (RsAllocation)alloc1, (RsAllocation)alloc2);
+    }
+
+    rsAllocationShareBufferQueue((RsContext)con, (RsAllocation)alloc1, (RsAllocation)alloc2);
+}
+
 static jobject
 nAllocationGetSurface(JNIEnv *_env, jobject _this, jlong con, jlong a)
 {
@@ -1265,16 +1286,15 @@
     rsAllocationIoSend((RsContext)con, (RsAllocation)alloc);
 }
 
-static void
+static jlong
 nAllocationIoReceive(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
 {
     if (kLogApi) {
         ALOGD("nAllocationIoReceive, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
     }
-    rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc);
+    return (jlong) rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc);
 }
 
-
 static void
 nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc)
 {
@@ -2856,10 +2876,12 @@
 {"rsnAllocationCopyToBitmap",        "(JJLandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
 
 {"rsnAllocationSyncAll",             "(JJI)V",                                (void*)nAllocationSyncAll },
+{"rsnAllocationSetupBufferQueue",    "(JJI)V",                                (void*)nAllocationSetupBufferQueue },
+{"rsnAllocationShareBufferQueue",    "(JJJ)V",                                (void*)nAllocationShareBufferQueue },
 {"rsnAllocationGetSurface",          "(JJ)Landroid/view/Surface;",            (void*)nAllocationGetSurface },
 {"rsnAllocationSetSurface",          "(JJLandroid/view/Surface;)V",           (void*)nAllocationSetSurface },
 {"rsnAllocationIoSend",              "(JJ)V",                                 (void*)nAllocationIoSend },
-{"rsnAllocationIoReceive",           "(JJ)V",                                 (void*)nAllocationIoReceive },
+{"rsnAllocationIoReceive",           "(JJ)J",                                 (void*)nAllocationIoReceive },
 {"rsnAllocationData1D",              "(JJIIILjava/lang/Object;IIIZ)V",        (void*)nAllocationData1D },
 {"rsnAllocationElementData",         "(JJIIIII[BI)V",                         (void*)nAllocationElementData },
 {"rsnAllocationData2D",              "(JJIIIIIILjava/lang/Object;IIIZ)V",     (void*)nAllocationData2D },
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 03809c0..2a8672d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -27,6 +27,7 @@
 import android.app.AlertDialog;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
+import android.app.UiAutomation;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -51,6 +52,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -258,10 +260,9 @@
                     UserState userState = getCurrentUserStateLocked();
                     // We have to reload the installed services since some services may
                     // have different attributes, resolve info (does not support equals),
-                    // etc. Remove them then to force reload. Do it even if automation is
-                    // running since when it goes away, we will have to reload as well.
+                    // etc. Remove them then to force reload.
                     userState.mInstalledServices.clear();
-                    if (userState.mUiAutomationService == null) {
+                    if (!userState.isUiAutomationSuppressingOtherServices()) {
                         if (readConfigurationForUserStateLocked(userState)) {
                             onUserStateChangedLocked(userState);
                         }
@@ -296,7 +297,7 @@
                                     TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
                                     userState.mTouchExplorationGrantedServices, userId);
                             // We will update when the automation service dies.
-                            if (userState.mUiAutomationService == null) {
+                            if (!userState.isUiAutomationSuppressingOtherServices()) {
                                 onUserStateChangedLocked(userState);
                             }
                             return;
@@ -330,7 +331,7 @@
                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                                         userState.mEnabledServices, userId);
                                 // We will update when the automation service dies.
-                                if (userState.mUiAutomationService == null) {
+                                if (!userState.isUiAutomationSuppressingOtherServices()) {
                                     onUserStateChangedLocked(userState);
                                 }
                             }
@@ -362,7 +363,7 @@
                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                     // We will update when the automation service dies.
                     UserState userState = getCurrentUserStateLocked();
-                    if (userState.mUiAutomationService == null) {
+                    if (!userState.isUiAutomationSuppressingOtherServices()) {
                         if (readConfigurationForUserStateLocked(userState)) {
                             onUserStateChangedLocked(userState);
                         }
@@ -473,11 +474,9 @@
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
 
-            // The automation service is a fake one and should not be reported
-            // to clients as being enabled. The automation service is always the
-            // only active one, if it exists.
+            // The automation service can suppress other services.
             UserState userState = getUserStateLocked(resolvedUserId);
-            if (userState.mUiAutomationService != null) {
+            if (userState.isUiAutomationSuppressingOtherServices()) {
                 return Collections.emptyList();
             }
 
@@ -490,7 +489,9 @@
                 final int serviceCount = services.size();
                 for (int i = 0; i < serviceCount; i++) {
                     Service service = services.get(i);
-                    if ((service.mFeedbackType & feedbackTypeBit) != 0) {
+                    // Don't report the UIAutomation (fake service)
+                    if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
+                            && (service.mFeedbackType & feedbackTypeBit) != 0) {
                         result.add(service.mAccessibilityServiceInfo);
                     }
                 }
@@ -621,7 +622,8 @@
     @Override
     public void registerUiTestAutomationService(IBinder owner,
             IAccessibilityServiceClient serviceClient,
-            AccessibilityServiceInfo accessibilityServiceInfo) {
+            AccessibilityServiceInfo accessibilityServiceInfo,
+            int flags) {
         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
                 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
 
@@ -645,15 +647,17 @@
 
             userState.mUiAutomationServiceOwner = owner;
             userState.mUiAutomationServiceClient = serviceClient;
-
-            // Set the temporary state.
+            userState.mUiAutomationFlags = flags;
             userState.mIsAccessibilityEnabled = true;
-            userState.mIsTouchExplorationEnabled = false;
-            userState.mIsEnhancedWebAccessibilityEnabled = false;
-            userState.mIsDisplayMagnificationEnabled = false;
-            userState.mIsAutoclickEnabled = false;
             userState.mInstalledServices.add(accessibilityServiceInfo);
-            userState.mEnabledServices.clear();
+            if (userState.isUiAutomationSuppressingOtherServices()) {
+                // Set the temporary state.
+                userState.mIsTouchExplorationEnabled = false;
+                userState.mIsEnhancedWebAccessibilityEnabled = false;
+                userState.mIsDisplayMagnificationEnabled = false;
+                userState.mIsAutoclickEnabled = false;
+                userState.mEnabledServices.clear();
+            }
             userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName);
             userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName);
 
@@ -694,7 +698,7 @@
             UserState userState = getCurrentUserStateLocked();
 
             // This is a nop if UI automation is enabled.
-            if (userState.mUiAutomationService != null) {
+            if (userState.isUiAutomationSuppressingOtherServices()) {
                 return;
             }
 
@@ -1027,6 +1031,9 @@
         if (!mTempComponentNameSet.equals(userState.mEnabledServices)) {
             userState.mEnabledServices.clear();
             userState.mEnabledServices.addAll(mTempComponentNameSet);
+            if (userState.mUiAutomationService != null) {
+                userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName);
+            }
             mTempComponentNameSet.clear();
             return true;
         }
@@ -3981,6 +3988,7 @@
         public boolean mAccessibilityFocusOnlyInActiveWindow;
 
         private Service mUiAutomationService;
+        private int mUiAutomationFlags;
         private IAccessibilityServiceClient mUiAutomationServiceClient;
 
         private IBinder mUiAutomationServiceOwner;
@@ -4044,6 +4052,7 @@
 
         public void destroyUiAutomationService() {
             mUiAutomationService = null;
+            mUiAutomationFlags = 0;
             mUiAutomationServiceClient = null;
             if (mUiAutomationServiceOwner != null) {
                 mUiAutomationServiceOwner.unlinkToDeath(
@@ -4051,6 +4060,11 @@
                 mUiAutomationServiceOwner = null;
             }
         }
+
+        boolean isUiAutomationSuppressingOtherServices() {
+            return ((mUiAutomationService != null) && (mUiAutomationFlags
+                    & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0);
+        }
     }
 
     private final class AccessibilityContentObserver extends ContentObserver {
@@ -4130,8 +4144,8 @@
                 // we are checking for changes only the parent settings.
                 UserState userState = getCurrentUserStateLocked();
 
-                // We will update when the automation service dies.
-                if (userState.mUiAutomationService != null) {
+                // If the automation service is suppressing, we will update when it dies.
+                if (userState.isUiAutomationSuppressingOtherServices()) {
                     return;
                 }
 
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index e6e69b1..a4455e9 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1181,6 +1181,9 @@
                             } else if ("audioserver".equals(packageName)) {
                                 pkgUid = Process.AUDIOSERVER_UID;
                                 isPrivileged = false;
+                            } else if ("cameraserver".equals(packageName)) {
+                                pkgUid = Process.CAMERASERVER_UID;
+                                isPrivileged = false;
                             }
                         }
                     } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3c13630..2d1f96b 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -745,7 +745,7 @@
         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
                 && SystemProperties.get("ro.build.type").equals("eng");
 
-        mTethering = new Tethering(mContext, mNetd, statsService, mHandler.getLooper());
+        mTethering = new Tethering(mContext, mNetd, statsService);
 
         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
 
@@ -3800,6 +3800,12 @@
             throw new IllegalArgumentException("Bad timeout specified");
         }
 
+        if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER
+                .equals(networkCapabilities.getNetworkSpecifier())) {
+            throw new IllegalArgumentException("Invalid network specifier - must not be '"
+                    + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
+        }
+
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
                 nextNetworkRequestId());
         NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index bc12fc5..9313148 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -21,6 +21,7 @@
 import android.os.Environment;
 import android.os.StatFs;
 import android.os.SystemClock;
+import android.os.storage.StorageManager;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -79,6 +80,10 @@
         reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw);
         reportFreeSpace(new File("/system"), "System", pw);
 
+        if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+            pw.println("File-based Encryption: true");
+        }
+
         // TODO: Read /proc/yaffs and report interesting values;
         // add configurable (through args) performance test parameters.
     }
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 2aa0390..d6575e8 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -38,6 +38,7 @@
 import android.view.KeyEvent;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
 /**
@@ -270,7 +271,7 @@
             launched = handleCameraLaunchGesture(false /* useWakelock */,
                     StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
             if (launched) {
-                MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
                         (int) doubleTapInterval);
             }
         }
@@ -341,7 +342,7 @@
                 }
                 if (handleCameraLaunchGesture(true /* useWakelock */,
                         StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)) {
-                    MetricsLogger.action(mContext, MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE);
+                    MetricsLogger.action(mContext, MetricsEvent.ACTION_WIGGLE_CAMERA_GESTURE);
                     trackCameraLaunchEvent(event);
                 }
                 return;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 9405d8e0..c55c5b6 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -24,10 +24,10 @@
 import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.FlpHardwareProvider;
 import com.android.server.location.FusedProxy;
+import com.android.server.location.GnssLocationProvider;
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
 import com.android.server.location.GeofenceProxy;
-import com.android.server.location.GpsLocationProvider;
 import com.android.server.location.GpsMeasurementsProvider;
 import com.android.server.location.GpsNavigationMessageProvider;
 import com.android.server.location.LocationBlacklist;
@@ -61,11 +61,11 @@
 import android.location.Criteria;
 import android.location.GeocoderParams;
 import android.location.Geofence;
+import android.location.IGnssStatusListener;
+import android.location.IGnssStatusProvider;
 import android.location.IGpsGeofenceHardware;
 import android.location.IGpsMeasurementsListener;
 import android.location.IGpsNavigationMessageListener;
-import android.location.IGpsStatusListener;
-import android.location.IGpsStatusProvider;
 import android.location.ILocationListener;
 import android.location.ILocationManager;
 import android.location.INetInitiatedListener;
@@ -157,7 +157,7 @@
     private PowerManager mPowerManager;
     private UserManager mUserManager;
     private GeocoderProxy mGeocodeProvider;
-    private IGpsStatusProvider mGpsStatusProvider;
+    private IGnssStatusProvider mGnssStatusProvider;
     private INetInitiatedListener mNetInitiatedListener;
     private LocationWorkerHandler mLocationHandler;
     private PassiveProvider mPassiveProvider;  // track passive provider for special cases
@@ -214,6 +214,8 @@
     private int mCurrentUserId = UserHandle.USER_SYSTEM;
     private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
 
+    private GnssLocationProvider.GpsSystemInfoProvider mGpsSystemInfoProvider;
+
     public LocationManagerService(Context context) {
         super();
         mContext = context;
@@ -456,17 +458,18 @@
         mEnabledProviders.add(passiveProvider.getName());
         mPassiveProvider = passiveProvider;
 
-        if (GpsLocationProvider.isSupported()) {
+        if (GnssLocationProvider.isSupported()) {
             // Create a gps location provider
-            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,
+            GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
                     mLocationHandler.getLooper());
-            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
-            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
-            addProviderLocked(gpsProvider);
-            mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
-            mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();
-            mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider();
-            mGpsGeofenceProxy = gpsProvider.getGpsGeofenceProxy();
+            mGpsSystemInfoProvider = gnssProvider.getGpsSystemInfoProvider();
+            mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
+            mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
+            addProviderLocked(gnssProvider);
+            mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
+            mGpsMeasurementsProvider = gnssProvider.getGpsMeasurementsProvider();
+            mGpsNavigationMessageProvider = gnssProvider.getGpsNavigationMessageProvider();
+            mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
         }
 
         /*
@@ -986,6 +989,18 @@
         }
     }
 
+    /**
+     * Returns the system information of the GPS hardware.
+     */
+    @Override
+    public int getGpsYearOfHardware() {
+        if (mGpsNavigationMessageProvider != null) {
+            return mGpsSystemInfoProvider.getGpsYearOfHardware();
+        } else {
+            return 0;
+        }
+    }
+
     private void addProviderLocked(LocationProviderInterface provider) {
         mProviders.add(provider);
         mProvidersByName.put(provider.getName(), provider);
@@ -1867,7 +1882,7 @@
 
 
     @Override
-    public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) {
+    public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
         checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
                 LocationManager.GPS_PROVIDER);
@@ -1883,26 +1898,26 @@
             Binder.restoreCallingIdentity(ident);
         }
 
-        if (mGpsStatusProvider == null) {
+        if (mGnssStatusProvider == null) {
             return false;
         }
 
         try {
-            mGpsStatusProvider.addGpsStatusListener(listener);
+            mGnssStatusProvider.registerGnssStatusCallback(callback);
         } catch (RemoteException e) {
-            Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
+            Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
             return false;
         }
         return true;
     }
 
     @Override
-    public void removeGpsStatusListener(IGpsStatusListener listener) {
+    public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
         synchronized (mLock) {
             try {
-                mGpsStatusProvider.removeGpsStatusListener(listener);
+                mGnssStatusProvider.unregisterGnssStatusCallback(callback);
             } catch (Exception e) {
-                Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
+                Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
             }
         }
     }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index f6f05fe..d0cd536 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -17,11 +17,12 @@
 package com.android.server;
 
 import android.app.ActivityManagerNative;
-import android.app.AppGlobals;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.app.backup.BackupManager;
 import android.app.trust.IStrongAuthTracker;
-import android.app.trust.ITrustManager;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -30,6 +31,8 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.content.res.Resources;
+
 import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
 import static android.content.Context.USER_SERVICE;
 import static android.Manifest.permission.READ_CONTACTS;
@@ -40,7 +43,6 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.storage.IMountService;
-import android.os.storage.StorageManager;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -70,19 +72,27 @@
  * @hide
  */
 public class LockSettingsService extends ILockSettings.Stub {
-
-    private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
-
     private static final String TAG = "LockSettingsService";
+    private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
+    private static final Intent ACTION_NULL; // hack to ensure notification shows the bouncer
+    private static final int FBE_ENCRYPTED_NOTIFICATION = 0;
+    private static final boolean DEBUG = false;
 
     private final Context mContext;
-
     private final LockSettingsStorage mStorage;
     private final LockSettingsStrongAuth mStrongAuth;
 
     private LockPatternUtils mLockPatternUtils;
     private boolean mFirstCallToVold;
     private IGateKeeperService mGateKeeperService;
+    private NotificationManager mNotificationManager;
+    private UserManager mUserManager;
+
+    static {
+        // Just launch the home screen, which happens anyway
+        ACTION_NULL = new Intent(Intent.ACTION_MAIN);
+        ACTION_NULL.addCategory(Intent.CATEGORY_HOME);
+    }
 
     private interface CredentialUtil {
         void setCredential(String credential, String savedCredential, int userId)
@@ -91,6 +101,42 @@
         String adjustForKeystore(String credential);
     }
 
+    // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
+    // devices. The most basic of these is to show/hide notifications about missing features until
+    // the user unlocks the account and credential-encrypted storage is available.
+    public static final class Lifecycle extends SystemService {
+        private LockSettingsService mLockSettingsService;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mLockSettingsService = new LockSettingsService(getContext());
+            publishBinderService("lock_settings", mLockSettingsService);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+                mLockSettingsService.maybeShowEncryptionNotification(UserHandle.ALL);
+            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+                // TODO
+            }
+        }
+
+        @Override
+        public void onUnlockUser(int userHandle) {
+            mLockSettingsService.onUnlockUser(userHandle);
+        }
+
+        @Override
+        public void onCleanupUser(int userHandle) {
+            mLockSettingsService.onCleanupUser(userHandle);
+        }
+    }
+
     public LockSettingsService(Context context) {
         mContext = context;
         mStrongAuth = new LockSettingsStrongAuth(context);
@@ -117,6 +163,71 @@
                 }
             }
         });
+        mNotificationManager = (NotificationManager)
+                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+    }
+
+    /**
+     * If the account is credential-encrypted, show notification requesting the user to unlock
+     * the device.
+     */
+    private void maybeShowEncryptionNotification(UserHandle userHandle) {
+        if (UserHandle.ALL.equals(userHandle)) {
+            final List<UserInfo> users = mUserManager.getUsers();
+            for (int i = 0; i < users.size(); i++) {
+                UserHandle user = users.get(i).getUserHandle();
+                if (!mUserManager.isUserUnlocked(user)) {
+                    showEncryptionNotification(user);
+                }
+            }
+        } else if (!mUserManager.isUserUnlocked(userHandle)){
+            showEncryptionNotification(userHandle);
+        }
+    }
+
+    private void showEncryptionNotification(UserHandle user) {
+        if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
+        Resources r = mContext.getResources();
+        CharSequence title = r.getText(
+                com.android.internal.R.string.user_encrypted_title);
+        CharSequence message = r.getText(
+                com.android.internal.R.string.user_encrypted_message);
+        CharSequence detail = r.getText(
+                com.android.internal.R.string.user_encrypted_detail);
+
+        PendingIntent intent = PendingIntent.getBroadcast(mContext, 0, ACTION_NULL,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+
+        Notification notification = new Notification.Builder(mContext)
+                .setSmallIcon(com.android.internal.R.drawable.ic_secure)
+                .setWhen(0)
+                .setOngoing(true)
+                .setTicker(title)
+                .setDefaults(0)  // please be quiet
+                .setPriority(Notification.PRIORITY_MAX)
+                .setColor(mContext.getColor(
+                        com.android.internal.R.color.system_notification_accent_color))
+                .setContentTitle(title)
+                .setContentText(message)
+                .setContentInfo(detail)
+                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .setContentIntent(intent)
+                .build();
+        mNotificationManager.notifyAsUser(null, FBE_ENCRYPTED_NOTIFICATION, notification, user);
+    }
+
+    public void hideEncryptionNotification(UserHandle userHandle) {
+        if (DEBUG) Slog.v(TAG, "hide encryption notification, user: "+ userHandle.getIdentifier());
+        mNotificationManager.cancelAsUser(null, FBE_ENCRYPTED_NOTIFICATION, userHandle);
+    }
+
+    public void onCleanupUser(int userId) {
+        hideEncryptionNotification(new UserHandle(userId));
+    }
+
+    public void onUnlockUser(int userHandle) {
+        hideEncryptionNotification(new UserHandle(userHandle));
     }
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -144,6 +255,7 @@
         }
     };
 
+    @Override // binder interface
     public void systemReady() {
         migrateOldData();
         try {
diff --git a/services/core/java/com/android/server/SensorNotificationService.java b/services/core/java/com/android/server/SensorNotificationService.java
new file mode 100644
index 0000000..0610464
--- /dev/null
+++ b/services/core/java/com/android/server/SensorNotificationService.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+
+public class SensorNotificationService extends SystemService implements SensorEventListener {
+    //TODO: set DBG to false or remove Slog before release
+    private static final boolean DBG = true;
+    private static final String TAG = "SensorNotificationService";
+    private Context mContext;
+
+    private SensorManager mSensorManager;
+    private Sensor mMetaSensor;
+
+    public SensorNotificationService(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    public void onStart() {
+        LocalServices.addService(SensorNotificationService.class, this);
+    }
+
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            // start
+            mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+            mMetaSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_DYNAMIC_SENSOR_META);
+            if (mMetaSensor == null) {
+                if (DBG) Slog.d(TAG, "Cannot obtain dynamic meta sensor, not supported.");
+            } else {
+                mSensorManager.registerListener(this, mMetaSensor,
+                        SensorManager.SENSOR_DELAY_FASTEST);
+            }
+        }
+    }
+
+    private void broadcastDynamicSensorChanged() {
+        Intent i = new Intent(Intent.ACTION_DYNAMIC_SENSOR_CHANGED);
+        i.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); // avoid waking up manifest receivers
+        mContext.sendBroadcastAsUser(i, UserHandle.ALL);
+        if (DBG) Slog.d(TAG, "DYNS sent dynamic sensor broadcast");
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor == mMetaSensor) {
+            broadcastDynamicSensorChanged();
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+
+    }
+}
+
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 4dc46ac..5aba22d 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -16,20 +16,24 @@
 
 package com.android.server;
 
+import static com.android.internal.util.ArrayUtils.appendInt;
+
 import android.app.ActivityManager;
 import android.content.pm.FeatureInfo;
-import android.os.*;
+import android.content.pm.PackageManager;
+import android.os.Environment;
 import android.os.Process;
+import android.os.storage.StorageManager;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
 
-import libcore.io.IoUtils;
-
 import com.android.internal.util.XmlUtils;
 
+import libcore.io.IoUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -38,8 +42,6 @@
 import java.io.FileReader;
 import java.io.IOException;
 
-import static com.android.internal.util.ArrayUtils.appendInt;
-
 /**
  * Loads global system configuration info.
  */
@@ -351,10 +353,7 @@
                         Slog.w(TAG, "<feature> without name in " + permFile + " at "
                                 + parser.getPositionDescription());
                     } else if (allowed) {
-                        //Log.i(TAG, "Got feature " + fname);
-                        FeatureInfo fi = new FeatureInfo();
-                        fi.name = fname;
-                        mAvailableFeatures.put(fname, fi);
+                        addFeature(fname);
                     }
                     XmlUtils.skipCurrentTag(parser);
                     continue;
@@ -443,10 +442,29 @@
             IoUtils.closeQuietly(permReader);
         }
 
-        for (String fname : mUnavailableFeatures) {
-            if (mAvailableFeatures.remove(fname) != null) {
-                Slog.d(TAG, "Removed unavailable feature " + fname);
-            }
+        // Some devices can be field-converted to FBE, so offer to splice in
+        // those features if not already defined by the static config
+        if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+            addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION);
+            addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS);
+        }
+
+        for (String featureName : mUnavailableFeatures) {
+            removeFeature(featureName);
+        }
+    }
+
+    private void addFeature(String featureName) {
+        if (!mAvailableFeatures.containsKey(featureName)) {
+            final FeatureInfo fi = new FeatureInfo();
+            fi.name = featureName;
+            mAvailableFeatures.put(featureName, fi);
+        }
+    }
+
+    private void removeFeature(String featureName) {
+        if (mAvailableFeatures.remove(featureName) != null) {
+            Slog.d(TAG, "Removed unavailable feature " + featureName);
         }
     }
 
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d0006aa..143015f 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -4342,6 +4342,7 @@
             String opPackageName) {
         List<String> permissionsToCheck = new ArrayList<String>(2);
         permissionsToCheck.add(Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
+        long id = Binder.clearCallingIdentity();
         try {
             ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
                     opPackageName, 0 /* flags */);
@@ -4363,6 +4364,8 @@
         } catch (NameNotFoundException e) {
             // No application associated with the specified package.
             Log.w(TAG, "No application associated with package: " + opPackageName);
+        } finally {
+            Binder.restoreCallingIdentity(id);
         }
         boolean isPermitted = isPermitted(opPackageName, callingUid, permissionsToCheck);
         return getTypesForCaller(callingUid, userId, isPermitted);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2c55ee2..b5982c3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9411,14 +9411,24 @@
     }
 
     @Override
-    public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode) {
+    public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
+            boolean preserveWindows, boolean animate) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
-                mStackSupervisor.resizeStackLocked(
-                        stackId, bounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                        !PRESERVE_WINDOWS, allowResizeInDockedMode);
+                if (animate) {
+                    if (stackId == PINNED_STACK_ID) {
+                        mWindowManager.animateResizePinnedStack(bounds);
+                    } else {
+                        throw new IllegalArgumentException("Stack: " + stackId
+                                + " doesn't support animated resize.");
+                    }
+                } else {
+                    mStackSupervisor.resizeStackLocked(stackId, bounds, null /* tempTaskBounds */,
+                            null /* tempTaskInsetBounds */, preserveWindows,
+                            allowResizeInDockedMode);
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -12960,6 +12970,9 @@
 
         final StringBuilder sb = new StringBuilder(1024);
         appendDropBoxProcessHeaders(process, processName, sb);
+        sb.append("Foreground: ")
+                .append(process.isInterestingToUserLocked() ? "Yes" : "No")
+                .append("\n");
         if (activity != null) {
             sb.append("Activity: ").append(activity.shortComponentName).append("\n");
         }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 71008a9..d1fcd3b 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -19,8 +19,9 @@
 import static android.app.ActivityManager.StackId;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
-import static android.content.pm.ActivityInfo.FLAG_RESIZEABLE;
-import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
@@ -355,6 +356,9 @@
         if (connections != null) {
             pw.print(prefix); pw.print("connections="); pw.println(connections);
         }
+        if (info != null) {
+            pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
+        }
     }
 
     public boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
@@ -754,11 +758,16 @@
     }
 
     boolean isResizeable() {
-        return (info.flags & FLAG_RESIZEABLE) != 0;
+        return !isHomeActivity() && (info.resizeMode == RESIZE_MODE_RESIZEABLE
+                || info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE);
     }
 
     boolean supportsPictureInPicture() {
-        return (info.flags & FLAG_SUPPORTS_PICTURE_IN_PICTURE) != 0;
+        return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+    }
+
+    boolean cropAppWindows() {
+        return !isHomeActivity() && info.resizeMode == RESIZE_MODE_CROP_WINDOWS;
     }
 
     boolean isAlwaysFocusable() {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ef8d230..3e99558 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1410,14 +1410,11 @@
         }
 
         if (mStackId == DOCKED_STACK_ID) {
-            // Docked stack is always visible, except in the case where the home activity
-            // is the top running activity in the focused home stack.
-            if (focusedStackId != HOME_STACK_ID) {
-                return STACK_VISIBLE;
-            }
-            ActivityRecord topHomeActivity = focusedStack.topRunningActivityLocked();
-            return topHomeActivity == null || !topHomeActivity.isHomeActivity() ?
-                    STACK_VISIBLE : STACK_INVISIBLE;
+            // Docked stack is always visible, except in the case where the top running activity in
+            // the focus stack doesn't support any form of resizing.
+            final ActivityRecord r = focusedStack.topRunningActivityLocked();
+            return r == null || r.isResizeable() || r.cropAppWindows()
+                    ? STACK_VISIBLE : STACK_INVISIBLE;
         }
 
         // Find the first stack below focused stack that actually got something visible.
@@ -4819,7 +4816,7 @@
                 r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                 (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
                 task.voiceSession != null, r.mLaunchTaskBehind, bounds, task.mOverrideConfig,
-                !r.isHomeActivity(), r.isAlwaysFocusable());
+                r.cropAppWindows() | r.isResizeable(), r.isAlwaysFocusable());
         mWindowManager.setTaskResizeable(task.taskId, task.mResizeable);
         r.taskConfigOverride = task.mOverrideConfig;
     }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8db2f8f..11dd8a3 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -98,6 +98,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 import static android.Manifest.permission.START_ANY_ACTIVITY;
@@ -2019,7 +2020,7 @@
         // If this is a forced resize, let it go through even if the bounds is not changing,
         // as we might need a relayout due to surface size change (to/from fullscreen).
         final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
-        if (task.mBounds != null && task.mBounds.equals(bounds) && !forced) {
+        if (Objects.equals(task.mBounds, bounds) && !forced) {
             // Nothing to do here...
             return true;
         }
@@ -2257,10 +2258,7 @@
             // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
             // window), we need to clear the replace window settings. Otherwise, we schedule a
             // timeout to remove the old window if the replacing window is not coming in time.
-            // In case of the pinned stack we don't resize the task during the move, but we will
-            // resize the stack soon after so we want to retain the replacing window.
-            mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken,
-                    !kept || stackId == PINNED_STACK_ID);
+            mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken, !kept);
         }
 
         // The task might have already been running and its visibility needs to be synchronized with
@@ -2294,7 +2292,8 @@
             return false;
         }
 
-        moveActivityToStackLocked(r, PINNED_STACK_ID, "moveTopActivityToPinnedStack", bounds);
+        moveActivityToStackLocked(r, PINNED_STACK_ID, "moveTopActivityToPinnedStack", null);
+        mWindowManager.animateResizePinnedStack(bounds);
         return true;
     }
 
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 82862e8..97ef10b 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -40,6 +40,7 @@
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ModemActivityInfo;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.IntArray;
@@ -51,6 +52,7 @@
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.PowerProfile;
+import com.android.internal.telephony.ITelephony;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 
@@ -855,6 +857,18 @@
         }
     }
 
+    @Override
+    public void noteBleScanStarted(WorkSource ws) {
+        enforceCallingPermission();
+        Slog.d(TAG, "BLE scan started for " + ws);
+    }
+
+    @Override
+    public void noteBleScanStopped(WorkSource ws) {
+        enforceCallingPermission();
+        Slog.d(TAG, "BLE scan stopped for " + ws);
+    }
+
     public boolean isOnBattery() {
         return mStats.isOnBattery();
     }
@@ -1317,6 +1331,24 @@
         return null;
     }
 
+    @GuardedBy("mExternalStatsLock")
+    private ModemActivityInfo pullModemActivityInfoLocked() {
+        ITelephony tm = ITelephony.Stub.asInterface(ServiceManager.getService(
+                Context.TELEPHONY_SERVICE));
+        try {
+            if (tm != null) {
+                ModemActivityInfo info = tm.getModemActivityInfo();
+                if (info == null || info.isValid()) {
+                    return info;
+                }
+                Slog.wtf(TAG, "Modem activity info is invalid: " + info);
+            }
+        } catch (RemoteException e) {
+            // Nothing to do.
+        }
+        return null;
+    }
+
     /**
      * Fetches data from external sources (WiFi controller, bluetooth chipset) and updates
      * batterystats with that information.
@@ -1346,6 +1378,11 @@
                 wifiEnergyInfo = pullWifiEnergyInfoLocked();
             }
 
+            ModemActivityInfo modemActivityInfo = null;
+            if ((updateFlags & UPDATE_RADIO) != 0) {
+                modemActivityInfo = pullModemActivityInfoLocked();
+            }
+
             BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
             if ((updateFlags & UPDATE_BT) != 0) {
                 // We only pull bluetooth stats when we have to, as we are not distributing its
@@ -1367,7 +1404,7 @@
                 }
 
                 if ((updateFlags & UPDATE_RADIO) != 0) {
-                    mStats.updateMobileRadioStateLocked(elapsedRealtime);
+                    mStats.updateMobileRadioStateLocked(elapsedRealtime, modemActivityInfo);
                 }
 
                 if ((updateFlags & UPDATE_WIFI) != 0) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index fd787df..c9d4595 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -24,7 +24,8 @@
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
-import static android.content.pm.ActivityInfo.FLAG_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
@@ -447,7 +448,9 @@
         } else {
             autoRemoveRecents = false;
         }
-        mResizeable = (info.flags & FLAG_RESIZEABLE) != 0 || mService.mForceResizableActivities;
+        mResizeable = info.resizeMode == RESIZE_MODE_RESIZEABLE
+                || info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
+                || mService.mForceResizableActivities;
         mLockTaskMode = info.lockTaskLaunchMode;
         mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
         setLockTaskAuth();
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 0029279..c5d38cb 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -248,10 +248,10 @@
     }
 
     public String toString() {
-        return "NetworkAgentInfo{ ni{" + networkInfo + "}  network{" +
-                network + "}  lp{" +
-                linkProperties + "}  nc{" +
-                networkCapabilities + "}  Score{" + getCurrentScore() + "}  " +
+        return "NetworkAgentInfo{ ni{" + networkInfo + "}  " +
+                "network{" + network + "}  nethandle{" + network.getNetworkHandle() + "}  " +
+                "lp{" + linkProperties + "}  " +
+                "nc{" + networkCapabilities + "}  Score{" + getCurrentScore() + "}  " +
                 "everValidated{" + everValidated + "}  lastValidated{" + lastValidated + "}  " +
                 "created{" + created + "} lingering{" + lingering + "} " +
                 "explicitlySelected{" + networkMisc.explicitlySelected + "} " +
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 6648efd..a73a67a 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -153,11 +153,10 @@
                                          // when RNDIS is enabled
 
     public Tethering(Context context, INetworkManagementService nmService,
-            INetworkStatsService statsService, Looper looper) {
+            INetworkStatsService statsService) {
         mContext = context;
         mNMService = nmService;
         mStatsService = statsService;
-        mLooper = looper;
 
         mPublicSync = new Object();
 
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 206cc8a..a633996 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -17,6 +17,7 @@
 package com.android.server.dreams;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -131,7 +132,7 @@
 
             mDreamStartTime = SystemClock.elapsedRealtime();
             MetricsLogger.visible(mContext,
-                    mCurrentDream.mCanDoze ? MetricsLogger.DOZING : MetricsLogger.DREAMING);
+                    mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
 
             try {
                 mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM);
@@ -196,7 +197,7 @@
                     + ", isTest=" + oldDream.mIsTest + ", canDoze=" + oldDream.mCanDoze
                     + ", userId=" + oldDream.mUserId);
             MetricsLogger.hidden(mContext,
-                    oldDream.mCanDoze ? MetricsLogger.DOZING : MetricsLogger.DREAMING);
+                    oldDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);
             MetricsLogger.histogram(mContext,
                     oldDream.mCanDoze ? "dozing_minutes" : "dreaming_minutes" ,
                     (int) ((SystemClock.elapsedRealtime() - mDreamStartTime) / (1000L * 60L)));
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index e74d636..13e7648 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -48,6 +48,7 @@
 import android.util.Slog;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.server.SystemService;
 
 import org.json.JSONArray;
@@ -686,7 +687,7 @@
         private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
             if (receiver == null) return true; // client not listening
             FingerprintUtils.vibrateFingerprintSuccess(getContext());
-            MetricsLogger.action(mContext, MetricsLogger.ACTION_FINGERPRINT_ENROLL);
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_FINGERPRINT_ENROLL);
             try {
                 receiver.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);
                 return remaining == 0;
@@ -704,7 +705,7 @@
             boolean authenticated = fpId != 0;
             if (receiver != null) {
                 try {
-                    MetricsLogger.action(mContext, MetricsLogger.ACTION_FINGERPRINT_AUTH,
+                    MetricsLogger.action(mContext, MetricsEvent.ACTION_FINGERPRINT_AUTH,
                             authenticated);
                     if (!authenticated) {
                         receiver.onAuthenticationFailed(mHalDeviceId);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 573afd6..033a243 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -16,7 +16,9 @@
 
 package com.android.server.input;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.LocaleList;
 import android.view.Display;
 import com.android.internal.inputmethod.InputMethodSubtypeHandle;
 import com.android.internal.os.SomeArgs;
@@ -780,8 +782,10 @@
                         || layout.getProductId() != d.getProductId()) {
                     return;
                 }
-                for (Locale l : layout.getLocales()) {
-                    if (isCompatibleLocale(systemLocale, l)) {
+                final LocaleList locales = layout.getLocales();
+                final int numLocales = locales.size();
+                for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+                    if (isCompatibleLocale(systemLocale, locales.get(localeIndex))) {
                         layouts.add(layout);
                         break;
                     }
@@ -799,9 +803,12 @@
         final int N = layouts.size();
         for (int i = 0; i < N; i++) {
             KeyboardLayout layout = layouts.get(i);
-            for (Locale l : layout.getLocales()) {
-                if (l.getCountry().equals(systemLocale.getCountry())
-                        && l.getVariant().equals(systemLocale.getVariant())) {
+            final LocaleList locales = layout.getLocales();
+            final int numLocales = locales.size();
+            for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+                final Locale locale = locales.get(localeIndex);
+                if (locale.getCountry().equals(systemLocale.getCountry())
+                        && locale.getVariant().equals(systemLocale.getVariant())) {
                     return layout.getDescriptor();
                 }
             }
@@ -809,8 +816,11 @@
         // Then try an exact match of language and country
         for (int i = 0; i < N; i++) {
             KeyboardLayout layout = layouts.get(i);
-            for (Locale l : layout.getLocales()) {
-                if (l.getCountry().equals(systemLocale.getCountry())) {
+            final LocaleList locales = layout.getLocales();
+            final int numLocales = locales.size();
+            for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+                final Locale locale = locales.get(localeIndex);
+                if (locale.getCountry().equals(systemLocale.getCountry())) {
                     return layout.getDescriptor();
                 }
             }
@@ -1170,7 +1180,7 @@
                                     0);
                             String languageTags = a.getString(
                                     com.android.internal.R.styleable.KeyboardLayout_locale);
-                            Locale[] locales = getLocalesFromLanguageTags(languageTags);
+                            LocaleList locales = getLocalesFromLanguageTags(languageTags);
                             int vid = a.getInt(
                                     com.android.internal.R.styleable.KeyboardLayout_vendorId, -1);
                             int pid = a.getInt(
@@ -1210,16 +1220,12 @@
         }
     }
 
-    private static Locale[] getLocalesFromLanguageTags(String languageTags) {
+    @NonNull
+    private static LocaleList getLocalesFromLanguageTags(String languageTags) {
         if (TextUtils.isEmpty(languageTags)) {
-            return new Locale[0];
+            return LocaleList.getEmptyLocaleList();
         }
-        String[] tags = languageTags.split("\\|");
-        Locale[] locales = new Locale[tags.length];
-        for (int i = 0; i < tags.length; i++) {
-            locales[i] = Locale.forLanguageTag(tags[i]);
-        }
-        return locales;
+        return LocaleList.forLanguageTags(languageTags.replace('|', ','));
     }
 
     /**
@@ -1596,7 +1602,7 @@
         final int accessibilityConfig = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
                 0, UserHandle.USER_CURRENT);
-        PointerIcon.sUseLargeIcons = (accessibilityConfig == 1);
+        PointerIcon.setUseLargeIcons(accessibilityConfig == 1);
         nativeReloadPointerIcons(mPtr);
     }
 
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
similarity index 96%
rename from services/core/java/com/android/server/location/GpsLocationProvider.java
rename to services/core/java/com/android/server/location/GnssLocationProvider.java
index 88ab2c6..9798e56 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -35,11 +35,12 @@
 import android.hardware.location.GeofenceHardwareImpl;
 import android.location.Criteria;
 import android.location.FusedBatchOptions;
+import android.location.GnssStatus;
+import android.location.IGnssStatusListener;
+import android.location.IGnssStatusProvider;
 import android.location.GpsMeasurementsEvent;
 import android.location.GpsNavigationMessageEvent;
 import android.location.IGpsGeofenceHardware;
-import android.location.IGpsStatusListener;
-import android.location.IGpsStatusProvider;
 import android.location.ILocationManager;
 import android.location.INetInitiatedListener;
 import android.location.Location;
@@ -100,9 +101,9 @@
  *
  * {@hide}
  */
-public class GpsLocationProvider implements LocationProviderInterface {
+public class GnssLocationProvider implements LocationProviderInterface {
 
-    private static final String TAG = "GpsLocationProvider";
+    private static final String TAG = "GnssLocationProvider";
 
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
@@ -366,7 +367,7 @@
     private final ILocationManager mILocationManager;
     private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
     private Bundle mLocationExtras = new Bundle();
-    private final GpsStatusListenerHelper mListenerHelper;
+    private final GnssStatusListenerHelper mListenerHelper;
     private final GpsMeasurementsProvider mGpsMeasurementsProvider;
     private final GpsNavigationMessageProvider mGpsNavigationMessageProvider;
 
@@ -382,7 +383,7 @@
     private final GpsNetInitiatedHandler mNIHandler;
 
     // Wakelocks
-    private final static String WAKELOCK_KEY = "GpsLocationProvider";
+    private final static String WAKELOCK_KEY = "GnssLocationProvider";
     private final PowerManager.WakeLock mWakeLock;
 
     // Alarms
@@ -405,20 +406,22 @@
 
     private GeofenceHardwareImpl mGeofenceHardwareImpl;
 
-    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
+    private int mYearOfHardware = 0;
+
+    private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
         @Override
-        public void addGpsStatusListener(IGpsStatusListener listener) {
-            mListenerHelper.addListener(listener);
+        public void registerGnssStatusCallback(IGnssStatusListener callback) {
+            mListenerHelper.addListener(callback);
         }
 
         @Override
-        public void removeGpsStatusListener(IGpsStatusListener listener) {
-            mListenerHelper.removeListener(listener);
+        public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
+            mListenerHelper.removeListener(callback);
         }
     };
 
-    public IGpsStatusProvider getGpsStatusProvider() {
-        return mGpsStatusProvider;
+    public IGnssStatusProvider getGnssStatusProvider() {
+        return mGnssStatusProvider;
     }
 
     public IGpsGeofenceHardware getGpsGeofenceProxy() {
@@ -655,7 +658,7 @@
         return true;
     }
 
-    public GpsLocationProvider(Context context, ILocationManager ilocationManager,
+    public GnssLocationProvider(Context context, ILocationManager ilocationManager,
             Looper looper) {
         mContext = context;
         mNtpTime = NtpTrustedTime.getInstance(context);
@@ -698,7 +701,7 @@
                                                 mNetInitiatedListener,
                                                 mSuplEsEnabled);
 
-        mListenerHelper = new GpsStatusListenerHelper(mHandler) {
+        mListenerHelper = new GnssStatusListenerHelper(mHandler) {
             @Override
             protected boolean isAvailableInPlatform() {
                 return isSupported();
@@ -1554,34 +1557,40 @@
      * called from native code to update SV info
      */
     private void reportSvStatus() {
-        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
+        int svCount = native_read_sv_status(mPrnWithFlags, mSnrs, mSvElevations, mSvAzimuths,
+                mConstellationTypes);
         mListenerHelper.onSvStatusChanged(
                 svCount,
-                mSvs,
+                mPrnWithFlags,
                 mSnrs,
                 mSvElevations,
                 mSvAzimuths,
-                mSvMasks[EPHEMERIS_MASK],
-                mSvMasks[ALMANAC_MASK],
-                mSvMasks[USED_FOR_FIX_MASK]);
+                mConstellationTypes);
 
         if (VERBOSE) {
-            Log.v(TAG, "SV count: " + svCount +
-                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
-                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
-            for (int i = 0; i < svCount; i++) {
-                Log.v(TAG, "sv: " + mSvs[i] +
+            Log.v(TAG, "SV count: " + svCount);
+        }
+        // Calculate number of sets used in fix.
+        int usedInFixCount = 0;
+        for (int i = 0; i < svCount; i++) {
+            if ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
+                ++usedInFixCount;
+            }
+            if (VERBOSE) {
+                Log.v(TAG, "prn: " + (mPrnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH) +
                         " snr: " + mSnrs[i]/10 +
                         " elev: " + mSvElevations[i] +
                         " azimuth: " + mSvAzimuths[i] +
-                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
-                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
-                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
+                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
+                                ? "  " : " E") +
+                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
+                                ? "  " : " A") +
+                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
+                                ? "" : "U"));
             }
         }
-
         // return number of sets used in fix instead of total
-        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
+        updateStatus(mStatus, usedInFixCount);
 
         if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
             System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
@@ -1675,6 +1684,33 @@
     }
 
     /**
+     * Called from native code to inform us the hardware information.
+     */
+    private void setGpsYearOfHardware(int yearOfHardware) {
+        if (DEBUG) Log.d(TAG, "setGpsYearOfHardware called with " + yearOfHardware);
+        mYearOfHardware = yearOfHardware;
+    }
+
+    public interface GpsSystemInfoProvider {
+        /**
+         * Returns the year of GPS hardware.
+         */
+        int getGpsYearOfHardware();
+    }
+
+    /**
+     * @hide
+     */
+    public GpsSystemInfoProvider getGpsSystemInfoProvider() {
+        return new GpsSystemInfoProvider() {
+            @Override
+            public int getGpsYearOfHardware() {
+                return mYearOfHardware;
+            }
+        };
+    }
+
+    /**
      * called from native code to request XTRA data
      */
     private void xtraDownloadRequest() {
@@ -2067,7 +2103,7 @@
         }
 
         /**
-         * This method is bound to {@link #GpsLocationProvider(Context, ILocationManager, Looper)}.
+         * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}.
          * It is in charge of loading properties and registering for events that will be posted to
          * this handler.
          */
@@ -2362,17 +2398,14 @@
     }
 
     // for GPS SV statistics
-    private static final int MAX_SVS = 32;
-    private static final int EPHEMERIS_MASK = 0;
-    private static final int ALMANAC_MASK = 1;
-    private static final int USED_FOR_FIX_MASK = 2;
+    private static final int MAX_SVS = 512;
 
     // preallocated arrays, to avoid memory allocation in reportStatus()
-    private int mSvs[] = new int[MAX_SVS];
+    private int mPrnWithFlags[] = new int[MAX_SVS];
     private float mSnrs[] = new float[MAX_SVS];
     private float mSvElevations[] = new float[MAX_SVS];
     private float mSvAzimuths[] = new float[MAX_SVS];
-    private int mSvMasks[] = new int[3];
+    private int mConstellationTypes[] = new int[MAX_SVS];
     private int mSvCount;
     // preallocated to avoid memory allocation in reportNmea()
     private byte[] mNmeaBuffer = new byte[120];
@@ -2392,8 +2425,8 @@
     private native void native_delete_aiding_data(int flags);
     // returns number of SVs
     // mask[0] is ephemeris mask and mask[1] is almanac mask
-    private native int native_read_sv_status(int[] svs, float[] snrs,
-            float[] elevations, float[] azimuths, int[] masks);
+    private native int native_read_sv_status(int[] prnWithFlags, float[] snrs, float[] elevations,
+            float[] azimuths, int[] constellationTypes);
     private native int native_read_nmea(byte[] buffer, int bufferSize);
     private native void native_inject_location(double latitude, double longitude, float accuracy);
 
diff --git a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
similarity index 63%
rename from services/core/java/com/android/server/location/GpsStatusListenerHelper.java
rename to services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 53ff6c2..9840c61 100644
--- a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -16,17 +16,17 @@
 
 package com.android.server.location;
 
-import android.location.IGpsStatusListener;
+import android.location.IGnssStatusListener;
 import android.os.Handler;
 import android.os.RemoteException;
 
 /**
- * Implementation of a handler for {@link IGpsStatusListener}.
+ * Implementation of a handler for {@link IGnssStatusListener}.
  */
-abstract class GpsStatusListenerHelper extends RemoteListenerHelper<IGpsStatusListener> {
-    protected GpsStatusListenerHelper(Handler handler) {
-        super(handler, "GpsStatusListenerHelper");
-        setSupported(GpsLocationProvider.isSupported());
+abstract class GnssStatusListenerHelper extends RemoteListenerHelper<IGnssStatusListener> {
+    protected GnssStatusListenerHelper(Handler handler) {
+        super(handler, "GnssStatusListenerHelper");
+        setSupported(GnssLocationProvider.isSupported());
     }
 
     @Override
@@ -38,7 +38,7 @@
     protected void unregisterFromService() {}
 
     @Override
-    protected ListenerOperation<IGpsStatusListener> getHandlerOperation(int result) {
+    protected ListenerOperation<IGnssStatusListener> getHandlerOperation(int result) {
         return null;
     }
 
@@ -47,15 +47,15 @@
         if (isNavigating) {
             operation = new Operation() {
                 @Override
-                public void execute(IGpsStatusListener listener) throws RemoteException {
-                    listener.onGpsStarted();
+                public void execute(IGnssStatusListener listener) throws RemoteException {
+                    listener.onGnssStarted();
                 }
             };
         } else {
             operation = new Operation() {
                 @Override
-                public void execute(IGpsStatusListener listener) throws RemoteException {
-                    listener.onGpsStopped();
+                public void execute(IGnssStatusListener listener) throws RemoteException {
+                    listener.onGnssStopped();
                 }
             };
         }
@@ -65,7 +65,7 @@
     public void onFirstFix(final int timeToFirstFix) {
         Operation operation = new Operation() {
             @Override
-            public void execute(IGpsStatusListener listener) throws RemoteException {
+            public void execute(IGnssStatusListener listener) throws RemoteException {
                 listener.onFirstFix(timeToFirstFix);
             }
         };
@@ -74,25 +74,21 @@
 
     public void onSvStatusChanged(
             final int svCount,
-            final int[] prns,
+            final int[] prnWithFlags,
             final float[] snrs,
             final float[] elevations,
             final float[] azimuths,
-            final int ephemerisMask,
-            final int almanacMask,
-            final int usedInFixMask) {
+            final int[] constellationTypes) {
         Operation operation = new Operation() {
             @Override
-            public void execute(IGpsStatusListener listener) throws RemoteException {
+            public void execute(IGnssStatusListener listener) throws RemoteException {
                 listener.onSvStatusChanged(
                         svCount,
-                        prns,
+                        prnWithFlags,
                         snrs,
                         elevations,
                         azimuths,
-                        ephemerisMask,
-                        almanacMask,
-                        usedInFixMask);
+                        constellationTypes);
             }
         };
         foreach(operation);
@@ -101,12 +97,12 @@
     public void onNmeaReceived(final long timestamp, final String nmea) {
         Operation operation = new Operation() {
             @Override
-            public void execute(IGpsStatusListener listener) throws RemoteException {
+            public void execute(IGnssStatusListener listener) throws RemoteException {
                 listener.onNmeaReceived(timestamp, nmea);
             }
         };
         foreach(operation);
     }
 
-    private interface Operation extends ListenerOperation<IGpsStatusListener> {}
+    private interface Operation extends ListenerOperation<IGnssStatusListener> {}
 }
diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java
index 53ba718..479b065 100644
--- a/services/core/java/com/android/server/net/NetworkStatsAccess.java
+++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java
@@ -66,15 +66,26 @@
          *
          * <p>Granted to:
          * <ul>
-         * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
-         * so it is not necessarily sufficient to declare this in the manifest.
-         * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
          * <li>Profile owners.
          * </ul>
          */
         int USER = 1;
 
         /**
+         * Access level for apps which can access usage summary of device. Device summary includes
+         * usage by apps running in any profiles/users, however this access level does not
+         * allow querying usage of individual apps running in other profiles/users.
+         *
+         * <p>Granted to:
+         * <ul>
+         * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
+         * so it is not necessarily sufficient to declare this in the manifest.
+         * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
+         * </ul>
+         */
+        int DEVICESUMMARY = 2;
+
+        /**
          * Access level for apps which can access usage for any app on the device, including apps
          * running on other users/profiles.
          *
@@ -85,7 +96,7 @@
          * <li>The system UID.
          * </ul>
          */
-        int DEVICE = 2;
+        int DEVICE = 3;
     }
 
     /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
@@ -107,11 +118,15 @@
             return NetworkStatsAccess.Level.DEVICE;
         }
 
+        boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage);
+        if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
+                READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
+            return NetworkStatsAccess.Level.DEVICESUMMARY;
+        }
+
         boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
                 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-        if (hasAppOpsPermission(context, callingUid, callingPackage) || isProfileOwner
-                || context.checkCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY) ==
-                PackageManager.PERMISSION_GRANTED) {
+        if (isProfileOwner) {
             // Apps with the AppOps permission, profile owners, and apps with the privileged
             // permission can access data usage for all apps in this user/profile.
             return NetworkStatsAccess.Level.USER;
@@ -131,6 +146,7 @@
             case NetworkStatsAccess.Level.DEVICE:
                 // Device-level access - can access usage for any uid.
                 return true;
+            case NetworkStatsAccess.Level.DEVICESUMMARY:
             case NetworkStatsAccess.Level.USER:
                 // User-level access - can access usage for any app running in the same user, along
                 // with some special uids (system, removed, or tethering).
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index b1d6f89..3aeceef 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -484,15 +484,19 @@
             public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start,
                     long end) {
                 @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
-                if (accessLevel < NetworkStatsAccess.Level.DEVICE) {
+                if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
                     throw new SecurityException("Calling package " + mCallingPackage
-                            + " cannot access device-level network stats");
+                            + " cannot access device summary network stats");
                 }
                 NetworkStats result = new NetworkStats(end - start, 1);
                 final long ident = Binder.clearCallingIdentity();
                 try {
+                    // Using access level higher than the one we checked for above.
+                    // Reason is that we are combining usage data in a way that is not PII
+                    // anymore.
                     result.combineAllValues(
-                            internalGetSummaryForNetwork(template, start, end, accessLevel));
+                            internalGetSummaryForNetwork(template, start, end,
+                                    NetworkStatsAccess.Level.DEVICE));
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7f783ec..b54efcc 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.notification;
 
+import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL;
 import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL_ALL;
 import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL;
@@ -28,6 +29,7 @@
 import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL_ALL;
 import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_BANNED;
 import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_SUSPENDED;
 import static android.service.notification.NotificationAssistantService.REASON_TOPIC_BANNED;
 import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
 import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
@@ -456,7 +458,7 @@
     /** Use this to check if a package can post a notification or toast. */
     private boolean checkNotificationOp(String pkg, int uid) {
         return mAppOps.checkOp(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
-                == AppOpsManager.MODE_ALLOWED;
+                == AppOpsManager.MODE_ALLOWED && !isApplicationSuspended(pkg, uid);
     }
 
     private static final class ToastRecord
@@ -691,13 +693,15 @@
             boolean queryRemove = false;
             boolean packageChanged = false;
             boolean cancelNotifications = true;
+            int reason = REASON_PACKAGE_CHANGED;
 
             if (action.equals(Intent.ACTION_PACKAGE_ADDED)
                     || (queryRemove=action.equals(Intent.ACTION_PACKAGE_REMOVED))
                     || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
                     || (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED))
                     || (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
-                    || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
+                    || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)
+                    || action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
                 int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                         UserHandle.USER_ALL);
                 String pkgList[] = null;
@@ -706,6 +710,9 @@
                 if (DBG) Slog.i(TAG, "action=" + action + " queryReplace=" + queryReplace);
                 if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
+                    pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                    reason = REASON_PACKAGE_SUSPENDED;
                 } else if (queryRestart) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
                 } else {
@@ -745,7 +752,7 @@
                     for (String pkgName : pkgList) {
                         if (cancelNotifications) {
                             cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart,
-                                    changeUserId, REASON_PACKAGE_CHANGED, null, null);
+                                    changeUserId, reason, null, null);
                         }
                     }
                 }
@@ -989,6 +996,11 @@
         getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, pkgFilter, null,
                 null);
 
+        IntentFilter suspendedPkgFilter = new IntentFilter();
+        suspendedPkgFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+        getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL,
+                suspendedPkgFilter, null, null);
+
         IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
         getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, sdFilter, null,
                 null);
@@ -1104,10 +1116,16 @@
             }
 
             final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
+            final boolean isApplicationSuspended =
+                    isApplicationSuspended(pkg, Binder.getCallingUid());
 
-            if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) {
+            if (ENABLE_BLOCKED_TOASTS && (!noteNotificationOp(pkg, Binder.getCallingUid())
+                    || isApplicationSuspended)) {
                 if (!isSystemToast) {
-                    Slog.e(TAG, "Suppressing toast from package " + pkg + " by user request.");
+                    Slog.e(TAG, "Suppressing toast from package " + pkg
+                            + (isApplicationSuspended
+                                    ? " due to package suspended by administrator."
+                                    : " by user request."));
                     return;
                 }
             }
@@ -1232,7 +1250,7 @@
         public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
             checkCallerIsSystem();
             return (mAppOps.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
-                    == AppOpsManager.MODE_ALLOWED);
+                    == AppOpsManager.MODE_ALLOWED) && !isApplicationSuspended(pkg, uid);
         }
 
         @Override
@@ -2325,14 +2343,20 @@
 
                 // why is this here?
                 savePolicyFile();
+                final boolean isApplicationSuspended = isApplicationSuspended(pkg, callingUid);
 
                 // blocked apps/topics
                 if (r.getImportance() == NotificationListenerService.Ranking.IMPORTANCE_NONE
-                        || !noteNotificationOp(pkg, callingUid)) {
+                        || !noteNotificationOp(pkg, callingUid) || isApplicationSuspended) {
                     if (!isSystemNotification) {
-                        Slog.e(TAG, "Suppressing notification from package " + pkg
-                                + " by user request.");
-                        mUsageStats.registerBlocked(r);
+                        if (isApplicationSuspended) {
+                            Slog.e(TAG, "Suppressing notification from package due to package "
+                                    + "suspended by administrator.");
+                            mUsageStats.registerSuspendedByAdmin(r);
+                        } else {
+                            Slog.e(TAG, "Suppressing notification from package by user request.");
+                            mUsageStats.registerBlocked(r);
+                        }
                         return;
                     }
                 }
@@ -3423,6 +3447,24 @@
         return true;
     }
 
+    private boolean isApplicationSuspended(String pkg, int uid) {
+        int userId = UserHandle.getUserId(uid);
+        ApplicationInfo ai;
+        try {
+            // TODO: it might be faster to return a boolean from package manager rather than the
+            // whole application info. Revisit and make the API change.
+            ai = AppGlobals.getPackageManager().getApplicationInfo(pkg, 0, userId);
+            if (ai == null) {
+                Slog.w(TAG, "No application info for package " + pkg + " and user " + userId);
+                return false;
+            }
+        } catch (RemoteException re) {
+            throw new SecurityException("Could not talk to package manager service");
+        }
+
+        return ((ai.flags & FLAG_SUSPENDED) != 0);
+    }
+
     private class TrimCache {
         StatusBarNotification heavy;
         StatusBarNotification sbnClone;
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index e75324f..0272850 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -198,6 +198,14 @@
         releaseAggregatedStatsLocked(aggregatedStatsArray);
     }
 
+    public synchronized void registerSuspendedByAdmin(NotificationRecord notification) {
+        AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
+        for (AggregatedStats stats : aggregatedStatsArray) {
+            stats.numSuspendedByAdmin++;
+        }
+        releaseAggregatedStatsLocked(aggregatedStatsArray);
+    }
+
     // Locked by this.
     private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
         if (!ENABLE_AGGREGATED_IN_MEMORY_STATS) {
@@ -298,6 +306,7 @@
         public int numWithStaredPeople;
         public int numWithValidPeople;
         public int numBlocked;
+        public int numSuspendedByAdmin;
         public int numWithActions;
         public int numPrivate;
         public int numSecret;
@@ -414,6 +423,7 @@
             maybeCount("people_cache_hit", (numPeopleCacheHit - mPrevious.numPeopleCacheHit));
             maybeCount("people_cache_miss", (numPeopleCacheMiss - mPrevious.numPeopleCacheMiss));
             maybeCount("note_blocked", (numBlocked - mPrevious.numBlocked));
+            maybeCount("note_suspended", (numSuspendedByAdmin - mPrevious.numSuspendedByAdmin));
             maybeCount("note_with_actions", (numWithActions - mPrevious.numWithActions));
             maybeCount("note_private", (numPrivate - mPrevious.numPrivate));
             maybeCount("note_secret", (numSecret - mPrevious.numSecret));
@@ -442,6 +452,7 @@
             mPrevious.numWithStaredPeople = numWithStaredPeople;
             mPrevious.numWithValidPeople = numWithValidPeople;
             mPrevious.numBlocked = numBlocked;
+            mPrevious.numSuspendedByAdmin = numSuspendedByAdmin;
             mPrevious.numWithActions = numWithActions;
             mPrevious.numPrivate = numPrivate;
             mPrevious.numSecret = numSecret;
@@ -501,6 +512,8 @@
             output.append(indentPlusTwo);
             output.append("numBlocked=").append(numBlocked).append(",\n");
             output.append(indentPlusTwo);
+            output.append("numSuspendedByAdmin=").append(numSuspendedByAdmin).append(",\n");
+            output.append(indentPlusTwo);
             output.append("numWithActions=").append(numWithActions).append(",\n");
             output.append(indentPlusTwo);
             output.append("numPrivate=").append(numPrivate).append(",\n");
@@ -551,6 +564,7 @@
             maybePut(dump, "numWithStaredPeople", numWithStaredPeople);
             maybePut(dump, "numWithValidPeople", numWithValidPeople);
             maybePut(dump, "numBlocked", numBlocked);
+            maybePut(dump, "numSuspendedByAdmin", numSuspendedByAdmin);
             maybePut(dump, "numWithActions", numWithActions);
             maybePut(dump, "numPrivate", numPrivate);
             maybePut(dump, "numSecret", numSecret);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index bce7223..4d66e10 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -70,8 +70,7 @@
     }
 
     static boolean canOptimizePackage(PackageParser.Package pkg) {
-        return pkg.canHaveOatDir() &&
-                ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0);
+        return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0;
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d11da79..c3f20eb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -76,6 +76,7 @@
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDWR;
+
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index fc79849..0f614ca 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -25,9 +25,11 @@
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.app.IStopUserCallback;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -302,6 +304,12 @@
 
     private final LockPatternUtils mLockPatternUtils;
 
+    /**
+     * Whether all users should be created ephemeral.
+     */
+    @GuardedBy("mUsersLock")
+    private boolean mForceEphemeralUsers;
+
     private static UserManagerService sInstance;
 
     public static UserManagerService getInstance() {
@@ -1836,23 +1844,25 @@
                     }
                 }
 
-                // Add ephemeral flag to guests if required. Also inherit it from parent.
+                userId = getNextAvailableId();
+                Environment.getUserSystemDirectory(userId).mkdirs();
                 boolean ephemeralGuests = Resources.getSystem()
                         .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
-                if ((isGuest && ephemeralGuests)
-                        || (parent != null && parent.info.isEphemeral())) {
-                    flags |= UserInfo.FLAG_EPHEMERAL;
-                }
-                userId = getNextAvailableId();
-                userInfo = new UserInfo(userId, name, null, flags);
-                userInfo.serialNumber = mNextSerialNumber++;
-                long now = System.currentTimeMillis();
-                userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
-                userInfo.partial = true;
-                userData = new UserData();
-                userData.info = userInfo;
-                Environment.getUserSystemDirectory(userInfo.id).mkdirs();
+
                 synchronized (mUsersLock) {
+                    // Add ephemeral flag to guests/users if required. Also inherit it from parent.
+                    if ((isGuest && ephemeralGuests) || mForceEphemeralUsers
+                            || (parent != null && parent.info.isEphemeral())) {
+                        flags |= UserInfo.FLAG_EPHEMERAL;
+                    }
+
+                    userInfo = new UserInfo(userId, name, null, flags);
+                    userInfo.serialNumber = mNextSerialNumber++;
+                    long now = System.currentTimeMillis();
+                    userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
+                    userInfo.partial = true;
+                    userData = new UserData();
+                    userData.info = userInfo;
                     mUsers.put(userId, userData);
                 }
                 writeUserListLP();
@@ -2914,6 +2924,61 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
+
+        @Override
+        public void setForceEphemeralUsers(boolean forceEphemeralUsers) {
+            synchronized (mUsersLock) {
+                mForceEphemeralUsers = forceEphemeralUsers;
+            }
+        }
+
+        @Override
+        public void removeAllUsers() {
+            if (UserHandle.USER_SYSTEM == ActivityManager.getCurrentUser()) {
+                // Remove the non-system users straight away.
+                removeNonSystemUsers();
+            } else {
+                // Switch to the system user first and then remove the other users.
+                BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        int userId =
+                                intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                        if (userId != UserHandle.USER_SYSTEM) {
+                            return;
+                        }
+                        mContext.unregisterReceiver(this);
+                        removeNonSystemUsers();
+                    }
+                };
+                IntentFilter userSwitchedFilter = new IntentFilter();
+                userSwitchedFilter.addAction(Intent.ACTION_USER_SWITCHED);
+                mContext.registerReceiver(
+                        userSwitchedReceiver, userSwitchedFilter, null, mHandler);
+
+                // Switch to the system user.
+                ActivityManager am =
+                        (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+                am.switchUser(UserHandle.USER_SYSTEM);
+            }
+        }
+    }
+
+    /* Remove all the users except of the system one. */
+    private void removeNonSystemUsers() {
+        ArrayList<UserInfo> usersToRemove = new ArrayList<>();
+        synchronized (mUsersLock) {
+            final int userSize = mUsers.size();
+            for (int i = 0; i < userSize; i++) {
+                UserInfo ui = mUsers.valueAt(i).info;
+                if (ui.id != UserHandle.USER_SYSTEM) {
+                    usersToRemove.add(ui);
+                }
+            }
+        }
+        for (UserInfo ui: usersToRemove) {
+            removeUser(ui.id);
+        }
     }
 
     private class Shell extends ShellCommand {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 290019c..a1f24f7 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -131,6 +131,7 @@
     private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
     private static final int WAKE_LOCK_DOZE = 1 << 6;
     private static final int WAKE_LOCK_DRAW = 1 << 7;
+    private static final int WAKE_LOCK_SUSTAINED_PERFORMANCE = 1 << 8;
 
     // Summarizes the user activity state.
     private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
@@ -149,6 +150,7 @@
 
     // Power hints defined in hardware/libhardware/include/hardware/power.h.
     private static final int POWER_HINT_LOW_POWER = 5;
+    private static final int POWER_HINT_SUSTAINED_PERFORMANCE = 6;
 
     // Power features defined in hardware/libhardware/include/hardware/power.h.
     private static final int POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 1;
@@ -444,6 +446,9 @@
     // True if we are currently in light device idle mode.
     private boolean mLightDeviceIdleMode;
 
+    // True if we are currently in sustained performance mode.
+    private boolean mSustainedPerformanceMode;
+
     // Set of app ids that we will always respect the wake locks for.
     int[] mDeviceIdleWhitelist = new int[0];
 
@@ -452,6 +457,8 @@
 
     private final SparseIntArray mUidState = new SparseIntArray();
 
+    private final SparseIntArray mSustainedPerformanceUid = new SparseIntArray();
+
     // True if theater mode is enabled
     private boolean mTheaterModeEnabled;
 
@@ -811,6 +818,12 @@
                     throw new IllegalArgumentException("Wake lock is already dead.");
                 }
                 mWakeLocks.add(wakeLock);
+
+                if ((flags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+                        == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK) {
+                    int numberWakelock = mSustainedPerformanceUid.get(uid);
+                    mSustainedPerformanceUid.put(uid, numberWakelock + 1);
+                }
                 setWakeLockDisabledStateLocked(wakeLock);
                 notifyAcquire = true;
             }
@@ -879,6 +892,17 @@
                 mRequestWaitForNegativeProximity = true;
             }
 
+
+            if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+                    == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK) {
+                int numberWakelock = mSustainedPerformanceUid.get(wakeLock.mOwnerUid);
+                if (numberWakelock == 1) {
+                    mSustainedPerformanceUid.delete(wakeLock.mOwnerUid);
+                } else {
+                    mSustainedPerformanceUid.put(wakeLock.mOwnerUid, numberWakelock - 1);
+                }
+            }
+
             wakeLock.mLock.unlinkToDeath(wakeLock, 0);
             removeWakeLockLocked(wakeLock, index);
         }
@@ -1501,6 +1525,10 @@
                         break;
                     case PowerManager.DRAW_WAKE_LOCK:
                         mWakeLockSummary |= WAKE_LOCK_DRAW;
+                    case PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK:
+                        if (!wakeLock.mDisabled) {
+                            mWakeLockSummary |= WAKE_LOCK_SUSTAINED_PERFORMANCE;
+                        }
                         break;
                 }
             }
@@ -2198,6 +2226,14 @@
         if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
             setHalAutoSuspendModeLocked(true);
         }
+
+        if (mSustainedPerformanceMode
+                && (mWakeLockSummary & WAKE_LOCK_SUSTAINED_PERFORMANCE) == 0) {
+            setSustainedPerformanceModeLocked(false);
+        } else if (!mSustainedPerformanceMode
+                && (mWakeLockSummary & WAKE_LOCK_SUSTAINED_PERFORMANCE) != 0) {
+            setSustainedPerformanceModeLocked(true);
+        }
     }
 
     /**
@@ -2296,6 +2332,12 @@
         }
     }
 
+    private void setSustainedPerformanceModeLocked(boolean mode) {
+            mSustainedPerformanceMode = mode;
+            powerHintInternal(POWER_HINT_SUSTAINED_PERFORMANCE,
+                              mSustainedPerformanceMode ? 1 : 0);
+    }
+
     boolean isDeviceIdleModeInternal() {
         synchronized (mLock) {
             return mDeviceIdleMode;
@@ -2425,7 +2467,7 @@
     void updateUidProcStateInternal(int uid, int procState) {
         synchronized (mLock) {
             mUidState.put(uid, procState);
-            if (mDeviceIdleMode) {
+            if (mDeviceIdleMode || mSustainedPerformanceUid.get(uid) != 0) {
                 updateWakeLockDisabledStatesLocked();
             }
         }
@@ -2446,7 +2488,9 @@
         for (int i = 0; i < numWakeLocks; i++) {
             final WakeLock wakeLock = mWakeLocks.get(i);
             if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
-                    == PowerManager.PARTIAL_WAKE_LOCK) {
+                    == PowerManager.PARTIAL_WAKE_LOCK
+                    || (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+                    == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK) {
                 if (setWakeLockDisabledStateLocked(wakeLock)) {
                     changed = true;
                     if (wakeLock.mDisabled) {
@@ -2465,9 +2509,9 @@
     }
 
     private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) {
+        boolean disabled = false;
         if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
                 == PowerManager.PARTIAL_WAKE_LOCK) {
-            boolean disabled = false;
             if (mDeviceIdleMode) {
                 final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
                 // If we are in idle mode, we will ignore all partial wake locks that are
@@ -2481,10 +2525,16 @@
                     disabled = true;
                 }
             }
-            if (wakeLock.mDisabled != disabled) {
-                wakeLock.mDisabled = disabled;
-                return true;
-            }
+        } else if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
+                == PowerManager.SUSTAINED_PERFORMANCE_WAKE_LOCK
+                && mUidState.get(wakeLock.mOwnerUid,
+                                 ActivityManager.PROCESS_STATE_CACHED_EMPTY)
+                > ActivityManager.PROCESS_STATE_TOP) {
+            disabled = true;
+        }
+        if (wakeLock.mDisabled != disabled) {
+            wakeLock.mDisabled = disabled;
+            return true;
         }
         return false;
     }
@@ -2695,6 +2745,7 @@
             pw.println("  mBatteryLevelLow=" + mBatteryLevelLow);
             pw.println("  mLightDeviceIdleMode=" + mLightDeviceIdleMode);
             pw.println("  mDeviceIdleMode=" + mDeviceIdleMode);
+            pw.println("  mSustainedPerformanceMode=" + mSustainedPerformanceMode);
             pw.println("  mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
             pw.println("  mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
             pw.println("  mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
@@ -2809,6 +2860,14 @@
             pw.println();
             pw.println("Display Power: " + mDisplayPowerCallbacks);
 
+            pw.println();
+            pw.println("Sustained Performance UIDs:");
+            for (int i=0; i<mSustainedPerformanceUid.size(); i++) {
+                pw.print("  UID "); UserHandle.formatUid(pw, mSustainedPerformanceUid.keyAt(i));
+                pw.print(": "); pw.println(mSustainedPerformanceUid.valueAt(i));
+            }
+
+
             wcd = mWirelessChargerDetector;
         }
 
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 62e7fb4..318f966 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -71,6 +71,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.InputChannel;
@@ -779,15 +780,14 @@
         }
     }
 
-    private void notifyTvInputInfoChanged(UserState userState, String inputId,
-            TvInputInfo inputInfo) {
+    private void setTvInputInfoLocked(UserState userState, TvInputInfo inputInfo) {
         if (DEBUG) {
-            Slog.d(TAG, "notifyTvInputInfoChanged(inputId=" + inputId + ", inputInfo=" + inputInfo
-                    + ")");
+            Slog.d(TAG, "setTvInputInfoLocked(inputInfo=" + inputInfo + ")");
         }
+        // TODO: Also update the internal input list.
         for (ITvInputManagerCallback callback : userState.callbackSet) {
             try {
-                callback.onTvInputInfoChanged(inputId, inputInfo);
+                callback.onTvInputInfoChanged(inputInfo);
             } catch (RemoteException e) {
                 Slog.e(TAG, "failed to report changed input info to callback", e);
             }
@@ -846,6 +846,36 @@
             }
         }
 
+        public void setTvInputInfo(TvInputInfo inputInfo, int userId) {
+            String inputInfoPackageName = inputInfo.getServiceInfo().packageName;
+            String callingPackageName = getCallingPackageName();
+            if (!TextUtils.equals(inputInfoPackageName, callingPackageName)) {
+                throw new IllegalArgumentException("calling package " + callingPackageName
+                        + " is not allowed to change TvInputInfo for " + inputInfoPackageName);
+            }
+
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "setTvInputInfoChanged");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+                    setTvInputInfoLocked(userState, inputInfo);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        private String getCallingPackageName() {
+            final String[] packages = mContext.getPackageManager().getPackagesForUid(
+                    Binder.getCallingUid());
+            if (packages != null && packages.length > 0) {
+                return packages[0];
+            }
+            return "unknown";
+        }
+
         @Override
         public int getTvInputState(String inputId, int userId) {
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
@@ -2233,18 +2263,6 @@
                 }
             }
         }
-
-        @Override
-        public void setTvInputInfo(String inputId, TvInputInfo inputInfo) {
-            ensureValidInput(inputInfo);
-            synchronized (mLock) {
-                if (DEBUG) {
-                    Slog.d(TAG, "setTvInputInfo(" + inputInfo + ")");
-                }
-                UserState userState = getOrCreateUserStateLocked(mUserId);
-                notifyTvInputInfoChanged(userState, inputId, inputInfo);
-            }
-        }
     }
 
     private final class SessionCallback extends ITvInputSessionCallback.Stub {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 39983dd..c7d7096 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -42,6 +42,9 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -71,6 +74,7 @@
 import android.view.IWindowManager;
 import android.view.WindowManager;
 
+import java.io.BufferedOutputStream;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
@@ -96,7 +100,7 @@
 
 public class WallpaperManagerService extends IWallpaperManager.Stub {
     static final String TAG = "WallpaperManagerService";
-    static final boolean DEBUG = false;
+    static final boolean DEBUG = true;
 
     final Object mLock = new Object[0];
 
@@ -106,7 +110,8 @@
      */
     static final long MIN_WALLPAPER_CRASH_TIME = 10000;
     static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
-    static final String WALLPAPER = "wallpaper";
+    static final String WALLPAPER = "wallpaper_orig";
+    static final String WALLPAPER_CROP = "wallpaper";
     static final String WALLPAPER_INFO = "wallpaper_info.xml";
 
     /**
@@ -120,6 +125,7 @@
         final WallpaperData mWallpaper;
         final File mWallpaperDir;
         final File mWallpaperFile;
+        final File mWallpaperCropFile;
         final File mWallpaperInfoFile;
 
         public WallpaperObserver(WallpaperData wallpaper) {
@@ -128,6 +134,7 @@
             mWallpaperDir = getWallpaperDir(wallpaper.userId);
             mWallpaper = wallpaper;
             mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
+            mWallpaperCropFile = new File(mWallpaperDir, WALLPAPER_CROP);
             mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
         }
 
@@ -136,8 +143,10 @@
             if (path == null) {
                 return;
             }
+            final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
+            final File changedFile = new File(mWallpaperDir, path);
+
             synchronized (mLock) {
-                File changedFile = new File(mWallpaperDir, path);
                 if (mWallpaperFile.equals(changedFile)
                         || mWallpaperInfoFile.equals(changedFile)) {
                     // changing the wallpaper means we'll need to back up the new one
@@ -148,22 +157,111 @@
                 }
                 if (mWallpaperFile.equals(changedFile)) {
                     notifyCallbacksLocked(mWallpaper);
-                    final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
                     if (mWallpaper.wallpaperComponent == null
                             || event != CLOSE_WRITE // includes the MOVED_TO case
                             || mWallpaper.imageWallpaperPending) {
                         if (written) {
+                            // The image source has finished writing the source image,
+                            // so we now produce the crop rect (in the background), and
+                            // only publish the new displayable (sub)image as a result
+                            // of that work.
+                            generateCrop(mWallpaper);
                             mWallpaper.imageWallpaperPending = false;
+                            if (mWallpaper.setComplete != null) {
+                                try {
+                                    mWallpaper.setComplete.onWallpaperChanged();
+                                } catch (RemoteException e) {
+                                    // if this fails we don't really care; the setting app may just
+                                    // have crashed and that sort of thing is a fact of life.
+                                }
+                            }
+                            bindWallpaperComponentLocked(mImageWallpaper, true,
+                                    false, mWallpaper, null);
+                            saveSettingsLocked(mWallpaper);
                         }
-                        bindWallpaperComponentLocked(mImageWallpaper, true,
-                                false, mWallpaper, null);
-                        saveSettingsLocked(mWallpaper);
                     }
                 }
             }
         }
     }
 
+    /**
+     * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
+     * for display.
+     */
+    private void generateCrop(WallpaperData wallpaper) {
+        boolean success = false;
+        boolean needCrop = false;
+
+        // Analyse the source; needed in multiple cases
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true;
+        BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
+
+        // Legacy case uses an empty crop rect here, so we just preserve the
+        // source image verbatim
+        if (!wallpaper.cropHint.isEmpty()) {
+            // ...clamp the crop rect to the measured bounds...
+            wallpaper.cropHint.right = Math.min(wallpaper.cropHint.right, options.outWidth);
+            wallpaper.cropHint.bottom = Math.min(wallpaper.cropHint.bottom, options.outHeight);
+            // ...and don't bother cropping if what we're left with is identity
+            needCrop = (options.outHeight >= wallpaper.cropHint.height()
+                    && options.outWidth >= wallpaper.cropHint.width());
+        }
+
+        if (!needCrop) {
+            // Simple case:  the nominal crop is at least as big as the source image,
+            // so we take the whole thing and just copy the image file directly.
+            if (DEBUG) {
+                Slog.v(TAG, "Null crop of new wallpaper; copying");
+            }
+            success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+            if (!success) {
+                wallpaper.cropFile.delete();
+                // TODO: fall back to default wallpaper in this case
+            }
+        } else {
+            // Fancy case: the crop is a subrect of the source
+            FileOutputStream f = null;
+            BufferedOutputStream bos = null;
+            try {
+                BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
+                        wallpaper.wallpaperFile.getAbsolutePath(), false);
+                Bitmap cropped = decoder.decodeRegion(wallpaper.cropHint, null);
+                decoder.recycle();
+
+                if (cropped == null) {
+                    Slog.e(TAG, "Could not decode new wallpaper");
+                } else {
+                    f = new FileOutputStream(wallpaper.cropFile);
+                    bos = new BufferedOutputStream(f, 32*1024);
+                    cropped.compress(Bitmap.CompressFormat.PNG, 90, bos);
+                    bos.flush();  // don't rely on the implicit flush-at-close when noting success
+                    success = true;
+                }
+            } catch (IOException e) {
+                if (DEBUG) {
+                    Slog.e(TAG, "I/O error decoding crop: " + e.getMessage());
+                }
+            } finally {
+                IoUtils.closeQuietly(bos);
+                IoUtils.closeQuietly(f);
+            }
+        }
+
+        if (!success) {
+            Slog.e(TAG, "Unable to apply new wallpaper");
+            wallpaper.cropFile.delete();
+        }
+
+        if (wallpaper.cropFile.exists()) {
+            boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
+            if (DEBUG) {
+                Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
+            }
+        }
+    }
+
     final Context mContext;
     final IWindowManager mIWindowManager;
     final IPackageManager mIPackageManager;
@@ -191,7 +289,8 @@
 
         int userId;
 
-        File wallpaperFile;
+        final File wallpaperFile;
+        final File cropFile;
 
         /**
          * Client is currently writing a new image wallpaper.
@@ -199,6 +298,11 @@
         boolean imageWallpaperPending;
 
         /**
+         * Callback once the set + crop is finished
+         */
+        IWallpaperManagerCallback setComplete;
+
+        /**
          * Resource name if using a picture from the wallpaper gallery
          */
         String name = "";
@@ -232,11 +336,26 @@
         int width = -1;
         int height = -1;
 
+        /**
+         * The crop hint supplied for displaying a subset of the source image
+         */
+        final Rect cropHint = new Rect(0, 0, 0, 0);
+
         final Rect padding = new Rect(0, 0, 0, 0);
 
         WallpaperData(int userId) {
             this.userId = userId;
             wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
+            cropFile = new File(getWallpaperDir(userId), WALLPAPER_CROP);
+        }
+
+        // Only called in single-threaded boot sequence mode
+        boolean ensureCropExists() {
+            // if the crop file is not present, copy over the source image to use verbatim
+            if (!cropFile.exists()) {
+                return FileUtils.copyFile(wallpaperFile, cropFile);
+            }
+            return true;
         }
     }
 
@@ -524,6 +643,9 @@
     public void systemRunning() {
         if (DEBUG) Slog.v(TAG, "systemReady");
         WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
+        if (!wallpaper.ensureCropExists()) {
+            clearWallpaperLocked(false, UserHandle.USER_SYSTEM, null);
+        }
         switchWallpaper(wallpaper, null);
         wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
         wallpaper.wallpaperObserver.startWatching();
@@ -602,6 +724,8 @@
             onStoppingUser(userId);
             File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
             wallpaperFile.delete();
+            File cropFile = new File(getWallpaperDir(userId), WALLPAPER_CROP);
+            cropFile.delete();
             File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
             wallpaperInfoFile.delete();
         }
@@ -653,9 +777,9 @@
         if (wallpaper == null) {
             return;
         }
-        File f = new File(getWallpaperDir(userId), WALLPAPER);
-        if (f.exists()) {
-            f.delete();
+        if (wallpaper.wallpaperFile.exists()) {
+            wallpaper.wallpaperFile.delete();
+            wallpaper.cropFile.delete();
         }
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -844,11 +968,10 @@
                     outParams.putInt("height", wallpaper.height);
                 }
                 wallpaper.callbacks.register(cb);
-                File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
-                if (!f.exists()) {
+                if (!wallpaper.cropFile.exists()) {
                     return null;
                 }
-                return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
+                return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
             } catch (FileNotFoundException e) {
                 /* Shouldn't happen as we check to see if the file exists */
                 Slog.w(TAG, "Error getting wallpaper", e);
@@ -869,8 +992,8 @@
     }
 
     @Override
-    public ParcelFileDescriptor setWallpaper(String name, String callingPackage, Bundle extras,
-            int which) {
+    public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
+            Rect cropHint, Bundle extras, int which, IWallpaperManagerCallback completion) {
         checkPermission(android.Manifest.permission.SET_WALLPAPER);
 
         if (which == 0) {
@@ -881,6 +1004,17 @@
             return null;
         }
 
+        // "null" means the no-op crop, preserving the full input image
+        if (cropHint == null) {
+            cropHint = new Rect(0, 0, 0, 0);
+        } else {
+            if (cropHint.isEmpty()
+                    || cropHint.left < 0
+                    || cropHint.top < 0) {
+                return null;
+            }
+        }
+
         synchronized (mLock) {
             if (DEBUG) Slog.v(TAG, "setWallpaper");
             int userId = UserHandle.getCallingUserId();
@@ -890,6 +1024,8 @@
                 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
                 if (pfd != null) {
                     wallpaper.imageWallpaperPending = true;
+                    wallpaper.setComplete = completion;
+                    wallpaper.cropHint.set(cropHint);
                 }
                 return pfd;
             } finally {
@@ -1196,6 +1332,12 @@
             out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
             out.attribute(null, "width", Integer.toString(wallpaper.width));
             out.attribute(null, "height", Integer.toString(wallpaper.height));
+
+            out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
+            out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
+            out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
+            out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
+
             if (wallpaper.padding.left != 0) {
                 out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
             }
@@ -1208,6 +1350,7 @@
             if (wallpaper.padding.bottom != 0) {
                 out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
             }
+
             out.attribute(null, "name", wallpaper.name);
             if (wallpaper.wallpaperComponent != null
                     && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
@@ -1304,6 +1447,10 @@
                         wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
                         wallpaper.height = Integer.parseInt(parser
                                 .getAttributeValue(null, "height"));
+                        wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
+                        wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
+                        wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
+                        wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
                         wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
                         wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
                         wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
@@ -1322,6 +1469,7 @@
                         if (DEBUG) {
                             Slog.v(TAG, "mWidth:" + wallpaper.width);
                             Slog.v(TAG, "mHeight:" + wallpaper.height);
+                            Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
                             Slog.v(TAG, "mName:" + wallpaper.name);
                             Slog.v(TAG, "mNextWallpaperComponent:"
                                     + wallpaper.nextWallpaperComponent);
@@ -1348,6 +1496,7 @@
         if (!success) {
             wallpaper.width = -1;
             wallpaper.height = -1;
+            wallpaper.cropHint.set(0, 0, 0, 0);
             wallpaper.padding.set(0, 0, 0, 0);
             wallpaper.name = "";
         } else {
@@ -1368,6 +1517,11 @@
         if (wallpaper.height < baseSize) {
             wallpaper.height = baseSize;
         }
+        // and crop, if not previously specified
+        if (wallpaper.cropHint.width() <= 0
+                || wallpaper.cropHint.height() <= 0) {
+            wallpaper.cropHint.set(0, 0, wallpaper.width, wallpaper.height);
+        }
     }
 
     private int getMaximumSizeDimension() {
@@ -1431,6 +1585,7 @@
         }
     }
 
+    // Restore the named resource bitmap to both source + crop files
     boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
         if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
             String resName = wallpaper.name.substring(4);
@@ -1456,6 +1611,7 @@
                 int resId = -1;
                 InputStream res = null;
                 FileOutputStream fos = null;
+                FileOutputStream cos = null;
                 try {
                     Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
                     Resources r = c.getResources();
@@ -1469,13 +1625,16 @@
                     res = r.openRawResource(resId);
                     if (wallpaper.wallpaperFile.exists()) {
                         wallpaper.wallpaperFile.delete();
+                        wallpaper.cropFile.delete();
                     }
                     fos = new FileOutputStream(wallpaper.wallpaperFile);
+                    cos = new FileOutputStream(wallpaper.cropFile);
 
                     byte[] buffer = new byte[32768];
                     int amt;
                     while ((amt=res.read(buffer)) > 0) {
                         fos.write(buffer, 0, amt);
+                        cos.write(buffer, 0, amt);
                     }
                     // mWallpaperObserver will notice the close and send the change broadcast
 
@@ -1491,8 +1650,12 @@
                     IoUtils.closeQuietly(res);
                     if (fos != null) {
                         FileUtils.sync(fos);
-                        IoUtils.closeQuietly(fos);
                     }
+                    if (cos != null) {
+                        FileUtils.sync(cos);
+                    }
+                    IoUtils.closeQuietly(fos);
+                    IoUtils.closeQuietly(cos);
                 }
             }
         }
@@ -1520,6 +1683,7 @@
                     pw.print(wallpaper.width);
                     pw.print(" mHeight=");
                     pw.println(wallpaper.height);
+                pw.print("  mCropHint="); pw.println(wallpaper.cropHint);
                 pw.print("  mPadding="); pw.println(wallpaper.padding);
                 pw.print("  mName=");  pw.println(wallpaper.name);
                 pw.print("  mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 552af03..43a17c9 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -134,7 +134,7 @@
     /** Fraction of animation at which the recents thumbnail becomes completely transparent */
     private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.5f;
 
-    private static final int DEFAULT_APP_TRANSITION_DURATION = 336;
+    static final int DEFAULT_APP_TRANSITION_DURATION = 336;
     private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336;
     private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336;
     private static final long APP_TRANSITION_TIMEOUT_MS = 5000;
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
new file mode 100644
index 0000000..5f97478
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.view.animation.LinearInterpolator;
+
+/**
+ * Enables animating bounds of objects.
+ *
+ * In multi-window world bounds of both stack and tasks can change. When we need these bounds to
+ * change smoothly and not require the app to relaunch (e.g. because it handles resizes and
+ * relaunching it would cause poorer experience), these class provides a way to directly animate
+ * the bounds of the resized object.
+ *
+ * The object that is resized needs to implement {@link AnimateBoundsUser} interface.
+ */
+public class BoundsAnimationController {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "BoundsAnimationController" : TAG_WM;
+
+    // Only acccessed on UI thread.
+    private ArrayMap<AnimateBoundsUser, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
+
+    private final class BoundsAnimator extends ValueAnimator
+            implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
+        private final AnimateBoundsUser mTarget;
+        private final Rect mFrom;
+        private final Rect mTo;
+        private final Rect mTmpRect;
+
+        BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to) {
+            super();
+            mTarget = target;
+            mFrom = from;
+            mTo = to;
+            mTmpRect = new Rect();
+            addUpdateListener(this);
+            addListener(this);
+        }
+
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            final float value = (Float) animation.getAnimatedValue();
+            final float remains = 1 - value;
+            mTmpRect.left = (int) (mFrom.left * remains + mTo.left * value);
+            mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value);
+            mTmpRect.right = (int) (mFrom.right * remains + mTo.right * value);
+            mTmpRect.bottom = (int) (mFrom.bottom * remains + mTo.bottom * value);
+            if (DEBUG_ANIM) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + ", mBounds="
+                    + mTmpRect + ", from=" + mFrom + ", mTo=" + mTo + ", value=" + value
+                    + ", remains=" + remains);
+            if (!mTarget.setSize(mTmpRect)) {
+                // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
+                // any further animation.
+                animation.cancel();
+            }
+        }
+
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            finishAnimation();
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            finishAnimation();
+        }
+
+        private void finishAnimation() {
+            mTarget.finishBoundsAnimation();
+            removeListener(this);
+            removeUpdateListener(this);
+            mRunningAnimations.remove(mTarget);
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+
+        }
+    }
+
+    public interface AnimateBoundsUser {
+        /**
+         * Asks the target to directly (without any intermediate steps, like scheduling animation)
+         * resize its bounds.
+         *
+         * @return Whether the target still wants to be animated and successfully finished the
+         * operation. If it returns false, the animation will immediately be cancelled. The target
+         * should return false when something abnormal happened, e.g. it was completely removed
+         * from the hierarchy and is not valid anymore.
+         */
+        boolean setSize(Rect bounds);
+
+        /**
+         * Callback for the target to inform it that the animation is finished, so it can do some
+         * necessary cleanup.
+         */
+        void finishBoundsAnimation();
+    }
+
+    void animateBounds(AnimateBoundsUser target, Rect from, Rect to) {
+        final BoundsAnimator existing = mRunningAnimations.get(target);
+        if (existing != null) {
+            existing.cancel();
+        }
+        BoundsAnimator animator = new BoundsAnimator(target, from, to);
+        mRunningAnimations.put(target, animator);
+        animator.setFloatValues(0f, 1f);
+        animator.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+        animator.setInterpolator(new LinearInterpolator());
+        animator.start();
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 2833b35..e6fa837 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -20,6 +20,7 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Debug;
+import android.os.RemoteException;
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -47,7 +48,8 @@
 import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
-public class TaskStack implements DimLayer.DimLayerUser {
+public class TaskStack implements DimLayer.DimLayerUser,
+        BoundsAnimationController.AnimateBoundsUser {
 
     // If the stack should be resized to fullscreen.
     private static final boolean FULLSCREEN = true;
@@ -72,6 +74,12 @@
     /** Content limits relative to the DisplayContent this sits in. */
     private Rect mBounds = new Rect();
 
+    /** Screen content area excluding IM windows, etc. */
+    private final Rect mContentBounds = new Rect();
+
+    /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
+    private final Rect mAdjustedBounds = new Rect();
+
     /** Whether mBounds is fullscreen */
     private boolean mFullscreen = true;
 
@@ -162,6 +170,85 @@
         return mTmpRect.equals(bounds);
     }
 
+    void alignTasksToAdjustedBounds(final Rect adjustedBounds) {
+        if (mFullscreen) {
+            return;
+        }
+        // Update bounds of containing tasks.
+        for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+            final Task task = mTasks.get(taskNdx);
+            if (task.isTwoFingerScrollMode()) {
+                // If we're scrolling we don't care about your bounds or configs,
+                // they should be null as if we were in fullscreen.
+                task.resizeLocked(null, null, false /* forced */);
+                task.getBounds(mTmpRect2);
+                task.scrollLocked(mTmpRect2);
+            } else if (task.isResizeable()) {
+                task.getBounds(mTmpRect2);
+                mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
+                task.resizeLocked(mTmpRect2, task.mOverrideConfig, false /* forced */);
+            }
+        }
+    }
+
+    void adjustForIME(final WindowState imeWin) {
+        final int dockedSide = getDockSide();
+        final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
+        final Rect adjustedBounds = mAdjustedBounds;
+        if (imeWin == null || !dockedTopOrBottom) {
+            // If mContentBounds is already empty, it means we're not applying
+            // any adjustments, so nothing to do; otherwise clear any adjustments.
+            if (!mContentBounds.isEmpty()) {
+                mContentBounds.setEmpty();
+                adjustedBounds.set(mBounds);
+                alignTasksToAdjustedBounds(adjustedBounds);
+            }
+            return;
+        }
+
+        final Rect displayContentRect = mTmpRect;
+        final Rect contentBounds = mTmpRect2;
+
+        // Calculate the content bounds excluding the area occupied by IME
+        mDisplayContent.getContentRect(displayContentRect);
+        contentBounds.set(displayContentRect);
+        int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top);
+        imeTop += imeWin.getGivenContentInsetsLw().top;
+        if (contentBounds.bottom > imeTop) {
+            contentBounds.bottom = imeTop;
+        }
+
+        // If content bounds not changing, nothing to do.
+        if (mContentBounds.equals(contentBounds)) {
+            return;
+        }
+
+        // Content bounds changed, need to apply adjustments depending on dock sides.
+        mContentBounds.set(contentBounds);
+        adjustedBounds.set(mBounds);
+        final int yOffset = displayContentRect.bottom - contentBounds.bottom;
+
+        if (dockedSide == DOCKED_TOP) {
+            // If this stack is docked on top, we make it smaller so the bottom stack is not
+            // occluded by IME. We shift its bottom up by the height of the IME (capped by
+            // the display content rect). Note that we don't change the task bounds.
+            adjustedBounds.bottom = Math.max(
+                    adjustedBounds.bottom - yOffset, displayContentRect.top);
+        } else {
+            // If this stack is docked on bottom, we shift it up so that it's not occluded by
+            // IME. We try to move it up by the height of the IME window (although the best
+            // we could do is to make the top stack fully collapsed).
+            final int dividerWidth = mDisplayContent.mDividerControllerLocked.getContentWidth();
+            adjustedBounds.top = Math.max(
+                    adjustedBounds.top - yOffset, displayContentRect.top + dividerWidth);
+            adjustedBounds.bottom = adjustedBounds.top + mBounds.height();
+
+            // We also move the member tasks together, taking care not to resize them.
+            // Resizing might cause relaunch, and IME window may not come back after that.
+            alignTasksToAdjustedBounds(adjustedBounds);
+        }
+    }
+
     private boolean setBounds(Rect bounds) {
         boolean oldFullscreen = mFullscreen;
         int rotation = Surface.ROTATION_0;
@@ -191,6 +278,16 @@
 
         mBounds.set(bounds);
         mRotation = rotation;
+
+        // Clear the adjusted content bounds as they're no longer valid.
+        // If IME is still visible, these will be re-applied.
+        // Note that we don't clear mContentBounds here, so that we know the last IME
+        // adjust we applied.
+        // If user starts dragging the dock divider while IME is visible, the new bounds
+        // we received are based on the actual screen location of the divider. It already
+        // accounted for the IME window, so we don't want to adjust again.
+        mAdjustedBounds.set(mBounds);
+
         return true;
     }
 
@@ -215,9 +312,14 @@
 
     public void getBounds(Rect out) {
         if (useCurrentBounds()) {
-            // No need to adjust the output bounds if fullscreen or the docked stack is visible
+            // If we're currently adjusting for IME, we use the adjusted bounds; otherwise,
+            // no need to adjust the output bounds if fullscreen or the docked stack is visible
             // since it is already what we want to represent to the rest of the system.
-            out.set(mBounds);
+            if (!mContentBounds.isEmpty()) {
+                out.set(mAdjustedBounds);
+            } else {
+                out.set(mBounds);
+            }
             return;
         }
 
@@ -587,6 +689,7 @@
                 outBounds.top = dockedBounds.bottom + dockDividerWidth;
             }
         }
+        DockedDividerUtils.sanitizeStackBounds(outBounds);
     }
 
     /** Resizes all non-docked stacks in the system to either fullscreen or the appropriate size
@@ -803,4 +906,32 @@
         }
         return false;
     }
+
+    @Override  // AnimatesBounds
+    public boolean setSize(Rect bounds) {
+        synchronized (mService.mWindowMap) {
+            if (mDisplayContent == null) {
+                return false;
+            }
+        }
+        try {
+            mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false);
+        } catch (RemoteException e) {
+        }
+        return true;
+    }
+
+    @Override  // AnimatesBounds
+    public void finishBoundsAnimation() {
+        synchronized (mService.mWindowMap) {
+            if (mTasks.isEmpty()) {
+                return;
+            }
+            final Task task = mTasks.get(mTasks.size() - 1);
+            if (task != null) {
+                task.setDragResizing(false);
+                mService.requestTraversal();
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 0979cd3..66aa863 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -35,10 +35,10 @@
 
     static final boolean DEBUG_RESIZE = false;
     static final boolean DEBUG = false;
-    static final boolean DEBUG_ADD_REMOVE = false;
+    static final boolean DEBUG_ADD_REMOVE = true;
     static final boolean DEBUG_FOCUS = false;
     static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
-    static final boolean DEBUG_ANIM = false;
+    static final boolean DEBUG_ANIM = true;
     static final boolean DEBUG_KEYGUARD = false;
     static final boolean DEBUG_LAYOUT = false;
     static final boolean DEBUG_LAYERS = false;
@@ -50,7 +50,7 @@
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_APP_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
-    static final boolean DEBUG_APP_TRANSITIONS = false;
+    static final boolean DEBUG_APP_TRANSITIONS = true;
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 93a1015..e0e44dc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -157,9 +157,11 @@
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -643,6 +645,9 @@
 
     final WindowAnimator mAnimator;
 
+    private final BoundsAnimationController mBoundsAnimationController =
+            new BoundsAnimationController();
+
     SparseArray<Task> mTaskIdToTask = new SparseArray<>();
 
     /** All of the TaskStacks in the window manager, unordered. For an ordered list call
@@ -2848,11 +2853,12 @@
         if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
             win.prepareWindowToDisplayDuringRelayout(outConfig);
         }
-        if ((attrChanges& LayoutParams.FORMAT_CHANGED) != 0) {
-            // If the format can be changed in place yaay!
-            // If not, fall back to a surface re-build
+        if ((attrChanges & LayoutParams.FORMAT_CHANGED) != 0) {
+            // If the format can't be changed in place, preserve the old surface until the app draws
+            // on the new one. This prevents blinking when we change elevation of freeform and
+            // pinned windows.
             if (!winAnimator.tryChangeFormatInPlaceLocked()) {
-                winAnimator.destroySurfaceLocked();
+                winAnimator.preserveSurfaceLocked();
                 result |= RELAYOUT_RES_SURFACE_CHANGED
                         | WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
             }
@@ -8070,8 +8076,29 @@
                 }
                 case UPDATE_DOCKED_STACK_DIVIDER: {
                     synchronized (mWindowMap) {
-                        getDefaultDisplayContentLocked().getDockedDividerController()
-                                .reevaluateVisibility(false);
+                        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+
+                        displayContent.getDockedDividerController().reevaluateVisibility(false);
+
+                        final WindowState imeWin = mInputMethodWindow;
+                        final TaskStack focusedStack =
+                                mCurrentFocus != null ? mCurrentFocus.getStack() : null;
+                        if (imeWin != null && focusedStack != null && imeWin.isVisibleNow()
+                                && focusedStack.getDockSide() == DOCKED_BOTTOM){
+                            final ArrayList<TaskStack> stacks = displayContent.getStacks();
+                            for (int i = stacks.size() - 1; i >= 0; --i) {
+                                final TaskStack stack = stacks.get(i);
+                                if (stack.isVisibleLocked()) {
+                                    stack.adjustForIME(imeWin);
+                                }
+                            }
+                        } else {
+                            final ArrayList<TaskStack> stacks = displayContent.getStacks();
+                            for (int i = stacks.size() - 1; i >= 0; --i) {
+                                final TaskStack stack = stacks.get(i);
+                                stack.adjustForIME(null);
+                            }
+                        }
                     }
                 }
                 break;
@@ -8085,7 +8112,8 @@
                 break;
                 case RESIZE_STACK: {
                     try {
-                        mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj, msg.arg2 == 1);
+                        mActivityManager.resizeStack(msg.arg1, (Rect) msg.obj, msg.arg2 == 1, false,
+                                false);
                     } catch (RemoteException e) {
                         // This will not happen since we are in the same process.
                     }
@@ -10273,6 +10301,31 @@
         }
     }
 
+    public void animateResizePinnedStack(final Rect bounds) {
+        synchronized (mWindowMap) {
+            final TaskStack stack = mStackIdToStack.get(PINNED_STACK_ID);
+            if (stack == null) {
+                Slog.w(TAG, "animateResizePinnedStack: stackId " + PINNED_STACK_ID + " not found.");
+                return;
+            }
+            final ArrayList<Task> tasks = stack.getTasks();
+            if (tasks.isEmpty()) {
+                Slog.w(TAG, "animateResizePinnedStack: pinned stack doesn't have any tasks.");
+                return;
+            }
+            final Task task = tasks.get(tasks.size() - 1);
+            task.setDragResizing(true);
+            final Rect originalBounds = new Rect();
+            stack.getBounds(originalBounds);
+            UiThread.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    mBoundsAnimationController.animateBounds(stack, originalBounds, bounds);
+                }
+            });
+        }
+    }
+
     public void setTaskResizeable(int taskId, boolean resizeable) {
         synchronized (mWindowMap) {
             Task task = mTaskIdToTask.get(taskId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e8de90c..4dd2b4d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -57,6 +57,7 @@
 import java.util.ArrayList;
 
 import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
@@ -750,15 +751,16 @@
                     Math.min(mStableFrame.bottom, frame.bottom));
         }
 
-        mOverscanInsets.set(Math.max(mOverscanFrame.left - frame.left, 0),
-                Math.max(mOverscanFrame.top - frame.top, 0),
-                Math.max(frame.right - mOverscanFrame.right, 0),
-                Math.max(frame.bottom - mOverscanFrame.bottom, 0));
-
-
+        if (!inFreeformWorkspace()) {
+            // Freeform windows can be positioned outside of the display frame, but that is not a
+            // reason to provide them with overscan insets.
+            mOverscanInsets.set(Math.max(mOverscanFrame.left - frame.left, 0),
+                    Math.max(mOverscanFrame.top - frame.top, 0),
+                    Math.max(frame.right - mOverscanFrame.right, 0),
+                    Math.max(frame.bottom - mOverscanFrame.bottom, 0));
+        }
 
         if (mAttrs.type == TYPE_DOCK_DIVIDER) {
-
             // For the docked divider, we calculate the stable insets like a full-screen window
             // so it can use it to calculate the snap positions.
             mStableInsets.set(Math.max(mStableFrame.left - mDisplayFrame.left, 0),
@@ -2051,17 +2053,29 @@
         // until the window to small size, otherwise the multithread renderer will shift last
         // one or more frame to wrong offset. So here we send fullscreen backdrop if either
         // isDragResizing() or isDragResizeChanged() is true.
+        boolean resizing = isDragResizing() || isDragResizeChanged();
+        if (StackId.useWindowFrameForBackdrop(getStackId()) || !resizing) {
+            return frame;
+        }
         DisplayInfo displayInfo = getDisplayInfo();
         mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
-        boolean resizing = isDragResizing() || isDragResizeChanged();
-        return (inFreeformWorkspace() || !resizing) ? frame : mTmpRect;
+        return mTmpRect;
+    }
+
+    private int getStackId() {
+        final TaskStack stack = getStack();
+        if (stack == null) {
+            return INVALID_STACK_ID;
+        }
+        return stack.mStackId;
     }
 
     private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
             Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
             Configuration newConfig) throws RemoteException {
         mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
-                reportDraw, newConfig, getBackdropFrame(frame));
+                reportDraw, newConfig, getBackdropFrame(frame),
+                isDragResizeChanged() /* forceRelayout */);
     }
 
     public void registerFocusObserver(IWindowFocusObserver observer) {
@@ -2225,7 +2239,8 @@
         }
         pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
                 pw.print(" mShownPosition="); mShownPosition.printShortString(pw);
-                pw.print(" isReadyForDisplay()="); pw.println(isReadyForDisplay());
+                pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay());
+                pw.print(" hasSavedSurface()="); pw.println(hasSavedSurface());
         if (dumpAll) {
             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
                     pw.print(" last="); mLastFrame.printShortString(pw);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index cffcc5d..428ab7a 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -567,6 +567,10 @@
 
     WindowSurfaceController createSurfaceLocked() {
         final WindowState w = mWin;
+        if (w.hasSavedSurface()) {
+            Slog.i(TAG, "***** createSurface: " + this + ": called when we had a saved surface");
+        }
+
         if (mSurfaceController == null) {
             if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
                     "createSurface " + this + ": mDrawState=DRAW_PENDING");
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 98d8d08..d1b8648 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -22,7 +22,7 @@
     $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \
     $(LOCAL_REL_DIR)/com_android_server_lights_LightsService.cpp \
-    $(LOCAL_REL_DIR)/com_android_server_location_GpsLocationProvider.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_location_GnssLocationProvider.cpp \
     $(LOCAL_REL_DIR)/com_android_server_location_FlpHardwareProvider.cpp \
     $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
similarity index 79%
rename from services/core/jni/com_android_server_location_GpsLocationProvider.cpp
rename to services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index b8d4196..0c85a15 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "GpsLocationProvider"
+#define LOG_TAG "GnssLocationProvider"
 
 #define LOG_NDEBUG 0
 
 #include "JNIHelp.h"
 #include "jni.h"
 #include "hardware/hardware.h"
-#include "hardware/gps.h"
+#include "hardware/gps_internal.h"
 #include "hardware_legacy/power.h"
 #include "utils/Log.h"
 #include "utils/misc.h"
@@ -42,6 +42,7 @@
 static jmethodID method_reportAGpsStatus;
 static jmethodID method_reportNmea;
 static jmethodID method_setEngineCapabilities;
+static jmethodID method_setGpsYearOfHardware;
 static jmethodID method_xtraDownloadRequest;
 static jmethodID method_reportNiNotification;
 static jmethodID method_requestRefLocation;
@@ -67,8 +68,14 @@
 static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
 static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
 
+#define MAX_SATELLITE_COUNT 512
+#define MAX_GPS_SATELLITE_COUNT 512
+
+#define PRN_SHIFT_WIDTH 3
+
 // temporary storage for GPS callbacks
-static GpsSvStatus  sGpsSvStatus;
+static GnssSvInfo sGnssSvList[MAX_SATELLITE_COUNT];
+static size_t sGnssSvListSize;
 static const char* sNmeaString;
 static int sNmeaStringLength;
 
@@ -105,7 +112,57 @@
 static void sv_status_callback(GpsSvStatus* sv_status)
 {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
-    memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus));
+    size_t status_size = sv_status->size;
+    // Some drive doesn't set the size field correctly. Assume GpsSvStatus_v1 if
+    // it doesn't provide a valid size.
+    if (status_size == 0) {
+        status_size = sizeof(GpsSvStatus_v1);
+    }
+    if (status_size == sizeof(GpsSvStatus)) {
+        sGnssSvListSize = sv_status->gnss_sv_list_size;
+        // Cramp the list size
+        if (sGnssSvListSize > MAX_SATELLITE_COUNT) {
+            sGnssSvListSize = MAX_SATELLITE_COUNT;
+        }
+        // Copy GNSS SV info into sGnssSvList, if any.
+        if (sGnssSvListSize > 0 && sv_status->gnss_sv_list) {
+            memcpy(sGnssSvList, sv_status->gnss_sv_list, sizeof(GnssSvInfo) * sGnssSvListSize);
+        }
+    } else if (status_size == sizeof(GpsSvStatus_v1)) {
+        sGnssSvListSize = sv_status->num_svs;
+        // Cramp the list size
+        if (sGnssSvListSize > MAX_GPS_SATELLITE_COUNT) {
+            sGnssSvListSize = MAX_GPS_SATELLITE_COUNT;
+        }
+        uint32_t ephemeris_mask = sv_status->ephemeris_mask;
+        uint32_t almanac_mask = sv_status->almanac_mask;
+        uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
+        for (size_t i = 0; i < sGnssSvListSize; i++) {
+            GnssSvInfo& info = sGnssSvList[i];
+            info.constellation = GNSS_CONSTELLATION_GPS;
+            info.prn = sv_status->sv_list[i].prn;
+            info.snr = sv_status->sv_list[i].snr;
+            info.elevation = sv_status->sv_list[i].elevation;
+            info.azimuth = sv_status->sv_list[i].azimuth;
+            info.flags = GNSS_SV_FLAGS_NONE;
+            if (info.prn > 0 && info.prn <= 32) {
+              int32_t this_prn_mask = (1 << (info.prn - 1));
+              if ((ephemeris_mask & this_prn_mask) != 0) {
+                info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
+              }
+              if ((almanac_mask & this_prn_mask) != 0) {
+                info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
+              }
+              if ((used_in_fix_mask & this_prn_mask) != 0) {
+                info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
+              }
+            }
+        }
+    } else {
+        sGnssSvListSize = 0;
+        ALOGE("Invalid size of GpsSvStatus found: %zd.", status_size);
+        return;
+    }
     env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
@@ -121,6 +178,14 @@
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
 
+static void set_system_info_callback(const GpsSystemInfo* info) {
+    ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mCallbacksObj, method_setGpsYearOfHardware,
+                        info->year_of_hw);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
 static void set_capabilities_callback(uint32_t capabilities)
 {
     ALOGD("set_capabilities_callback: %du\n", capabilities);
@@ -162,6 +227,7 @@
     release_wakelock_callback,
     create_thread_callback,
     request_utc_time_callback,
+    set_system_info_callback,
 };
 
 static void xtra_download_request_callback()
@@ -213,7 +279,7 @@
     bool isSupported = false;
 
     size_t status_size = agps_status->size;
-    if (status_size == sizeof(AGpsStatus_v3)) {
+    if (status_size == sizeof(AGpsStatus)) {
       ALOGV("AGpsStatus is V3: %zd", status_size);
       switch (agps_status->addr.ss_family)
       {
@@ -439,7 +505,7 @@
     create_thread_callback,
 };
 
-static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
     int err;
     hw_module_t* module;
 
@@ -449,6 +515,7 @@
     method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
     method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
     method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
+    method_setGpsYearOfHardware = env->GetMethodID(clazz, "setGpsYearOfHardware", "(I)V");
     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
     method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
             "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
@@ -509,13 +576,13 @@
     }
 }
 
-static jboolean android_location_GpsLocationProvider_is_supported(
+static jboolean android_location_GnssLocationProvider_is_supported(
         JNIEnv* /* env */, jclass /* clazz */)
 {
     return (sGpsInterface != NULL) ?  JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_is_agps_ril_supported(
+static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
         JNIEnv* /* env */, jclass /* clazz */)
 {
     return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
@@ -527,7 +594,7 @@
     return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
+static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
 {
     // this must be set before calling into the HAL library
     if (!mCallbacksObj)
@@ -553,13 +620,13 @@
     return JNI_TRUE;
 }
 
-static void android_location_GpsLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
+static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
 {
     if (sGpsInterface)
         sGpsInterface->cleanup();
 }
 
-static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* /* env */,
+static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
         jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
         jint preferred_time)
 {
@@ -575,7 +642,7 @@
         return JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
+static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
 {
     if (sGpsInterface) {
         if (sGpsInterface->start() == 0) {
@@ -588,7 +655,7 @@
         return JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
+static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
 {
     if (sGpsInterface) {
         if (sGpsInterface->stop() == 0) {
@@ -601,7 +668,7 @@
         return JNI_FALSE;
 }
 
-static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* /* env */,
+static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
                                                                     jobject /* obj */,
                                                                     jint flags)
 {
@@ -609,38 +676,36 @@
         sGpsInterface->delete_aiding_data(flags);
 }
 
-static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
-        jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray,
-        jintArray maskArray)
+static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
+        jintArray prnWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
+        jfloatArray azumArray, jintArray constellationTypeArray)
 {
     // this should only be called from within a call to reportSvStatus
-
-    jint* prns = env->GetIntArrayElements(prnArray, 0);
+    jint* prnWithFlags = env->GetIntArrayElements(prnWithFlagArray, 0);
     jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
-    jint* mask = env->GetIntArrayElements(maskArray, 0);
+    jint* constellationTypes = env->GetIntArrayElements(constellationTypeArray, 0);
 
-    int num_svs = sGpsSvStatus.num_svs;
-    for (int i = 0; i < num_svs; i++) {
-        prns[i] = sGpsSvStatus.sv_list[i].prn;
-        snrs[i] = sGpsSvStatus.sv_list[i].snr;
-        elev[i] = sGpsSvStatus.sv_list[i].elevation;
-        azim[i] = sGpsSvStatus.sv_list[i].azimuth;
+    // GNSS SV info.
+    for (size_t i = 0; i < sGnssSvListSize; ++i) {
+        const GnssSvInfo& info = sGnssSvList[i];
+        constellationTypes[i] = info.constellation;
+        prnWithFlags[i] = (info.prn << PRN_SHIFT_WIDTH) | info.flags;
+        snrs[i] = info.snr;
+        elev[i] = info.elevation;
+        azim[i] = info.azimuth;
     }
-    mask[0] = sGpsSvStatus.ephemeris_mask;
-    mask[1] = sGpsSvStatus.almanac_mask;
-    mask[2] = sGpsSvStatus.used_in_fix_mask;
 
-    env->ReleaseIntArrayElements(prnArray, prns, 0);
+    env->ReleaseIntArrayElements(prnWithFlagArray, prnWithFlags, 0);
     env->ReleaseFloatArrayElements(snrArray, snrs, 0);
     env->ReleaseFloatArrayElements(elevArray, elev, 0);
     env->ReleaseFloatArrayElements(azumArray, azim, 0);
-    env->ReleaseIntArrayElements(maskArray, mask, 0);
-    return (jint) num_svs;
+    env->ReleaseIntArrayElements(constellationTypeArray, constellationTypes, 0);
+    return (jint) sGnssSvListSize;
 }
 
-static void android_location_GpsLocationProvider_agps_set_reference_location_cellid(
+static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
         JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
 {
     AGpsRefLocation location;
@@ -667,7 +732,7 @@
     sAGpsRilInterface->set_ref_location(&location, sizeof(location));
 }
 
-static void android_location_GpsLocationProvider_agps_send_ni_message(JNIEnv* env,
+static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
         jobject /* obj */, jbyteArray ni_msg, jint size)
 {
     size_t sz;
@@ -684,7 +749,7 @@
     env->ReleaseByteArrayElements(ni_msg,b,0);
 }
 
-static void android_location_GpsLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
+static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
                                                              jint type, jstring  setid_string)
 {
     if (!sAGpsRilInterface) {
@@ -697,7 +762,7 @@
     env->ReleaseStringUTFChars(setid_string, setid);
 }
 
-static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
+static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
                                             jbyteArray nmeaArray, jint buffer_size)
 {
     // this should only be called from within a call to reportNmea
@@ -710,27 +775,27 @@
     return (jint) length;
 }
 
-static void android_location_GpsLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
+static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
         jlong time, jlong timeReference, jint uncertainty)
 {
     if (sGpsInterface)
         sGpsInterface->inject_time(time, timeReference, uncertainty);
 }
 
-static void android_location_GpsLocationProvider_inject_location(JNIEnv* /* env */,
+static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
         jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
 {
     if (sGpsInterface)
         sGpsInterface->inject_location(latitude, longitude, accuracy);
 }
 
-static jboolean android_location_GpsLocationProvider_supports_xtra(
+static jboolean android_location_GnssLocationProvider_supports_xtra(
         JNIEnv* /* env */, jobject /* obj */)
 {
     return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
 }
 
-static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
+static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
         jbyteArray data, jint length)
 {
     if (!sGpsXtraInterface) {
@@ -743,7 +808,7 @@
     env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
 }
 
-static void android_location_GpsLocationProvider_agps_data_conn_open(
+static void android_location_GnssLocationProvider_agps_data_conn_open(
         JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
 {
     if (!sAGpsInterface) {
@@ -758,7 +823,7 @@
     const char *apnStr = env->GetStringUTFChars(apn, NULL);
 
     size_t interface_size = sAGpsInterface->size;
-    if (interface_size == sizeof(AGpsInterface_v2)) {
+    if (interface_size == sizeof(AGpsInterface)) {
         sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
     } else if (interface_size == sizeof(AGpsInterface_v1)) {
         sAGpsInterface->data_conn_open(apnStr);
@@ -769,7 +834,7 @@
     env->ReleaseStringUTFChars(apn, apnStr);
 }
 
-static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
+static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
                                                                        jobject /* obj */)
 {
     if (!sAGpsInterface) {
@@ -779,7 +844,7 @@
     sAGpsInterface->data_conn_closed();
 }
 
-static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
+static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
                                                                        jobject /* obj */)
 {
     if (!sAGpsInterface) {
@@ -789,7 +854,7 @@
     sAGpsInterface->data_conn_failed();
 }
 
-static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
+static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
         jint type, jstring hostname, jint port)
 {
     if (!sAGpsInterface) {
@@ -801,7 +866,7 @@
     env->ReleaseStringUTFChars(hostname, c_hostname);
 }
 
-static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* /* env */,
+static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
       jobject /* obj */, jint notifId, jint response)
 {
     if (!sGpsNiInterface) {
@@ -812,7 +877,7 @@
     sGpsNiInterface->respond(notifId, response);
 }
 
-static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* env,
+static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
                                                                        jobject /* obj */) {
     jstring result = NULL;
     if (sGpsDebugInterface) {
@@ -826,7 +891,7 @@
     return result;
 }
 
-static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
+static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
         jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
 {
 
@@ -849,13 +914,13 @@
     }
 }
 
-static jboolean android_location_GpsLocationProvider_is_geofence_supported(
+static jboolean android_location_GnssLocationProvider_is_geofence_supported(
         JNIEnv* /* env */, jobject /* obj */)
 {
     return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_add_geofence(JNIEnv* /* env */,
+static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
         jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
         jint last_transition, jint monitor_transition, jint notification_responsiveness,
         jint unknown_timer) {
@@ -870,7 +935,7 @@
     return JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_remove_geofence(JNIEnv* /* env */,
+static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
         jobject /* obj */, jint geofence_id) {
     if (sGpsGeofencingInterface != NULL) {
         sGpsGeofencingInterface->remove_geofence_area(geofence_id);
@@ -881,7 +946,7 @@
     return JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_pause_geofence(JNIEnv* /* env */,
+static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
         jobject /* obj */, jint geofence_id) {
     if (sGpsGeofencingInterface != NULL) {
         sGpsGeofencingInterface->pause_geofence(geofence_id);
@@ -892,7 +957,7 @@
     return JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_resume_geofence(JNIEnv* /* env */,
+static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
         jobject /* obj */, jint geofence_id, jint monitor_transition) {
     if (sGpsGeofencingInterface != NULL) {
         sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
@@ -903,10 +968,12 @@
     return JNI_FALSE;
 }
 
-static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
+static jobject translate_gps_clock(JNIEnv* env, void* data, size_t size) {
     const char* doubleSignature = "(D)V";
     const char* longSignature = "(J)V";
 
+    GpsClock* clock = reinterpret_cast<GpsClock*>(data);
+
     jclass gpsClockClass = env->FindClass("android/location/GpsClock");
     jmethodID gpsClockCtor = env->GetMethodID(gpsClockClass, "<init>", "()V");
 
@@ -958,11 +1025,23 @@
         env->CallVoidMethod(gpsClockObject, setterMethod, clock->drift_uncertainty_nsps);
     }
 
+    if (flags & GPS_CLOCK_TYPE_LOCAL_HW_TIME) {
+        if (size == sizeof(GpsClock)) {
+            jmethodID setterMethod =
+                    env->GetMethodID(gpsClockClass,
+                                     "setTimeOfLastHwClockDiscontinuityInNs",
+                                     longSignature);
+            env->CallVoidMethod(gpsClockObject,
+                                setterMethod,
+                                clock->time_of_last_hw_clock_discontinuity_ns);
+        }
+    }
+
     env->DeleteLocalRef(gpsClockClass);
     return gpsClockObject;
 }
 
-static jobject translate_gps_measurement(JNIEnv* env, GpsMeasurement* measurement) {
+static jobject translate_gps_measurement(JNIEnv* env, void* data, size_t size) {
     const char* byteSignature = "(B)V";
     const char* shortSignature = "(S)V";
     const char* intSignature = "(I)V";
@@ -972,6 +1051,7 @@
 
     jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement");
     jmethodID gpsMeasurementCtor = env->GetMethodID(gpsMeasurementClass, "<init>", "()V");
+    GpsMeasurement* measurement = reinterpret_cast<GpsMeasurement*>(data);
 
     jobject gpsMeasurementObject = env->NewObject(gpsMeasurementClass, gpsMeasurementCtor);
     GpsMeasurementFlags flags = measurement->flags;
@@ -1205,12 +1285,38 @@
             usedInFixSetterMethod,
             (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
 
+    if (size == sizeof(GpsMeasurement)) {
+      jmethodID setterMethod =
+          env->GetMethodID(gpsMeasurementClass,
+                           "setPseudorangeRateCarrierInMetersPerSec",
+                           doubleSignature);
+      env->CallVoidMethod(
+          gpsMeasurementObject,
+          setterMethod,
+          measurement->pseudorange_rate_carrier_mps);
+
+      setterMethod =
+          env->GetMethodID(gpsMeasurementClass,
+                           "setPseudorangeRateCarrierUncertaintyInMetersPerSec",
+                           doubleSignature);
+      env->CallVoidMethod(
+          gpsMeasurementObject,
+          setterMethod,
+          measurement->pseudorange_rate_carrier_uncertainty_mps);
+    }
+
     env->DeleteLocalRef(gpsMeasurementClass);
     return gpsMeasurementObject;
 }
 
-static jobjectArray translate_gps_measurements(JNIEnv* env, GpsData* data) {
-    size_t measurementCount = data->measurement_count;
+/**
+ * <T> can only be GpsData or GpsData_v1. Must rewrite this function if more
+ * types are introduced in the future releases.
+ */
+template<class T>
+static jobjectArray translate_gps_measurements(JNIEnv* env, void* data) {
+    T* gps_data = reinterpret_cast<T*>(data);
+    size_t measurementCount = gps_data->measurement_count;
     if (measurementCount == 0) {
         return NULL;
     }
@@ -1221,9 +1327,11 @@
             gpsMeasurementClass,
             NULL /* initialElement */);
 
-    GpsMeasurement* gpsMeasurements = data->measurements;
     for (uint16_t i = 0; i < measurementCount; ++i) {
-        jobject gpsMeasurement = translate_gps_measurement(env, &gpsMeasurements[i]);
+        jobject gpsMeasurement = translate_gps_measurement(
+            env,
+            &(gps_data->measurements[i]),
+            sizeof(gps_data->measurements[0]));
         env->SetObjectArrayElement(gpsMeasurementArray, i, gpsMeasurement);
         env->DeleteLocalRef(gpsMeasurement);
     }
@@ -1238,33 +1346,39 @@
         ALOGE("Invalid data provided to gps_measurement_callback");
         return;
     }
-
-    if (data->size == sizeof(GpsData)) {
-        jobject gpsClock = translate_gps_clock(env, &data->clock);
-        jobjectArray measurementArray = translate_gps_measurements(env, data);
-
-        jclass gpsMeasurementsEventClass = env->FindClass("android/location/GpsMeasurementsEvent");
-        jmethodID gpsMeasurementsEventCtor = env->GetMethodID(
-                gpsMeasurementsEventClass,
-                "<init>",
-                "(Landroid/location/GpsClock;[Landroid/location/GpsMeasurement;)V");
-
-        jobject gpsMeasurementsEvent = env->NewObject(
-                gpsMeasurementsEventClass,
-                gpsMeasurementsEventCtor,
-                gpsClock,
-                measurementArray);
-
-        env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gpsMeasurementsEvent);
-        checkAndClearExceptionFromCallback(env, __FUNCTION__);
-
-        env->DeleteLocalRef(gpsClock);
-        env->DeleteLocalRef(measurementArray);
-        env->DeleteLocalRef(gpsMeasurementsEventClass);
-        env->DeleteLocalRef(gpsMeasurementsEvent);
-    } else {
+    if (data->size != sizeof(GpsData) && data->size != sizeof(GpsData_v1)) {
         ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%zd", data->size);
+        return;
     }
+
+    jobject gpsClock;
+    jobjectArray measurementArray;
+    if (data->size == sizeof(GpsData)) {
+        gpsClock = translate_gps_clock(env, &data->clock, sizeof(GpsClock));
+        measurementArray = translate_gps_measurements<GpsData>(env, data);
+    } else {
+        gpsClock = translate_gps_clock(env, &data->clock, sizeof(GpsClock_v1));
+        measurementArray = translate_gps_measurements<GpsData_v1>(env, data);
+    }
+    jclass gpsMeasurementsEventClass = env->FindClass("android/location/GpsMeasurementsEvent");
+    jmethodID gpsMeasurementsEventCtor = env->GetMethodID(
+        gpsMeasurementsEventClass,
+        "<init>",
+        "(Landroid/location/GpsClock;[Landroid/location/GpsMeasurement;)V");
+
+    jobject gpsMeasurementsEvent = env->NewObject(
+        gpsMeasurementsEventClass,
+        gpsMeasurementsEventCtor,
+        gpsClock,
+        measurementArray);
+
+    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gpsMeasurementsEvent);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+    env->DeleteLocalRef(gpsClock);
+    env->DeleteLocalRef(measurementArray);
+    env->DeleteLocalRef(gpsMeasurementsEventClass);
+    env->DeleteLocalRef(gpsMeasurementsEvent);
 }
 
 GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
@@ -1272,7 +1386,7 @@
     measurement_callback,
 };
 
-static jboolean android_location_GpsLocationProvider_is_measurement_supported(
+static jboolean android_location_GnssLocationProvider_is_measurement_supported(
         JNIEnv* env,
         jclass clazz) {
     if (sGpsMeasurementInterface != NULL) {
@@ -1281,7 +1395,7 @@
     return JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_start_measurement_collection(
+static jboolean android_location_GnssLocationProvider_start_measurement_collection(
         JNIEnv* env,
         jobject obj) {
     if (sGpsMeasurementInterface == NULL) {
@@ -1298,7 +1412,7 @@
     return JNI_TRUE;
 }
 
-static jboolean android_location_GpsLocationProvider_stop_measurement_collection(
+static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
         JNIEnv* env,
         jobject obj) {
     if (sGpsMeasurementInterface == NULL) {
@@ -1382,7 +1496,7 @@
     navigation_message_callback,
 };
 
-static jboolean android_location_GpsLocationProvider_is_navigation_message_supported(
+static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
         JNIEnv* env,
         jclass clazz) {
     if(sGpsNavigationMessageInterface != NULL) {
@@ -1391,7 +1505,7 @@
     return JNI_FALSE;
 }
 
-static jboolean android_location_GpsLocationProvider_start_navigation_message_collection(
+static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
         JNIEnv* env,
         jobject obj) {
     if (sGpsNavigationMessageInterface == NULL) {
@@ -1408,7 +1522,7 @@
     return JNI_TRUE;
 }
 
-static jboolean android_location_GpsLocationProvider_stop_navigation_message_collection(
+static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
         JNIEnv* env,
         jobject obj) {
     if (sGpsNavigationMessageInterface == NULL) {
@@ -1420,7 +1534,7 @@
     return JNI_TRUE;
 }
 
-static void android_location_GpsLocationProvider_configuration_update(JNIEnv* env, jobject obj,
+static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
         jstring config_content)
 {
     if (!sGnssConfigurationInterface) {
@@ -1436,105 +1550,105 @@
 
 static const JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
-    {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
-    {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
+    {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
+    {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
     {"native_is_agps_ril_supported", "()Z",
-            (void*)android_location_GpsLocationProvider_is_agps_ril_supported},
+            (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
     {"native_is_gnss_configuration_supported", "()Z",
             (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
-    {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
-    {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
+    {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
+    {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
     {"native_set_position_mode",
             "(IIIII)Z",
-            (void*)android_location_GpsLocationProvider_set_position_mode},
-    {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start},
-    {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
+            (void*)android_location_GnssLocationProvider_set_position_mode},
+    {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
+    {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
     {"native_delete_aiding_data",
             "(I)V",
-            (void*)android_location_GpsLocationProvider_delete_aiding_data},
+            (void*)android_location_GnssLocationProvider_delete_aiding_data},
     {"native_read_sv_status",
             "([I[F[F[F[I)I",
-            (void*)android_location_GpsLocationProvider_read_sv_status},
-    {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea},
-    {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
+            (void*)android_location_GnssLocationProvider_read_sv_status},
+    {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
+    {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
     {"native_inject_location",
             "(DDF)V",
-            (void*)android_location_GpsLocationProvider_inject_location},
-    {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
+            (void*)android_location_GnssLocationProvider_inject_location},
+    {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
     {"native_inject_xtra_data",
             "([BI)V",
-            (void*)android_location_GpsLocationProvider_inject_xtra_data},
+            (void*)android_location_GnssLocationProvider_inject_xtra_data},
     {"native_agps_data_conn_open",
             "(Ljava/lang/String;I)V",
-            (void*)android_location_GpsLocationProvider_agps_data_conn_open},
+            (void*)android_location_GnssLocationProvider_agps_data_conn_open},
     {"native_agps_data_conn_closed",
             "()V",
-            (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
+            (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
     {"native_agps_data_conn_failed",
             "()V",
-            (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
+            (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
     {"native_agps_set_id",
             "(ILjava/lang/String;)V",
-            (void*)android_location_GpsLocationProvider_agps_set_id},
+            (void*)android_location_GnssLocationProvider_agps_set_id},
     {"native_agps_set_ref_location_cellid",
             "(IIIII)V",
-            (void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},
+            (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
     {"native_set_agps_server",
             "(ILjava/lang/String;I)V",
-            (void*)android_location_GpsLocationProvider_set_agps_server},
+            (void*)android_location_GnssLocationProvider_set_agps_server},
     {"native_send_ni_response",
             "(II)V",
-            (void*)android_location_GpsLocationProvider_send_ni_response},
+            (void*)android_location_GnssLocationProvider_send_ni_response},
     {"native_agps_ni_message",
             "([BI)V",
-            (void *)android_location_GpsLocationProvider_agps_send_ni_message},
+            (void *)android_location_GnssLocationProvider_agps_send_ni_message},
     {"native_get_internal_state",
             "()Ljava/lang/String;",
-            (void*)android_location_GpsLocationProvider_get_internal_state},
+            (void*)android_location_GnssLocationProvider_get_internal_state},
     {"native_update_network_state",
             "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
-            (void*)android_location_GpsLocationProvider_update_network_state },
+            (void*)android_location_GnssLocationProvider_update_network_state },
     {"native_is_geofence_supported",
             "()Z",
-            (void*) android_location_GpsLocationProvider_is_geofence_supported},
+            (void*) android_location_GnssLocationProvider_is_geofence_supported},
     {"native_add_geofence",
             "(IDDDIIII)Z",
-            (void *)android_location_GpsLocationProvider_add_geofence},
+            (void *)android_location_GnssLocationProvider_add_geofence},
     {"native_remove_geofence",
             "(I)Z",
-            (void *)android_location_GpsLocationProvider_remove_geofence},
-    {"native_pause_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_pause_geofence},
+            (void *)android_location_GnssLocationProvider_remove_geofence},
+    {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
     {"native_resume_geofence",
             "(II)Z",
-            (void *)android_location_GpsLocationProvider_resume_geofence},
+            (void *)android_location_GnssLocationProvider_resume_geofence},
     {"native_is_measurement_supported",
             "()Z",
-            (void*) android_location_GpsLocationProvider_is_measurement_supported},
+            (void*) android_location_GnssLocationProvider_is_measurement_supported},
     {"native_start_measurement_collection",
             "()Z",
-            (void*) android_location_GpsLocationProvider_start_measurement_collection},
+            (void*) android_location_GnssLocationProvider_start_measurement_collection},
     {"native_stop_measurement_collection",
             "()Z",
-            (void*) android_location_GpsLocationProvider_stop_measurement_collection},
+            (void*) android_location_GnssLocationProvider_stop_measurement_collection},
     {"native_is_navigation_message_supported",
             "()Z",
-            (void*) android_location_GpsLocationProvider_is_navigation_message_supported},
+            (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
     {"native_start_navigation_message_collection",
             "()Z",
-            (void*) android_location_GpsLocationProvider_start_navigation_message_collection},
+            (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
     {"native_stop_navigation_message_collection",
             "()Z",
-            (void*) android_location_GpsLocationProvider_stop_navigation_message_collection},
+            (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
     {"native_configuration_update",
             "(Ljava/lang/String;)V",
-            (void*)android_location_GpsLocationProvider_configuration_update},
+            (void*)android_location_GnssLocationProvider_configuration_update},
 };
 
-int register_android_server_location_GpsLocationProvider(JNIEnv* env)
+int register_android_server_location_GnssLocationProvider(JNIEnv* env)
 {
     return jniRegisterNativeMethods(
             env,
-            "com/android/server/location/GpsLocationProvider",
+            "com/android/server/location/GnssLocationProvider",
             sMethods,
             NELEM(sMethods));
 }
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 1f3fde6..a7010bc 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -36,7 +36,7 @@
 int register_android_server_UsbMidiDevice(JNIEnv* env);
 int register_android_server_UsbHostManager(JNIEnv* env);
 int register_android_server_VibratorService(JNIEnv* env);
-int register_android_server_location_GpsLocationProvider(JNIEnv* env);
+int register_android_server_location_GnssLocationProvider(JNIEnv* env);
 int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
 int register_android_server_connectivity_Vpn(JNIEnv* env);
 int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
@@ -71,7 +71,7 @@
     register_android_server_UsbHostManager(env);
     register_android_server_VibratorService(env);
     register_android_server_SystemServer(env);
-    register_android_server_location_GpsLocationProvider(env);
+    register_android_server_location_GnssLocationProvider(env);
     register_android_server_location_FlpHardwareProvider(env);
     register_android_server_connectivity_Vpn(env);
     register_android_server_AssetAtlasService(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9b2f829..ca0b43a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -49,6 +49,7 @@
 import android.app.admin.IDevicePolicyManager;
 import android.app.admin.SystemUpdatePolicy;
 import android.app.backup.IBackupManager;
+import android.auditing.SecurityLog;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -194,7 +195,7 @@
 
     private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
 
-    protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
+    private static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
             = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
 
     private static final int MONITORING_CERT_NOTIFICATION_ID = R.string.ssl_ca_cert_warning;
@@ -471,6 +472,7 @@
         private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
         private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
         private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
+        private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
         private static final String TAG_ACCOUNT_TYPE = "account-type";
         private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES
                 = "permitted-accessiblity-services";
@@ -507,6 +509,7 @@
         private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
         private static final String TAG_PARENT_ADMIN = "parent-admin";
         private static final String TAG_ORGANIZATION_COLOR = "organization-color";
+        private static final String TAG_ORGANIZATION_NAME = "organization-name";
 
         final DeviceAdminInfo info;
 
@@ -559,6 +562,7 @@
         boolean disableBluetoothContactSharing = true;
         boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
         boolean requireAutoTime = false; // Can only be set by a device owner.
+        boolean forceEphemeralUsers = false; // Can only be set by a device owner.
 
         ActiveAdmin parentAdmin;
         final boolean isParent;
@@ -604,6 +608,9 @@
         static final int DEF_ORGANIZATION_COLOR = Color.GRAY;
         int organizationColor = DEF_ORGANIZATION_COLOR;
 
+        // Default title of confirm credentials screen
+        String organizationName = null;
+
         ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
             info = _info;
             isParent = parent;
@@ -749,6 +756,11 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(requireAutoTime));
                 out.endTag(null, TAG_REQUIRE_AUTO_TIME);
             }
+            if (forceEphemeralUsers) {
+                out.startTag(null, TAG_FORCE_EPHEMERAL_USERS);
+                out.attribute(null, ATTR_VALUE, Boolean.toString(forceEphemeralUsers));
+                out.endTag(null, TAG_FORCE_EPHEMERAL_USERS);
+            }
             if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
                 out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
                 out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
@@ -822,6 +834,11 @@
                 out.attribute(null, ATTR_VALUE, Integer.toString(organizationColor));
                 out.endTag(null, TAG_ORGANIZATION_COLOR);
             }
+            if (organizationName != null) {
+                out.startTag(null, TAG_ORGANIZATION_NAME);
+                out.text(organizationName);
+                out.endTag(null, TAG_ORGANIZATION_NAME);
+            }
         }
 
         void writePackageListToXml(XmlSerializer out, String outerTag,
@@ -919,7 +936,10 @@
                     disableScreenCapture = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
-                    requireAutoTime= Boolean.parseBoolean(
+                    requireAutoTime = Boolean.parseBoolean(
+                            parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_FORCE_EPHEMERAL_USERS.equals(tag)) {
+                    forceEphemeralUsers = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
                     disabledKeyguardFeatures = Integer.parseInt(
@@ -960,6 +980,13 @@
                 } else if (TAG_ORGANIZATION_COLOR.equals(tag)) {
                     organizationColor = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_ORGANIZATION_NAME.equals(tag)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        organizationName = parser.getText();
+                    } else {
+                        Log.w(LOG_TAG, "Missing text when loading organization name");
+                    }
                 } else {
                     Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -1150,6 +1177,8 @@
                     pw.println(disableScreenCapture);
             pw.print(prefix); pw.print("requireAutoTime=");
                     pw.println(requireAutoTime);
+            pw.print(prefix); pw.print("forceEphemeralUsers=");
+                    pw.println(forceEphemeralUsers);
             pw.print(prefix); pw.print("disabledKeyguardFeatures=");
                     pw.println(disabledKeyguardFeatures);
             pw.print(prefix); pw.print("crossProfileWidgetProviders=");
@@ -1166,6 +1195,12 @@
                 pw.print(prefix); pw.print("keepUninstalledPackages=");
                     pw.println(keepUninstalledPackages);
             }
+            pw.print(prefix); pw.print("organizationColor=");
+                    pw.println(organizationColor);
+            if (organizationName != null) {
+                pw.print(prefix); pw.print("organizationName=");
+                    pw.println(organizationName);
+            }
             pw.print(prefix); pw.println("userRestrictions:");
             UserRestrictionsUtils.dumpRestrictions(pw, prefix + "  ", userRestrictions);
             pw.print(prefix); pw.print("isParent=");
@@ -1690,8 +1725,8 @@
      * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
      * reminders.  Clears alarm if no expirations are configured.
      */
-    private void setExpirationAlarmCheckLocked(Context context, int userHandle) {
-        final long expiration = getPasswordExpirationLocked(null, userHandle, /* parent */ false);
+    private void setExpirationAlarmCheckLocked(Context context, int userHandle, boolean parent) {
+        final long expiration = getPasswordExpirationLocked(null, userHandle, parent);
         final long now = System.currentTimeMillis();
         final long timeToExpire = expiration - now;
         final long alarmTime;
@@ -1713,11 +1748,12 @@
 
         long token = mInjector.binderClearCallingIdentity();
         try {
+            int affectedUserHandle = parent ? getProfileParentId(userHandle) : userHandle;
             AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
             PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
                     new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
                     PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT,
-                    UserHandle.of(userHandle));
+                    UserHandle.of(affectedUserHandle));
             am.cancel(pi);
             if (alarmTime != 0) {
                 am.set(AlarmManager.RTC, alarmTime, pi);
@@ -1971,7 +2007,7 @@
         final ResolveInfo ri = infos.get(0);
 
         if (!permission.BIND_DEVICE_ADMIN.equals(ri.activityInfo.permission)) {
-            final String message = "DeviceAdminReceiver " + adminName + " must be protected with"
+            final String message = "DeviceAdminReceiver " + adminName + " must be protected with "
                     + permission.BIND_DEVICE_ADMIN;
             Slog.w(LOG_TAG, message);
             if (throwForMissiongPermission &&
@@ -2408,6 +2444,14 @@
         if (packageList != null) {
             mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList);
         }
+
+        synchronized (this) {
+            // push the force-ephemeral-users policy to the user manager.
+            ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
+            if (deviceOwner != null) {
+                mUserManagerInternal.setForceEphemeralUsers(deviceOwner.forceEphemeralUsers);
+            }
+        }
     }
 
     private void ensureDeviceOwnerUserStarted() {
@@ -2468,7 +2512,6 @@
         synchronized (this) {
             final long now = System.currentTimeMillis();
 
-            // Return the strictest policy across all participating admins.
             List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(
                     userHandle, /* parent */ false);
             final int N = admins.size();
@@ -2482,7 +2525,7 @@
                             DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
                 }
             }
-            setExpirationAlarmCheckLocked(mContext, userHandle);
+            setExpirationAlarmCheckLocked(mContext, userHandle, /* parent */ false);
         }
     }
 
@@ -2955,8 +2998,7 @@
             saveSettingsLocked(userHandle);
 
             // in case this is the first one, set the alarm on the appropriate user.
-            int affectedUserHandle = parent ? getProfileParentId(userHandle) : userHandle;
-            setExpirationAlarmCheckLocked(mContext, affectedUserHandle);
+            setExpirationAlarmCheckLocked(mContext, userHandle, parent);
         }
     }
 
@@ -4303,7 +4345,7 @@
                 policy.mFailedPasswordAttempts = 0;
                 saveSettingsLocked(userHandle);
                 updatePasswordExpirationsLocked(userHandle);
-                setExpirationAlarmCheckLocked(mContext, userHandle);
+                setExpirationAlarmCheckLocked(mContext, userHandle, /* parent */ false);
 
                 // Send a broadcast to each profile using this password as its primary unlock.
                 sendAdminCommandForLockscreenPoliciesLocked(
@@ -4381,6 +4423,10 @@
         } finally {
             mInjector.binderRestoreCallingIdentity(ident);
         }
+
+        if (SecurityLog.isLoggingEnabled()) {
+            SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 0);
+        }
     }
 
     @Override
@@ -4407,6 +4453,28 @@
                 }
             }
         }
+
+        if (SecurityLog.isLoggingEnabled()) {
+            SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 1);
+        }
+    }
+
+    @Override
+    public void reportKeyguardDismissed() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+        if (SecurityLog.isLoggingEnabled()) {
+            SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISSED);
+        }
+    }
+
+    @Override
+    public void reportKeyguardSecured() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+        if (SecurityLog.isLoggingEnabled()) {
+            SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_SECURED);
+        }
     }
 
     @Override
@@ -4789,6 +4857,46 @@
         }
     }
 
+    @Override
+    public void setForceEphemeralUsers(ComponentName who, boolean forceEphemeralUsers) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        boolean removeAllUsers = false;
+        synchronized (this) {
+            final ActiveAdmin deviceOwner =
+                    getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            if (deviceOwner.forceEphemeralUsers != forceEphemeralUsers) {
+                deviceOwner.forceEphemeralUsers = forceEphemeralUsers;
+                saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+                mUserManagerInternal.setForceEphemeralUsers(forceEphemeralUsers);
+                removeAllUsers = forceEphemeralUsers;
+            }
+        }
+        if (removeAllUsers) {
+            long identitity = mInjector.binderClearCallingIdentity();
+            try {
+                mUserManagerInternal.removeAllUsers();
+            } finally {
+                mInjector.binderRestoreCallingIdentity(identitity);
+            }
+        }
+    }
+
+    @Override
+    public boolean getForceEphemeralUsers(ComponentName who) {
+        if (!mHasFeature) {
+            return false;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        synchronized (this) {
+            final ActiveAdmin deviceOwner =
+                    getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            return deviceOwner.forceEphemeralUsers;
+        }
+    }
+
     private void ensureDeviceOwnerManagingSingleUser(ComponentName who) throws SecurityException {
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -5319,6 +5427,8 @@
             if (admin != null) {
                 admin.disableCamera = false;
                 admin.userRestrictions = null;
+                admin.forceEphemeralUsers = false;
+                mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
             }
 
             clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));
@@ -5361,7 +5471,9 @@
         if (!mHasFeature) {
             return;
         }
-        UserHandle callingUser = mInjector.binderGetCallingUserHandle();
+        final UserHandle callingUser = mInjector.binderGetCallingUserHandle();
+        final int userId = callingUser.getIdentifier();
+        enforceNotManagedProfile(userId, "clear profile owner");
         // Check if this is the profile owner who is calling
         final ActiveAdmin admin =
                 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -5369,7 +5481,6 @@
             admin.disableCamera = false;
             admin.userRestrictions = null;
             clearUserPoliciesLocked(callingUser);
-            final int userId = callingUser.getIdentifier();
             mOwners.removeProfileOwner(userId);
             mOwners.writeProfileOwner(userId);
         }
@@ -6525,7 +6636,11 @@
 
             final long id = mInjector.binderClearCallingIdentity();
             try {
-                UserInfo userInfo = mUserManager.createUser(name, 0 /* flags */);
+                int userInfoFlags = 0;
+                if ((flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0) {
+                    userInfoFlags |= UserInfo.FLAG_EPHEMERAL;
+                }
+                UserInfo userInfo = mUserManager.createUser(name, userInfoFlags);
                 if (userInfo != null) {
                     user = userInfo.getUserHandle();
                 }
@@ -8003,11 +8118,12 @@
 
     @Override
     public void setOrganizationColor(@NonNull ComponentName who, int color) {
-        final int userHandle = mInjector.userHandleGetCallingUserId();
-        if (!mHasFeature || !isManagedProfile(userHandle)) {
+        if (!mHasFeature) {
             return;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
+        final int userHandle = mInjector.userHandleGetCallingUserId();
+        enforceManagedProfile(userHandle, "set organization color");
         synchronized (this) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -8018,11 +8134,11 @@
 
     @Override
     public int getOrganizationColor(@NonNull ComponentName who) {
-        final int userHandle = mInjector.userHandleGetCallingUserId();
-        if (!mHasFeature || !isManagedProfile(userHandle)) {
+        if (!mHasFeature) {
             return ActiveAdmin.DEF_ORGANIZATION_COLOR;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
+        enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization color");
         synchronized (this) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -8032,10 +8148,11 @@
 
     @Override
     public int getOrganizationColorForUser(int userHandle) {
-        if (!mHasFeature || !isManagedProfile(userHandle)) {
+        if (!mHasFeature) {
             return ActiveAdmin.DEF_ORGANIZATION_COLOR;
         }
-        enforceCrossUsersPermission(userHandle);
+        enforceFullCrossUsersPermission(userHandle);
+        enforceManagedProfile(userHandle, "get organization color");
         synchronized (this) {
             ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
             return (profileOwner != null)
@@ -8045,6 +8162,53 @@
     }
 
     @Override
+    public void setOrganizationName(@NonNull ComponentName who, String text) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        final int userHandle = mInjector.userHandleGetCallingUserId();
+        enforceManagedProfile(userHandle, "set organization name");
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!TextUtils.equals(admin.organizationName, text)) {
+                admin.organizationName = TextUtils.nullIfEmpty(text);
+                saveSettingsLocked(userHandle);
+            }
+        }
+    }
+
+    @Override
+    public String getOrganizationName(@NonNull ComponentName who) {
+        if (!mHasFeature) {
+            return null;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization name");
+        synchronized(this) {
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            return admin.organizationName;
+        }
+    }
+
+    @Override
+    public String getOrganizationNameForUser(int userHandle) {
+        if (!mHasFeature) {
+            return null;
+        }
+        enforceFullCrossUsersPermission(userHandle);
+        enforceManagedProfile(userHandle, "get organization name");
+        synchronized (this) {
+            ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
+            return (profileOwner != null)
+                    ? profileOwner.organizationName
+                    : null;
+        }
+    }
+
+    @Override
     public void setAffiliationIds(ComponentName admin, List<String> ids) {
         final Set<String> affiliationIds = new ArraySet<String>(ids);
         final int callingUserId = mInjector.userHandleGetCallingUserId();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c186a12..254a37a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -68,6 +68,7 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
+import com.android.internal.widget.ILockSettings;
 import com.android.server.media.MediaRouterService;
 import com.android.server.media.MediaSessionService;
 import com.android.server.media.MediaResourceMonitorService;
@@ -84,6 +85,7 @@
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
 import com.android.server.restrictions.RestrictionsManagerService;
+import com.android.server.soundtrigger.SoundTriggerService;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.storage.DeviceStorageMonitorService;
 import com.android.server.telecom.TelecomLoaderService;
@@ -142,6 +144,8 @@
             "com.android.server.ethernet.EthernetService";
     private static final String JOB_SCHEDULER_SERVICE_CLASS =
             "com.android.server.job.JobSchedulerService";
+    private static final String LOCK_SETTINGS_SERVICE_CLASS =
+            "com.android.server.LockSettingsService$Lifecycle";
     private static final String MOUNT_SERVICE_CLASS =
             "com.android.server.MountService$Lifecycle";
     private static final String SEARCH_MANAGER_SERVICE_CLASS =
@@ -606,7 +610,7 @@
         LocationManagerService location = null;
         CountryDetectorService countryDetector = null;
         TextServicesManagerService tsms = null;
-        LockSettingsService lockSettings = null;
+        ILockSettings lockSettings = null;
         AssetAtlasService atlas = null;
         MediaRouterService mediaRouter = null;
 
@@ -679,8 +683,9 @@
             if (!disableNonCoreServices) {
                 traceBeginAndSlog("StartLockSettingsService");
                 try {
-                    lockSettings = new LockSettingsService(context);
-                    ServiceManager.addService("lock_settings", lockSettings);
+                    mSystemServiceManager.startService(LOCK_SETTINGS_SERVICE_CLASS);
+                    lockSettings = ILockSettings.Stub.asInterface(
+                            ServiceManager.getService("lock_settings"));
                 } catch (Throwable e) {
                     reportWtf("starting LockSettingsService service", e);
                 }
@@ -959,6 +964,8 @@
 
             mSystemServiceManager.startService(JobSchedulerService.class);
 
+            mSystemServiceManager.startService(SoundTriggerService.class);
+
             if (!disableNonCoreServices) {
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BACKUP)) {
                     mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS);
@@ -976,6 +983,7 @@
                     Slog.i(TAG, "Gesture Launcher Service");
                     mSystemServiceManager.startService(GestureLauncherService.class);
                 }
+                mSystemServiceManager.startService(SensorNotificationService.class);
             }
 
             traceBeginAndSlog("StartDiskStatsService");
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 27d5207..5874429 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -52,10 +52,12 @@
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
+import android.os.Messenger;
 import android.os.MessageQueue.IdleHandler;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -1298,6 +1300,36 @@
         validatedCallback.expectCallback(CallbackState.LOST);
     }
 
+    @SmallTest
+    public void testInvalidNetworkSpecifier() {
+        boolean execptionCalled = true;
+
+        try {
+            NetworkRequest.Builder builder = new NetworkRequest.Builder();
+            builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+            execptionCalled = false;
+        } catch (IllegalArgumentException e) {
+            // do nothing - should get here
+        }
+
+        assertTrue("NetworkReqeuest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
+                execptionCalled);
+
+        try {
+            NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+            networkCapabilities.addTransportType(TRANSPORT_WIFI)
+                    .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+            mService.requestNetwork(networkCapabilities, null, 0, null,
+                    ConnectivityManager.TYPE_WIFI);
+            execptionCalled = false;
+        } catch (IllegalArgumentException e) {
+            // do nothing - should get here
+        }
+
+        assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
+                execptionCalled);
+    }
+
     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
 
         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index b4bca3e..6c2fcd5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -26,7 +26,10 @@
 import android.os.UserManager;
 import android.test.AndroidTestCase;
 
+import com.android.internal.util.ArrayUtils;
+
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /** Test {@link UserManager} functionality. */
@@ -196,6 +199,17 @@
         assertEquals(user2.id, mUserManager.getUserHandle(serialNumber2));
     }
 
+    public void testGetSerialNumbersOfUsers() {
+        UserInfo user1 = createUser("User 1", 0);
+        UserInfo user2 = createUser("User 2", 0);
+        long[] serialNumbersOfUsers = mUserManager.getSerialNumbersOfUsers(false);
+        String errMsg = "Array " + Arrays.toString(serialNumbersOfUsers) + " should contain ";
+        assertTrue(errMsg + user1.serialNumber,
+                ArrayUtils.contains(serialNumbersOfUsers, user1.serialNumber));
+        assertTrue(errMsg + user2.serialNumber,
+                ArrayUtils.contains(serialNumbersOfUsers, user2.serialNumber));
+    }
+
     public void testMaxUsers() {
         int N = UserManager.getMaxSupportedUsers();
         int count = mUserManager.getUsers().size();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 0ca4bd8..87c5ba0 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -17,6 +17,7 @@
 package com.android.server.usage;
 
 import android.app.usage.TimeSparseArray;
+import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.os.Build;
 import android.util.AtomicFile;
@@ -25,6 +26,10 @@
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileReader;
 import java.io.FileWriter;
@@ -39,6 +44,14 @@
 class UsageStatsDatabase {
     private static final int CURRENT_VERSION = 3;
 
+    // Current version of the backup schema
+    static final int BACKUP_STATE_VERSION = 1;
+
+    // Key under which the payload blob is stored
+    // same as UsageStatsBackupHelper.KEY_USAGE_STATS
+    static final String KEY_USAGE_STATS = "usage_stats";
+
+
     private static final String TAG = "UsageStatsDatabase";
     private static final boolean DEBUG = UsageStatsService.DEBUG;
     private static final String BAK_SUFFIX = ".bak";
@@ -539,4 +552,186 @@
             stats.lastTimeSaved = f.getLastModifiedTime();
         }
     }
+
+
+    /* Backup/Restore Code */
+    protected byte[] getBackupPayload(String key){
+        synchronized (mLock) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            if (KEY_USAGE_STATS.equals(key)) {
+                prune(System.currentTimeMillis());
+                DataOutputStream out = new DataOutputStream(baos);
+                try {
+                    out.writeInt(BACKUP_STATE_VERSION);
+
+                    out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].size());
+                    for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].size(); i++){
+                        writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].valueAt(i));
+                    }
+
+                    out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].size());
+                    for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].size(); i++){
+                        writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].valueAt(i));
+                    }
+
+                    out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].size());
+                    for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].size(); i++){
+                        writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].valueAt(i));
+                    }
+
+                    out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].size());
+                    for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].size(); i++){
+                        writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].valueAt(i));
+                    }
+                    if (DEBUG) Slog.i(TAG, "Written " + baos.size() + " bytes of data");
+                } catch (IOException ioe){
+                    Slog.d(TAG, "Failed to write data to output stream", ioe);
+                    baos.reset();
+                }
+            }
+            return baos.toByteArray();
+        }
+
+    }
+
+    protected void applyRestoredPayload(String key, byte[] payload){
+        synchronized (mLock) {
+            if (KEY_USAGE_STATS.equals(key)) {
+                // Read stats files for the current device configs
+                IntervalStats dailyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_DAILY);
+                IntervalStats weeklyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_WEEKLY);
+                IntervalStats monthlyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_MONTHLY);
+                IntervalStats yearlyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_YEARLY);
+
+                // Delete all stats files
+                for(int i = 0; i<mIntervalDirs.length; i++){
+                    deleteDirectoryContents(mIntervalDirs[i]);
+                }
+                try {
+                    DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
+                    int stateVersion = in.readInt();
+
+                    int fileCount = in.readInt();
+                    for(int i = 0; i<fileCount; i++){
+                        IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in));
+                        stats = mergeStats(stats, dailyConfigSource);
+                        putUsageStats(UsageStatsManager.INTERVAL_DAILY, stats);
+                    }
+
+                    fileCount = in.readInt();
+                    for(int i = 0; i<fileCount; i++){
+                        IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in));
+                        stats = mergeStats(stats, weeklyConfigSource);
+                        putUsageStats(UsageStatsManager.INTERVAL_WEEKLY, stats);
+                    }
+
+                    fileCount = in.readInt();
+                    for(int i = 0; i<fileCount; i++){
+                        IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in));
+                        stats = mergeStats(stats, monthlyConfigSource);
+                        putUsageStats(UsageStatsManager.INTERVAL_MONTHLY, stats);
+                    }
+
+                    fileCount = in.readInt();
+                    for(int i = 0; i<fileCount; i++){
+                        IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in));
+                        stats = mergeStats(stats, yearlyConfigSource);
+                        putUsageStats(UsageStatsManager.INTERVAL_YEARLY, stats);
+                    }
+                    if (DEBUG) Slog.i(TAG, "Completed Restoring UsageStats");
+                } catch (IOException ioe){
+                    Slog.d(TAG, "Failed to read data from input stream", ioe);
+                }
+                finally {
+                    indexFilesLocked();
+                }
+            }
+        }
+    }
+
+    /**
+     * Get the Configuration Statistics from the current device statistics and merge them
+     * with the backed up usage statistics.
+     */
+    private IntervalStats mergeStats(IntervalStats beingRestored, IntervalStats onDevice) {
+        beingRestored.activeConfiguration = onDevice.activeConfiguration;
+        beingRestored.configurations.putAll(onDevice.configurations);
+        beingRestored.events = onDevice.events;
+        return beingRestored;
+    }
+
+    private void writeIntervalStatsToStream(DataOutputStream out, AtomicFile statsFile) throws IOException{
+        IntervalStats stats = new IntervalStats();
+        try {
+            UsageStatsXml.read(statsFile, stats);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read usage stats file", e);
+            out.writeInt(0);
+            return;
+        }
+        sanitizeIntervalStatsForBackup(stats);
+        byte[] data = serializeIntervalStats(stats);
+        out.writeInt(data.length);
+        out.write(data);
+    }
+
+    private static byte[] getIntervalStatsBytes(DataInputStream in) throws IOException {
+        int length = in.readInt();
+        byte[] buffer = new byte[length];
+        in.read(buffer, 0, length);
+        return buffer;
+    }
+
+    private static void sanitizeIntervalStatsForBackup(IntervalStats stats) {
+        if (stats == null) return;
+        stats.activeConfiguration = null;
+        stats.configurations.clear();
+        if (stats.events != null) stats.events.clear();
+    }
+
+    private static byte[] serializeIntervalStats(IntervalStats stats) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        DataOutputStream out = new DataOutputStream(baos);
+        try {
+            out.writeLong(stats.beginTime);
+            UsageStatsXml.write(out, stats);
+        } catch (IOException ioe) {
+            Slog.d(TAG, "Serializing IntervalStats Failed", ioe);
+            baos.reset();
+        }
+        return baos.toByteArray();
+    }
+
+    private static IntervalStats deserializeIntervalStats(byte[] data) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+        DataInputStream in = new DataInputStream(bais);
+        IntervalStats stats = new IntervalStats();
+        try {
+            stats.beginTime = in.readLong();
+            UsageStatsXml.read(in, stats);
+        } catch (IOException ioe) {
+            Slog.d(TAG, "DeSerializing IntervalStats Failed", ioe);
+            stats = null;
+        }
+        return stats;
+    }
+
+    private static void deleteDirectoryContents(File directory){
+        File[] files = directory.listFiles();
+        for (File file : files) {
+            deleteDirectory(file);
+        }
+    }
+
+    private static void deleteDirectory(File directory) {
+        File[] files = directory.listFiles();
+        for (File file : files) {
+            if (!file.isDirectory()) {
+                file.delete();
+            } else {
+                deleteDirectory(file);
+            }
+        }
+        directory.delete();
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index f2949bf4..bfdac7e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -123,6 +123,7 @@
     static final int MSG_PAROLE_END_TIMEOUT = 7;
     static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
     static final int MSG_PAROLE_STATE_CHANGED = 9;
+    static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
 
     private final Object mLock = new Object();
     Handler mHandler;
@@ -145,7 +146,7 @@
     private long mLastAppIdleParoledTime;
 
     long mScreenOnTime;
-    long mScreenOnSystemTimeSnapshot;
+    long mLastScreenOnEventRealtime;
 
     @GuardedBy("mLock")
     private AppIdleHistory mAppIdleHistory = new AppIdleHistory();
@@ -188,6 +189,8 @@
 
         synchronized (mLock) {
             cleanUpRemovedUsersLocked();
+            mLastScreenOnEventRealtime = SystemClock.elapsedRealtime();
+            mScreenOnTime = readScreenOnTimeLocked();
         }
 
         mRealTimeSnapshot = SystemClock.elapsedRealtime();
@@ -214,10 +217,6 @@
                     Context.DISPLAY_SERVICE);
             mPowerManager = getContext().getSystemService(PowerManager.class);
 
-            mScreenOnSystemTimeSnapshot = System.currentTimeMillis();
-            synchronized (mLock) {
-                mScreenOnTime = readScreenOnTimeLocked();
-            }
             mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
             synchronized (mLock) {
                 updateDisplayLocked();
@@ -281,6 +280,11 @@
     }
 
     @Override
+    public void onStatsReloaded() {
+        postOneTimeCheckIdleStates();
+    }
+
+    @Override
     public long getAppIdleRollingWindowDurationMillis() {
         return mAppIdleWallclockThresholdMillis * 2;
     }
@@ -359,6 +363,14 @@
         mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
     }
 
+    /**
+     * We send a different message to check idle states once, otherwise we would end up
+     * scheduling a series of repeating checkIdleStates each time we fired off one.
+     */
+    void postOneTimeCheckIdleStates() {
+        mHandler.sendEmptyMessage(MSG_ONE_TIME_CHECK_IDLE_STATES);
+    }
+
     /** Check all running users' or specified user's apps to see if they enter an idle state. */
     void checkIdleStates(int checkUserId) {
         if (!mAppIdleEnabled) {
@@ -385,7 +397,7 @@
                             userId);
             synchronized (mLock) {
                 final long timeNow = checkAndGetTimeLocked();
-                final long screenOnTime = getScreenOnTimeLocked(timeNow);
+                final long screenOnTime = getScreenOnTimeLocked();
                 UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId,
                         timeNow);
                 final int packageCount = packages.size();
@@ -401,8 +413,6 @@
                 }
             }
         }
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0),
-                mCheckIdleIntervalMillis);
     }
 
     /** Check if it's been a while since last parole and let idle apps do some work */
@@ -443,21 +453,21 @@
         if (screenOn == mScreenOn) return;
 
         mScreenOn = screenOn;
-        long now = System.currentTimeMillis();
+        long now = SystemClock.elapsedRealtime();
         if (mScreenOn) {
-            mScreenOnSystemTimeSnapshot = now;
+            mLastScreenOnEventRealtime = now;
         } else {
-            mScreenOnTime += now - mScreenOnSystemTimeSnapshot;
+            mScreenOnTime += now - mLastScreenOnEventRealtime;
             writeScreenOnTimeLocked(mScreenOnTime);
         }
     }
 
-    private long getScreenOnTimeLocked(long now) {
+    long getScreenOnTimeLocked() {
+        long screenOnTime = mScreenOnTime;
         if (mScreenOn) {
-            return now - mScreenOnSystemTimeSnapshot + mScreenOnTime;
-        } else {
-            return mScreenOnTime;
+            screenOnTime += SystemClock.elapsedRealtime() - mLastScreenOnEventRealtime;
         }
+        return screenOnTime;
     }
 
     private File getScreenOnTimeFile() {
@@ -527,7 +537,7 @@
         if (service == null) {
             service = new UserUsageStatsService(getContext(), userId,
                     new File(mUsageStatsDir, Integer.toString(userId)), this);
-            service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis));
+            service.init(currentTimeMillis, getScreenOnTimeLocked());
             mUserState.put(userId, service);
         }
         return service;
@@ -540,25 +550,18 @@
         final long actualSystemTime = System.currentTimeMillis();
         final long actualRealtime = SystemClock.elapsedRealtime();
         final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
-        boolean resetBeginIdleTime = false;
-        if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
+        final long diffSystemTime = actualSystemTime - expectedSystemTime;
+        if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
             // The time has changed.
-
-            // Check if it's severe enough a change to reset screenOnTime
-            if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) {
-                mScreenOnSystemTimeSnapshot = actualSystemTime;
-                mScreenOnTime = 0;
-                resetBeginIdleTime = true;
-            }
+            Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds");
             final int userCount = mUserState.size();
             for (int i = 0; i < userCount; i++) {
                 final UserUsageStatsService service = mUserState.valueAt(i);
-                service.onTimeChanged(expectedSystemTime, actualSystemTime, mScreenOnTime,
-                        resetBeginIdleTime);
+                service.onTimeChanged(expectedSystemTime, actualSystemTime, getScreenOnTimeLocked(),
+                        false);
             }
             mRealTimeSnapshot = actualRealtime;
             mSystemTimeSnapshot = actualSystemTime;
-            postCheckIdleStates(UserHandle.USER_ALL);
         }
         return actualSystemTime;
     }
@@ -587,7 +590,7 @@
     void reportEvent(UsageEvents.Event event, int userId) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
-            final long screenOnTime = getScreenOnTimeLocked(timeNow);
+            final long screenOnTime = getScreenOnTimeLocked();
             convertToSystemTimeLocked(event);
 
             final UserUsageStatsService service =
@@ -603,7 +606,6 @@
                     || event.mEventType == Event.SYSTEM_INTERACTION
                     || event.mEventType == Event.USER_INTERACTION)) {
                 if (previouslyIdle) {
-                    //Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                             /* idle = */ 0, event.mPackage));
                     notifyBatteryStats(event.mPackage, userId, false);
@@ -643,7 +645,7 @@
     void forceIdleState(String packageName, int userId, boolean idle) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
-            final long screenOnTime = getScreenOnTimeLocked(timeNow);
+            final long screenOnTime = getScreenOnTimeLocked();
             final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000;
 
             final UserUsageStatsService service =
@@ -657,7 +659,6 @@
                     timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000);
             // Inform listeners if necessary
             if (previouslyIdle != idle) {
-                // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName);
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                         /* idle = */ idle ? 1 : 0, packageName));
                 if (!idle) {
@@ -796,7 +797,7 @@
                 timeNow = checkAndGetTimeLocked();
             }
             userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            screenOnTime = getScreenOnTimeLocked(timeNow);
+            screenOnTime = getScreenOnTimeLocked();
         }
         return isAppIdleFiltered(packageName, UserHandle.getAppId(uidForAppId), userId,
                 userService, timeNow, screenOnTime);
@@ -865,7 +866,7 @@
         synchronized (mLock) {
             timeNow = checkAndGetTimeLocked();
             userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            screenOnTime = getScreenOnTimeLocked(timeNow);
+            screenOnTime = getScreenOnTimeLocked();
         }
 
         List<ApplicationInfo> apps;
@@ -987,7 +988,7 @@
      */
     void dump(String[] args, PrintWriter pw) {
         synchronized (mLock) {
-            final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked());
+            final long screenOnTime = getScreenOnTimeLocked();
             IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
             ArraySet<String> argSet = new ArraySet<>();
             argSet.addAll(Arrays.asList(args));
@@ -1008,7 +1009,11 @@
                 }
                 idpw.decreaseIndent();
             }
-            pw.println("Screen On Timebase:" + mScreenOnTime);
+            pw.print("Screen On Timebase: ");
+            pw.print(screenOnTime);
+            pw.print(" (");
+            TimeUtils.formatDuration(screenOnTime, pw);
+            pw.println(")");
 
             pw.println();
             pw.println("Settings:");
@@ -1042,8 +1047,8 @@
             pw.println();
             pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw);
             pw.println();
-            pw.print("mScreenOnSystemTimeSnapshot=");
-            TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw);
+            pw.print("mLastScreenOnEventRealtime=");
+            TimeUtils.formatDuration(mLastScreenOnEventRealtime, pw);
             pw.println();
         }
     }
@@ -1078,6 +1083,14 @@
 
                 case MSG_CHECK_IDLE_STATES:
                     checkIdleStates(msg.arg1);
+                    mHandler.sendMessageDelayed(mHandler.obtainMessage(
+                            MSG_CHECK_IDLE_STATES, msg.arg1, 0),
+                            mCheckIdleIntervalMillis);
+                    break;
+
+                case MSG_ONE_TIME_CHECK_IDLE_STATES:
+                    mHandler.removeMessages(MSG_ONE_TIME_CHECK_IDLE_STATES);
+                    checkIdleStates(UserHandle.USER_ALL);
                     break;
 
                 case MSG_CHECK_PAROLE_TIMEOUT:
@@ -1138,7 +1151,7 @@
         @Override
         public void onChange(boolean selfChange) {
             updateSettings();
-            postCheckIdleStates(UserHandle.USER_ALL);
+            postOneTimeCheckIdleStates();
         }
 
         void updateSettings() {
@@ -1310,6 +1323,8 @@
             }
             UsageStatsService.this.dump(args, pw);
         }
+
+
     }
 
     /**
@@ -1416,5 +1431,26 @@
                 AppIdleStateChangeListener listener) {
             UsageStatsService.this.removeListener(listener);
         }
+
+        @Override
+        public byte[] getBackupPayload(int user, String key) {
+            // Check to ensure that only user 0's data is b/r for now
+            if (user == UserHandle.USER_SYSTEM) {
+                final UserUsageStatsService userStats =
+                        getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+                return userStats.getBackupPayload(key);
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public void applyRestoredPayload(int user, String key, byte[] payload) {
+            if (user == UserHandle.USER_SYSTEM) {
+                final UserUsageStatsService userStats =
+                        getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
+                userStats.applyRestoredPayload(key, payload);
+            }
+        }
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java
index 543f361..e7db741 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXml.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java
@@ -87,7 +87,7 @@
         }
     }
 
-    private static void read(InputStream in, IntervalStats statsOut) throws IOException {
+    static void read(InputStream in, IntervalStats statsOut) throws IOException {
         XmlPullParser parser = Xml.newPullParser();
         try {
             parser.setInput(in, "utf-8");
@@ -113,7 +113,7 @@
         }
     }
 
-    private static void write(OutputStream out, IntervalStats stats) throws IOException {
+    static void write(OutputStream out, IntervalStats stats) throws IOException {
         FastXmlSerializer xml = new FastXmlSerializer();
         xml.setOutput(out, "utf-8");
         xml.startDocument("utf-8", true);
@@ -126,4 +126,4 @@
         xml.endTag(null, USAGESTATS_TAG);
         xml.endDocument();
     }
-}
+}
\ No newline at end of file
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 224faf4..f2045d3 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -73,6 +73,7 @@
 
     interface StatsUpdatedListener {
         void onStatsUpdated();
+        void onStatsReloaded();
         long getAppIdleRollingWindowDurationMillis();
     }
 
@@ -523,6 +524,9 @@
 
         mStatsChanged = false;
         updateRolloverDeadline();
+
+        // Tell the listener that the stats reloaded, which may have changed idle states.
+        mListener.onStatsReloaded();
     }
 
     private void updateRolloverDeadline() {
@@ -741,4 +745,12 @@
                 return "UNKNOWN";
         }
     }
+
+    byte[] getBackupPayload(String key){
+        return mDatabase.getBackupPayload(key);
+    }
+
+    void applyRestoredPayload(String key, byte[] payload){
+        mDatabase.applyRestoredPayload(key, payload);
+    }
 }
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
new file mode 100644
index 0000000..18a5d59
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerDbHelper.java
@@ -0,0 +1,144 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.soundtrigger;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.util.Locale;
+import java.util.UUID;
+
+/**
+ * Helper to manage the database of the sound models that have been registered on the device.
+ *
+ * @hide
+ */
+public class SoundTriggerDbHelper extends SQLiteOpenHelper {
+    static final String TAG = "SoundTriggerDbHelper";
+    static final boolean DBG = false;
+
+    private static final String NAME = "st_sound_model.db";
+    private static final int VERSION = 1;
+
+    // Sound trigger-based sound models.
+    public static interface GenericSoundModelContract {
+        public static final String TABLE = "st_sound_model";
+        public static final String KEY_MODEL_UUID = "model_uuid";
+        public static final String KEY_VENDOR_UUID = "vendor_uuid";
+        public static final String KEY_DATA = "data";
+    }
+
+
+    // Table Create Statement for the sound trigger table
+    private static final String CREATE_TABLE_ST_SOUND_MODEL = "CREATE TABLE "
+            + GenericSoundModelContract.TABLE + "("
+            + GenericSoundModelContract.KEY_MODEL_UUID + " TEXT PRIMARY KEY,"
+            + GenericSoundModelContract.KEY_DATA + " BLOB" + " )";
+
+
+    public SoundTriggerDbHelper(Context context) {
+        super(context, NAME, null, VERSION);
+    }
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        // creating required tables
+        db.execSQL(CREATE_TABLE_ST_SOUND_MODEL);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        // TODO: For now, drop older tables and recreate new ones.
+        db.execSQL("DROP TABLE IF EXISTS " + GenericSoundModelContract.TABLE);
+        onCreate(db);
+    }
+
+    /**
+     * Updates the given sound trigger model, adds it, if it doesn't already exist.
+     *
+     */
+    public boolean updateGenericSoundModel(GenericSoundModel soundModel) {
+        synchronized(this) {
+            SQLiteDatabase db = getWritableDatabase();
+            ContentValues values = new ContentValues();
+            values.put(GenericSoundModelContract.KEY_MODEL_UUID, soundModel.uuid.toString());
+            values.put(GenericSoundModelContract.KEY_VENDOR_UUID, soundModel.vendorUuid.toString());
+            values.put(GenericSoundModelContract.KEY_DATA, soundModel.data);
+
+            try {
+                return db.insertWithOnConflict(GenericSoundModelContract.TABLE, null, values,
+                        SQLiteDatabase.CONFLICT_REPLACE) != -1;
+            } finally {
+                db.close();
+            }
+
+        }
+    }
+
+    public GenericSoundModel getGenericSoundModel(UUID model_uuid) {
+        synchronized(this) {
+
+            // Find the corresponding sound model ID for the keyphrase.
+            String selectQuery = "SELECT  * FROM " + GenericSoundModelContract.TABLE
+                    + " WHERE " + GenericSoundModelContract.KEY_MODEL_UUID + "= '" +
+                    model_uuid + "'";
+            SQLiteDatabase db = getReadableDatabase();
+            Cursor c = db.rawQuery(selectQuery, null);
+            try {
+                if (c.moveToFirst()) {
+                    do {
+                        byte[] data = c.getBlob(c.getColumnIndex(
+                                GenericSoundModelContract.KEY_DATA));
+                        String vendor_uuid = c.getString(
+                                c.getColumnIndex(GenericSoundModelContract.KEY_VENDOR_UUID));
+                        return new GenericSoundModel(model_uuid, UUID.fromString(vendor_uuid),
+                                data);
+                    } while (c.moveToNext());
+                }
+            } finally {
+                c.close();
+                db.close();
+            }
+        }
+        return null;
+    }
+
+    public boolean deleteGenericSoundModel(UUID model_uuid) {
+        synchronized(this) {
+            GenericSoundModel soundModel = getGenericSoundModel(model_uuid);
+            if (soundModel == null) {
+                return false;
+            }
+            // Delete all sound models for the given keyphrase and specified user.
+            SQLiteDatabase db = getWritableDatabase();
+            String soundModelClause = GenericSoundModelContract.KEY_MODEL_UUID
+                    + "='" + soundModel.uuid.toString() + "'";
+            try {
+                return db.delete(GenericSoundModelContract.TABLE, soundModelClause, null) != 0;
+            } finally {
+                db.close();
+            }
+        }
+    }
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
similarity index 99%
rename from services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
rename to services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 31d859f..597f915ec 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.voiceinteraction;
+package com.android.server.soundtrigger;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
new file mode 100644
index 0000000..0a06bfa
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.soundtrigger;
+
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
+import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent;
+import android.hardware.soundtrigger.SoundTriggerModule;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Provides a local service for managing voice-related recoginition models. This is primarily used
+ * by the {@link VoiceInteractionManagerService}.
+ */
+public abstract class SoundTriggerInternal {
+    /**
+     * Return codes for {@link #startRecognition(int, KeyphraseSoundModel,
+     *      IRecognitionStatusCallback, RecognitionConfig)},
+     * {@link #stopRecognition(int, IRecognitionStatusCallback)}
+     */
+    public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR;
+    public static final int STATUS_OK = SoundTrigger.STATUS_OK;
+
+    /** The {@link ModuleProperties} for the system, or null if none exists. */
+    private ModuleProperties moduleProperties;
+
+    /**
+     * Starts recognition for the given keyphraseId.
+     *
+     * @param keyphraseId The identifier of the keyphrase for which
+     *        the recognition is to be started.
+     * @param soundModel The sound model to use for recognition.
+     * @param listener The listener for the recognition events related to the given keyphrase.
+     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+     */
+    public abstract int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+            IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig);
+
+    /**
+     * Stops recognition for the given {@link Keyphrase} if a recognition is
+     * currently active.
+     *
+     * @param keyphraseId The identifier of the keyphrase for which
+     *        the recognition is to be stopped.
+     * @param listener The listener for the recognition events related to the given keyphrase.
+     *
+     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+     */
+    public abstract int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener);
+
+    /**
+     * Stops all recognitions active currently and clears the internal state.
+     */
+    public abstract void stopAllRecognitions();
+
+    public ModuleProperties getModuleProperties() {
+        return moduleProperties;
+    }
+
+    public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
+}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
new file mode 100644
index 0000000..5e8fe9e
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.soundtrigger;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.Manifest;
+import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.os.Parcel;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+import com.android.internal.app.ISoundTriggerService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.UUID;
+
+/**
+ * A single SystemService to manage all sound/voice-based sound models on the DSP.
+ * This services provides apis to manage sound trigger-based sound models via
+ * the ISoundTriggerService interface. This class also publishes a local interface encapsulating
+ * the functionality provided by {@link SoundTriggerHelper} for use by
+ * {@link VoiceInteractionManagerService}.
+ *
+ * @hide
+ */
+public class SoundTriggerService extends SystemService {
+    static final String TAG = "SoundTriggerService";
+    static final boolean DEBUG = false;
+
+    final Context mContext;
+    private final SoundTriggerServiceStub mServiceStub;
+    private final LocalSoundTriggerService mLocalSoundTriggerService;
+    private SoundTriggerDbHelper mDbHelper;
+
+    public SoundTriggerService(Context context) {
+        super(context);
+        mContext = context;
+        mServiceStub = new SoundTriggerServiceStub();
+        mLocalSoundTriggerService = new LocalSoundTriggerService(context);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.SOUND_TRIGGER_SERVICE, mServiceStub);
+        publishLocalService(SoundTriggerInternal.class, mLocalSoundTriggerService);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (PHASE_SYSTEM_SERVICES_READY == phase) {
+            mLocalSoundTriggerService.initSoundTriggerHelper();
+        } else if (PHASE_THIRD_PARTY_APPS_CAN_START == phase) {
+            mDbHelper = new SoundTriggerDbHelper(mContext);
+        }
+    }
+
+    @Override
+    public void onStartUser(int userHandle) {
+    }
+
+    @Override
+    public void onSwitchUser(int userHandle) {
+    }
+
+    class SoundTriggerServiceStub extends ISoundTriggerService.Stub {
+        @Override
+        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                throws RemoteException {
+            try {
+                return super.onTransact(code, data, reply, flags);
+            } catch (RuntimeException e) {
+                // The activity manager only throws security exceptions, so let's
+                // log all others.
+                if (!(e instanceof SecurityException)) {
+                    Slog.wtf(TAG, "SoundTriggerService Crash", e);
+                }
+                throw e;
+            }
+        }
+
+        @Override
+        public void startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback) {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (DEBUG) {
+                Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid);
+            }
+        }
+
+        @Override
+        public void stopRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback) {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (DEBUG) {
+                Slog.i(TAG, "stopRecognition(): Uuid : " + parcelUuid);
+            }
+        }
+
+        @Override
+        public SoundTrigger.GenericSoundModel getSoundModel(ParcelUuid soundModelId) {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (DEBUG) {
+                Slog.i(TAG, "getSoundModel(): id = " + soundModelId);
+            }
+            SoundTrigger.GenericSoundModel model = mDbHelper.getGenericSoundModel(soundModelId.getUuid());
+            if (model == null) {
+                Slog.e(TAG, "Null model in database.");
+            }
+            return model;
+        }
+
+        @Override
+        public void updateSoundModel(SoundTrigger.GenericSoundModel soundModel) {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (DEBUG) {
+                Slog.i(TAG, "updateSoundModel(): model = " + soundModel);
+            }
+            mDbHelper.updateGenericSoundModel(soundModel);
+        }
+
+        @Override
+        public void deleteSoundModel(ParcelUuid soundModelId) {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (DEBUG) {
+                Slog.i(TAG, "deleteSoundModel(): id = " + soundModelId);
+            }
+            mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
+        }
+    }
+
+    public final class LocalSoundTriggerService extends SoundTriggerInternal {
+        private final Context mContext;
+        private SoundTriggerHelper mSoundTriggerHelper;
+
+        LocalSoundTriggerService(Context context) {
+            mContext = context;
+        }
+
+        void initSoundTriggerHelper() {
+            if (mSoundTriggerHelper == null) {
+                mSoundTriggerHelper = new SoundTriggerHelper(mContext);
+            }
+        }
+
+        @Override
+        public int startRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+                IRecognitionStatusCallback listener, RecognitionConfig recognitionConfig) {
+            return mSoundTriggerHelper.startRecognition(keyphraseId, soundModel, listener,
+                    recognitionConfig);
+        }
+
+        @Override
+        public int stopRecognition(int keyphraseId, IRecognitionStatusCallback listener) {
+            return mSoundTriggerHelper.stopRecognition(keyphraseId, listener);
+        }
+
+        @Override
+        public void stopAllRecognitions() {
+            mSoundTriggerHelper.stopAllRecognitions();
+        }
+
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            mSoundTriggerHelper.dump(fd, pw, args);
+        }
+    }
+
+    private void enforceCallingPermission(String permission) {
+        if (mContext.checkCallingOrSelfPermission(permission)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Caller does not hold the permission " + permission);
+        }
+    }
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 2aef109..4a54643 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -62,6 +62,7 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.LocalServices;
+import com.android.server.soundtrigger.SoundTriggerInternal;
 import com.android.server.SystemService;
 import com.android.server.UiThread;
 
@@ -79,15 +80,14 @@
     final Context mContext;
     final ContentResolver mResolver;
     final DatabaseHelper mDbHelper;
-    final SoundTriggerHelper mSoundTriggerHelper;
     final ActivityManagerInternal mAmInternal;
+    SoundTriggerInternal mSoundTriggerInternal;
 
     public VoiceInteractionManagerService(Context context) {
         super(context);
         mContext = context;
         mResolver = context.getContentResolver();
         mDbHelper = new DatabaseHelper(context);
-        mSoundTriggerHelper = new SoundTriggerHelper(context);
         mServiceStub = new VoiceInteractionManagerServiceStub();
         mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
 
@@ -115,7 +115,9 @@
 
     @Override
     public void onBootPhase(int phase) {
-        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+        if (PHASE_SYSTEM_SERVICES_READY == phase) {
+            mSoundTriggerInternal = LocalServices.getService(SoundTriggerInternal.class);
+        } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
             mServiceStub.systemRunning(isSafeMode());
         }
     }
@@ -380,7 +382,7 @@
 
                 if (force || mImpl == null || mImpl.mUser != mCurUser
                         || !mImpl.mComponent.equals(serviceComponent)) {
-                    mSoundTriggerHelper.stopAllRecognitions();
+                    mSoundTriggerInternal.stopAllRecognitions();
                     if (mImpl != null) {
                         mImpl.shutdownLocked();
                     }
@@ -736,9 +738,9 @@
                             mImpl.notifySoundModelsChangedLocked();
                         }
                     }
-                    return SoundTriggerHelper.STATUS_OK;
+                    return SoundTriggerInternal.STATUS_OK;
                 } else {
-                    return SoundTriggerHelper.STATUS_ERROR;
+                    return SoundTriggerInternal.STATUS_ERROR;
                 }
             } finally {
                 Binder.restoreCallingIdentity(caller);
@@ -759,7 +761,7 @@
             boolean deleted = false;
             try {
                 deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
-                return deleted ? SoundTriggerHelper.STATUS_OK : SoundTriggerHelper.STATUS_ERROR;
+                return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
             } finally {
                 if (deleted) {
                     synchronized (this) {
@@ -812,7 +814,7 @@
 
                 final long caller = Binder.clearCallingIdentity();
                 try {
-                    return mSoundTriggerHelper.moduleProperties;
+                    return mSoundTriggerInternal.getModuleProperties();
                 } finally {
                     Binder.restoreCallingIdentity(caller);
                 }
@@ -845,9 +847,9 @@
                         || soundModel.uuid == null
                         || soundModel.keyphrases == null) {
                     Slog.w(TAG, "No matching sound model found in startRecognition");
-                    return SoundTriggerHelper.STATUS_ERROR;
+                    return SoundTriggerInternal.STATUS_ERROR;
                 } else {
-                    return mSoundTriggerHelper.startRecognition(
+                    return mSoundTriggerInternal.startRecognition(
                             keyphraseId, soundModel, callback, recognitionConfig);
                 }
             } finally {
@@ -869,7 +871,7 @@
 
             final long caller = Binder.clearCallingIdentity();
             try {
-                return mSoundTriggerHelper.stopRecognition(keyphraseId, callback);
+                return mSoundTriggerInternal.stopRecognition(keyphraseId, callback);
             } finally {
                 Binder.restoreCallingIdentity(caller);
             }
@@ -1011,7 +1013,7 @@
                 }
                 mImpl.dumpLocked(fd, pw, args);
             }
-            mSoundTriggerHelper.dump(fd, pw, args);
+            mSoundTriggerInternal.dump(fd, pw, args);
         }
 
         private void enforceCallingPermission(String permission) {
@@ -1060,7 +1062,7 @@
                     // The user is force stopping our current interactor/recognizer.
                     // Clear the current settings and restore default state.
                     synchronized (VoiceInteractionManagerService.this) {
-                        mSoundTriggerHelper.stopAllRecognitions();
+                        mSoundTriggerInternal.stopAllRecognitions();
                         if (mImpl != null) {
                             mImpl.shutdownLocked();
                             mImpl = null;
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 3859294..de90202 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -265,6 +265,7 @@
         // Next PROPERTY value: 0x00000040
         //******************************************************************************************
 
+        private final String mTelecomCallId;
         private final Uri mHandle;
         private final int mHandlePresentation;
         private final String mCallerDisplayName;
@@ -414,6 +415,11 @@
             return builder.toString();
         }
 
+        /** {@hide} */
+        public String getTelecomCallId() {
+            return mTelecomCallId;
+        }
+
         /**
          * @return The handle (e.g., phone number) to which the {@code Call} is currently
          * connected.
@@ -567,6 +573,7 @@
 
         /** {@hide} */
         public Details(
+                String telecomCallId,
                 Uri handle,
                 int handlePresentation,
                 String callerDisplayName,
@@ -581,6 +588,7 @@
                 StatusHints statusHints,
                 Bundle extras,
                 Bundle intentExtras) {
+            mTelecomCallId = telecomCallId;
             mHandle = handle;
             mHandlePresentation = handlePresentation;
             mCallerDisplayName = callerDisplayName;
@@ -596,6 +604,26 @@
             mExtras = extras;
             mIntentExtras = intentExtras;
         }
+
+        /** {@hide} */
+        public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
+            return new Details(
+                    parcelableCall.getId(),
+                    parcelableCall.getHandle(),
+                    parcelableCall.getHandlePresentation(),
+                    parcelableCall.getCallerDisplayName(),
+                    parcelableCall.getCallerDisplayNamePresentation(),
+                    parcelableCall.getAccountHandle(),
+                    parcelableCall.getCapabilities(),
+                    parcelableCall.getProperties(),
+                    parcelableCall.getDisconnectCause(),
+                    parcelableCall.getConnectTimeMillis(),
+                    parcelableCall.getGatewayInfo(),
+                    parcelableCall.getVideoState(),
+                    parcelableCall.getStatusHints(),
+                    parcelableCall.getExtras(),
+                    parcelableCall.getIntentExtras());
+        }
     }
 
     public static abstract class Callback {
@@ -1022,21 +1050,7 @@
     /** {@hide} */
     final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
         // First, we update the internal state as far as possible before firing any updates.
-        Details details = new Details(
-                parcelableCall.getHandle(),
-                parcelableCall.getHandlePresentation(),
-                parcelableCall.getCallerDisplayName(),
-                parcelableCall.getCallerDisplayNamePresentation(),
-                parcelableCall.getAccountHandle(),
-                parcelableCall.getCapabilities(),
-                parcelableCall.getProperties(),
-                parcelableCall.getDisconnectCause(),
-                parcelableCall.getConnectTimeMillis(),
-                parcelableCall.getGatewayInfo(),
-                parcelableCall.getVideoState(),
-                parcelableCall.getStatusHints(),
-                parcelableCall.getExtras(),
-                parcelableCall.getIntentExtras());
+        Details details = Details.createFromParcelableCall(parcelableCall);
         boolean detailsChanged = !Objects.equals(mDetails, details);
         if (detailsChanged) {
             mDetails = details;
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
new file mode 100644
index 0000000..f62b170
--- /dev/null
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.telecom;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+
+import com.android.internal.os.SomeArgs;
+import com.android.internal.telecom.ICallScreeningService;
+import com.android.internal.telecom.ICallScreeningAdapter;
+
+/**
+ * This service can be implemented by the default dialer (see
+ * {@link TelecomManager#getDefaultDialerPackage()}) to allow or disallow incoming calls before
+ * they are shown to a user.
+ * <p>
+ * Below is an example manifest registration for a {@code CallScreeningService}.
+ * <pre>
+ * {@code
+ * <service android:name="your.package.YourCallScreeningServiceImplementation"
+ *          android:permission="android.permission.BIND_SCREENING_SERVICE">
+ *      <intent-filter>
+ *          <action android:name="android.telecom.CallScreeningService"/>
+ *      </intent-filter>
+ * </service>
+ * }
+ * </pre>
+ */
+public abstract class CallScreeningService extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.telecom.CallScreeningService";
+
+    private static final int MSG_SCREEN_CALL = 1;
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SCREEN_CALL:
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        mCallScreeningAdapter = (ICallScreeningAdapter) args.arg1;
+                        onScreenCall(
+                                Call.Details.createFromParcelableCall((ParcelableCall) args.arg2));
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+            }
+        }
+    };
+
+    private final class CallScreeningBinder extends ICallScreeningService.Stub {
+        @Override
+        public void screenCall(ICallScreeningAdapter adapter, ParcelableCall call) {
+            Log.v(this, "screenCall");
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = adapter;
+            args.arg2 = call;
+            mHandler.obtainMessage(MSG_SCREEN_CALL, args).sendToTarget();
+        }
+    }
+
+    private ICallScreeningAdapter mCallScreeningAdapter;
+
+    /*
+     * Information about how to respond to an incoming call.
+     */
+    public static class CallResponse {
+        private final boolean mShouldDisallowCall;
+        private final boolean mShouldRejectCall;
+        private final boolean mShouldSkipCallLog;
+        private final boolean mShouldSkipNotification;
+
+        private CallResponse(
+                boolean shouldDisallowCall,
+                boolean shouldRejectCall,
+                boolean shouldSkipCallLog,
+                boolean shouldSkipNotification) {
+            if (!shouldDisallowCall
+                    && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) {
+                throw new IllegalStateException("Invalid response state for allowed call.");
+            }
+
+            mShouldDisallowCall = shouldDisallowCall;
+            mShouldRejectCall = shouldRejectCall;
+            mShouldSkipCallLog = shouldSkipCallLog;
+            mShouldSkipNotification = shouldSkipNotification;
+        }
+
+        /*
+         * @return Whether the incoming call should be blocked.
+         */
+        public boolean getDisallowCall() {
+            return mShouldDisallowCall;
+        }
+
+        /*
+         * @return Whether the incoming call should be disconnected as if the user had manually
+         * rejected it.
+         */
+        public boolean getRejectCall() {
+            return mShouldRejectCall;
+        }
+
+        /*
+         * @return Whether the incoming call should not be displayed in the call log.
+         */
+        public boolean getSkipCallLog() {
+            return mShouldSkipCallLog;
+        }
+
+        /*
+         * @return Whether a missed call notification should not be shown for the incoming call.
+         */
+        public boolean getSkipNotification() {
+            return mShouldSkipNotification;
+        }
+
+        public static class Builder {
+            private boolean mShouldDisallowCall;
+            private boolean mShouldRejectCall;
+            private boolean mShouldSkipCallLog;
+            private boolean mShouldSkipNotification;
+
+            /*
+             * Sets whether the incoming call should be blocked.
+             */
+            public Builder setDisallowCall(boolean shouldDisallowCall) {
+                mShouldDisallowCall = shouldDisallowCall;
+                return this;
+            }
+
+            /*
+             * Sets whether the incoming call should be disconnected as if the user had manually
+             * rejected it. This property should only be set to true if the call is disallowed.
+             */
+            public Builder setRejectCall(boolean shouldRejectCall) {
+                mShouldRejectCall = shouldRejectCall;
+                return this;
+            }
+
+            /*
+             * Sets whether the incoming call should not be displayed in the call log. This property
+             * should only be set to true if the call is disallowed.
+             */
+            public Builder setSkipCallLog(boolean shouldSkipCallLog) {
+                mShouldSkipCallLog = shouldSkipCallLog;
+                return this;
+            }
+
+            /*
+             * Sets whether a missed call notification should not be shown for the incoming call.
+             * This property should only be set to true if the call is disallowed.
+             */
+            public Builder setSkipNotification(boolean shouldSkipNotification) {
+                mShouldSkipNotification = shouldSkipNotification;
+                return this;
+            }
+
+            public CallResponse build() {
+                return new CallResponse(
+                        mShouldDisallowCall,
+                        mShouldRejectCall,
+                        mShouldSkipCallLog,
+                        mShouldSkipNotification);
+            }
+       }
+    }
+
+    public CallScreeningService() {
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.v(this, "onBind");
+        return new CallScreeningBinder();
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.v(this, "onUnbind");
+        return false;
+    }
+
+    /**
+     * Called when a new incoming call is added.
+     * {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}
+     * should be called to allow or disallow the call.
+     *
+     * @param callDetails Information about a new incoming call, see {@link Call.Details}.
+     */
+    public abstract void onScreenCall(Call.Details callDetails);
+
+    /**
+     * Responds to the given call, either allowing it or disallowing it.
+     *
+     * @param callDetails The call to allow.
+     * @param response The {@link CallScreeningService.CallResponse} which contains information
+     * about how to respond to a call.
+     */
+    public final void respondToCall(Call.Details callDetails, CallResponse response) {
+        try {
+            if (response.getDisallowCall()) {
+                mCallScreeningAdapter.disallowCall(
+                        callDetails.getTelecomCallId(),
+                        response.getRejectCall(),
+                        !response.getSkipCallLog(),
+                        !response.getSkipNotification());
+            } else {
+                mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
+            }
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 426b240..671399b 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -73,6 +73,7 @@
     private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5;
     private static final int MSG_BRING_TO_FOREGROUND = 6;
     private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
+    private static final int MSG_SILENCE_RINGER = 8;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -114,6 +115,9 @@
                 case MSG_ON_CAN_ADD_CALL_CHANGED:
                     mPhone.internalSetCanAddCall(msg.arg1 == 1);
                     break;
+                case MSG_SILENCE_RINGER:
+                    mPhone.internalSilenceRinger();
+                    break;
                 default:
                     break;
             }
@@ -165,6 +169,11 @@
             mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0)
                     .sendToTarget();
         }
+
+        @Override
+        public void silenceRinger() {
+            mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
+        }
     }
 
     private Phone.Listener mPhoneListener = new Phone.Listener() {
@@ -202,6 +211,12 @@
             InCallService.this.onCanAddCallChanged(canAddCall);
         }
 
+        /** ${inheritDoc} */
+        @Override
+        public void onSilenceRinger(Phone phone) {
+            InCallService.this.onSilenceRinger();
+        }
+
     };
 
     private Phone mPhone;
@@ -405,6 +420,12 @@
     }
 
     /**
+     * Called to silence the ringer if a ringing call exists.
+     */
+    public void onSilenceRinger() {
+    }
+
+    /**
      * Used to issue commands to the {@link Connection.VideoProvider} associated with a
      * {@link Call}.
      */
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 47154da..56eb7ec 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -97,6 +97,13 @@
          * @param canAddCall Indicates whether an additional call can be added.
          */
         public void onCanAddCallChanged(Phone phone, boolean canAddCall) { }
+
+        /**
+         * Called to silence the ringer if a ringing call exists.
+         *
+         * @param phone The {@code Phone} calling this method.
+         */
+        public void onSilenceRinger(Phone phone) { }
     }
 
     // A Map allows us to track each Call by its Telecom-specified call ID
@@ -179,6 +186,10 @@
         }
     }
 
+    final void internalSilenceRinger() {
+        fireSilenceRinger();
+    }
+
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      */
@@ -330,6 +341,12 @@
         }
     }
 
+    private void fireSilenceRinger() {
+        for (Listener listener : mListeners) {
+            listener.onSilenceRinger(this);
+        }
+    }
+
     private void checkCallTree(ParcelableCall parcelableCall) {
         if (parcelableCall.getParentCallId() != null &&
                 !mCallByTelecomCallId.containsKey(parcelableCall.getParentCallId())) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 497864e..72ff272 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -308,6 +308,15 @@
             "android.telecom.IN_CALL_SERVICE_CAR_MODE_UI";
 
     /**
+     * A boolean meta-data value indicating whether an {@link InCallService} implements ringing.
+     * Dialer implementations (see {@link #getDefaultDialerPackage()}) which would also like to
+     * override the system provided ringing should set this meta-data to {@code true} in the
+     * manifest registration of their {@link InCallService}.
+     */
+    public static final String METADATA_IN_CALL_SERVICE_RINGING =
+            "android.telecom.IN_CALL_SERVICE_RINGING";
+
+    /**
      * The dual tone multi-frequency signaling character sent to indicate the dialing system should
      * pause for a predefined period.
      */
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
new file mode 100644
index 0000000..2e0af27
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telecom;
+
+/**
+ * Internal remote callback interface for call screening services.
+ *
+ * @see android.telecom.CallScreeningService
+ *
+ * {@hide}
+ */
+oneway interface ICallScreeningAdapter {
+    void allowCall(String callId);
+
+    void disallowCall(
+            String callId,
+            boolean shouldReject,
+            boolean shouldAddToCallLog,
+            boolean shouldShowNotification);
+}
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl
new file mode 100644
index 0000000..c3fe1af
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telecom;
+
+import android.telecom.ParcelableCall;
+
+import com.android.internal.telecom.ICallScreeningAdapter;
+
+/**
+ * Internal remote interface for a call screening service.
+ * @see android.telecom.CallScreeningService
+ * @hide
+ */
+oneway interface ICallScreeningService {
+    void screenCall(in ICallScreeningAdapter adapter, in ParcelableCall call);
+}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index ded47d5..0088e0c 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -45,4 +45,6 @@
     void bringToForeground(boolean showDialpad);
 
     void onCanAddCallChanged(boolean canAddCall);
+
+    void silenceRinger();
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 630dacc..4368b81 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -409,6 +409,11 @@
     public static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN = "vvm_cellular_data_required";
 
     /**
+     * Whether to prefetch audio data on new voicemail arrival, defaulted to true.
+     */
+    public static final String KEY_VVM_PREFETCH_BOOLEAN = "vvm_prefetch";
+
+    /**
      * The package name of the carrier's visual voicemail app to ensure that dialer visual voicemail
      * and carrier visual voicemail are not active at the same time.
      */
@@ -638,6 +643,7 @@
         sDefaults.putInt(KEY_VVM_PORT_NUMBER_INT, 0);
         sDefaults.putString(KEY_VVM_TYPE_STRING, "");
         sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false);
+        sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true);
         sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
         sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 90d2aa0..74f1171 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -38,6 +38,10 @@
     private final int mLac;
     // 16-bit GSM Cell Identity described in TS 27.007, 0..65535
     private final int mCid;
+    // 16-bit GSM Absolute RF Channel Number
+    private final int mArfcn;
+    // 6-bit Base Station Identity Code
+    private final int mBsic;
 
     /**
      * @hide
@@ -47,6 +51,8 @@
         mMnc = Integer.MAX_VALUE;
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
+        mArfcn = Integer.MAX_VALUE;
+        mBsic = Integer.MAX_VALUE;
     }
     /**
      * public constructor
@@ -58,10 +64,27 @@
      * @hide
      */
     public CellIdentityGsm (int mcc, int mnc, int lac, int cid) {
+        this(mcc, mnc, lac, cid, Integer.MAX_VALUE, Integer.MAX_VALUE);
+    }
+
+    /**
+     * public constructor
+     * @param mcc 3-digit Mobile Country Code, 0..999
+     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+     * @param lac 16-bit Location Area Code, 0..65535
+     * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
+     * @param arfcn 16-bit GSM Absolute RF Channel Number
+     * @param bsic 6-bit Base Station Identity Code
+     *
+     * @hide
+     */
+    public CellIdentityGsm (int mcc, int mnc, int lac, int cid, int arfcn, int bsic) {
         mMcc = mcc;
         mMnc = mnc;
         mLac = lac;
         mCid = cid;
+        mArfcn = arfcn;
+        mBsic = bsic;
     }
 
     private CellIdentityGsm(CellIdentityGsm cid) {
@@ -69,6 +92,8 @@
         mMnc = cid.mMnc;
         mLac = cid.mLac;
         mCid = cid.mCid;
+        mArfcn = cid.mArfcn;
+        mBsic = cid.mBsic;
     }
 
     CellIdentityGsm copy() {
@@ -106,6 +131,21 @@
     }
 
     /**
+     * @return 16-bit GSM Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+     */
+    public int getArfcn() {
+        return mArfcn;
+    }
+
+    /**
+     * @return 6-bit Base Station Identity Code, Integer.MAX_VALUE if unknown
+     */
+    public int getBsic() {
+        return mBsic;
+    }
+
+
+    /**
      * @return Integer.MAX_VALUE, undefined for GSM
      */
     @Deprecated
@@ -132,7 +172,9 @@
         return mMcc == o.mMcc &&
                 mMnc == o.mMnc &&
                 mLac == o.mLac &&
-                mCid == o.mCid;
+                mCid == o.mCid &&
+                mArfcn == o.mArfcn &&
+                mBsic == o.mBsic;
     }
 
     @Override
@@ -142,6 +184,8 @@
         sb.append(" mMnc=").append(mMnc);
         sb.append(" mLac=").append(mLac);
         sb.append(" mCid=").append(mCid);
+        sb.append(" mArfcn=").append(mArfcn);
+        sb.append(" mBsic=").append("0x").append(Integer.toHexString(mBsic));
         sb.append("}");
 
         return sb.toString();
@@ -161,6 +205,8 @@
         dest.writeInt(mMnc);
         dest.writeInt(mLac);
         dest.writeInt(mCid);
+        dest.writeInt(mArfcn);
+        dest.writeInt(mBsic);
     }
 
     /** Construct from Parcel, type has already been processed */
@@ -169,6 +215,8 @@
         mMnc = in.readInt();
         mLac = in.readInt();
         mCid = in.readInt();
+        mArfcn = in.readInt();
+        mBsic = in.readInt();
         if (DBG) log("CellIdentityGsm(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 1e7ac08..ce74383 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -40,6 +40,8 @@
     private final int mPci;
     // 16-bit tracking area code
     private final int mTac;
+    // 18-bit Absolute RF Channel Number
+    private final int mEarfcn;
 
     /**
      * @hide
@@ -50,6 +52,7 @@
         mCi = Integer.MAX_VALUE;
         mPci = Integer.MAX_VALUE;
         mTac = Integer.MAX_VALUE;
+        mEarfcn = Integer.MAX_VALUE;
     }
 
     /**
@@ -63,11 +66,27 @@
      * @hide
      */
     public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac) {
+        this(mcc, mnc, ci, pci, tac, Integer.MAX_VALUE);
+    }
+
+    /**
+     *
+     * @param mcc 3-digit Mobile Country Code, 0..999
+     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+     * @param ci 28-bit Cell Identity
+     * @param pci Physical Cell Id 0..503
+     * @param tac 16-bit Tracking Area Code
+     * @param earfcn 18-bit LTE Absolute RF Channel Number
+     *
+     * @hide
+     */
+    public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
         mMcc = mcc;
         mMnc = mnc;
         mCi = ci;
         mPci = pci;
         mTac = tac;
+        mEarfcn = earfcn;
     }
 
     private CellIdentityLte(CellIdentityLte cid) {
@@ -76,6 +95,7 @@
         mCi = cid.mCi;
         mPci = cid.mPci;
         mTac = cid.mTac;
+        mEarfcn = cid.mEarfcn;
     }
 
     CellIdentityLte copy() {
@@ -117,6 +137,13 @@
         return mTac;
     }
 
+    /**
+     * @return 18-bit Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+     */
+    public int getEarfcn() {
+        return mEarfcn;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mMcc, mMnc, mCi, mPci, mTac);
@@ -137,7 +164,8 @@
                 mMnc == o.mMnc &&
                 mCi == o.mCi &&
                 mPci == o.mPci &&
-                mTac == o.mTac;
+                mTac == o.mTac &&
+                mEarfcn == o.mEarfcn;
     }
 
     @Override
@@ -148,6 +176,7 @@
         sb.append(" mCi="); sb.append(mCi);
         sb.append(" mPci="); sb.append(mPci);
         sb.append(" mTac="); sb.append(mTac);
+        sb.append(" mEarfcn="); sb.append(mEarfcn);
         sb.append("}");
 
         return sb.toString();
@@ -168,6 +197,7 @@
         dest.writeInt(mCi);
         dest.writeInt(mPci);
         dest.writeInt(mTac);
+        dest.writeInt(mEarfcn);
     }
 
     /** Construct from Parcel, type has already been processed */
@@ -177,6 +207,7 @@
         mCi = in.readInt();
         mPci = in.readInt();
         mTac = in.readInt();
+        mEarfcn = in.readInt();
         if (DBG) log("CellIdentityLte(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 56ee8c9..0d13efd 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -40,6 +40,8 @@
     private final int mCid;
     // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
     private final int mPsc;
+    // 16-bit UMTS Absolute RF Channel Number
+    private final int mUarfcn;
 
     /**
      * @hide
@@ -50,6 +52,7 @@
         mLac = Integer.MAX_VALUE;
         mCid = Integer.MAX_VALUE;
         mPsc = Integer.MAX_VALUE;
+        mUarfcn = Integer.MAX_VALUE;
     }
     /**
      * public constructor
@@ -62,11 +65,27 @@
      * @hide
      */
     public CellIdentityWcdma (int mcc, int mnc, int lac, int cid, int psc) {
+        this(mcc, mnc, lac, cid, psc, Integer.MAX_VALUE);
+    }
+
+    /**
+     * public constructor
+     * @param mcc 3-digit Mobile Country Code, 0..999
+     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+     * @param lac 16-bit Location Area Code, 0..65535
+     * @param cid 28-bit UMTS Cell Identity
+     * @param psc 9-bit UMTS Primary Scrambling Code
+     * @param uarfcn 16-bit UMTS Absolute RF Channel Number
+     *
+     * @hide
+     */
+    public CellIdentityWcdma (int mcc, int mnc, int lac, int cid, int psc, int uarfcn) {
         mMcc = mcc;
         mMnc = mnc;
         mLac = lac;
         mCid = cid;
         mPsc = psc;
+        mUarfcn = uarfcn;
     }
 
     private CellIdentityWcdma(CellIdentityWcdma cid) {
@@ -75,6 +94,7 @@
         mLac = cid.mLac;
         mCid = cid.mCid;
         mPsc = cid.mPsc;
+        mUarfcn = cid.mUarfcn;
     }
 
     CellIdentityWcdma copy() {
@@ -123,6 +143,13 @@
         return Objects.hash(mMcc, mMnc, mLac, mCid, mPsc);
     }
 
+    /**
+     * @return 16-bit UMTS Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+     */
+    public int getUarfcn() {
+        return mUarfcn;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
@@ -138,7 +165,8 @@
                 mMnc == o.mMnc &&
                 mLac == o.mLac &&
                 mCid == o.mCid &&
-                mPsc == o.mPsc;
+                mPsc == o.mPsc &&
+                mUarfcn == o.mUarfcn;
     }
 
     @Override
@@ -149,6 +177,7 @@
         sb.append(" mLac=").append(mLac);
         sb.append(" mCid=").append(mCid);
         sb.append(" mPsc=").append(mPsc);
+        sb.append(" mUarfcn=").append(mUarfcn);
         sb.append("}");
 
         return sb.toString();
@@ -169,6 +198,7 @@
         dest.writeInt(mLac);
         dest.writeInt(mCid);
         dest.writeInt(mPsc);
+        dest.writeInt(mUarfcn);
     }
 
     /** Construct from Parcel, type has already been processed */
@@ -178,6 +208,7 @@
         mLac = in.readInt();
         mCid = in.readInt();
         mPsc = in.readInt();
+        mUarfcn = in.readInt();
         if (DBG) log("CellIdentityWcdma(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index d27fcec..addf7ef 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -34,6 +34,7 @@
 
     private int mSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
     private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+    private int mTimingAdvance;
 
     /**
      * Empty constructor
@@ -75,6 +76,22 @@
     public void initialize(int ss, int ber) {
         mSignalStrength = ss;
         mBitErrorRate = ber;
+        mTimingAdvance = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param ss SignalStrength as ASU value
+     * @param ber is Bit Error Rate
+     * @param ta timing advance
+     *
+     * @hide
+     */
+    public void initialize(int ss, int ber, int ta) {
+        mSignalStrength = ss;
+        mBitErrorRate = ber;
+        mTimingAdvance = ta;
     }
 
     /**
@@ -83,6 +100,7 @@
     protected void copyFrom(CellSignalStrengthGsm s) {
         mSignalStrength = s.mSignalStrength;
         mBitErrorRate = s.mBitErrorRate;
+        mTimingAdvance = s.mTimingAdvance;
     }
 
     /**
@@ -98,6 +116,7 @@
     public void setDefaultValues() {
         mSignalStrength = Integer.MAX_VALUE;
         mBitErrorRate = Integer.MAX_VALUE;
+        mTimingAdvance = Integer.MAX_VALUE;
     }
 
     /**
@@ -174,7 +193,8 @@
             return false;
         }
 
-        return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate;
+        return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate &&
+                        s.mTimingAdvance == mTimingAdvance;
     }
 
     /**
@@ -184,7 +204,8 @@
     public String toString() {
         return "CellSignalStrengthGsm:"
                 + " ss=" + mSignalStrength
-                + " ber=" + mBitErrorRate;
+                + " ber=" + mBitErrorRate
+                + " mTa=" + mTimingAdvance;
     }
 
     /** Implement the Parcelable interface */
@@ -193,6 +214,7 @@
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
         dest.writeInt(mSignalStrength);
         dest.writeInt(mBitErrorRate);
+        dest.writeInt(mTimingAdvance);
     }
 
     /**
@@ -202,6 +224,7 @@
     private CellSignalStrengthGsm(Parcel in) {
         mSignalStrength = in.readInt();
         mBitErrorRate = in.readInt();
+        mTimingAdvance = in.readInt();
         if (DBG) log("CellSignalStrengthGsm(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index ea96e7c..84883d8 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -48,7 +48,9 @@
         mTimestamp = timestamp;
         mSleepTimeMs = sleepTimeMs;
         mIdleTimeMs = idleTimeMs;
-        System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+        if (txTimeMs != null) {
+            System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+        }
         mRxTimeMs = rxTimeMs;
         mEnergyUsed = energyUsed;
     }
@@ -58,6 +60,7 @@
         return "ModemActivityInfo{"
             + " mTimestamp=" + mTimestamp
             + " mSleepTimeMs=" + mSleepTimeMs
+            + " mIdleTimeMs=" + mIdleTimeMs
             + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
             + " mRxTimeMs=" + mRxTimeMs
             + " mEnergyUsed=" + mEnergyUsed
@@ -153,7 +156,7 @@
         for (int i = 0; i < TX_POWER_LEVELS; i++) {
             totalTxTimeMs += txTime[i];
         }
-        return ((getIdleTimeMillis() != 0) || (totalTxTimeMs != 0)
-                || (getSleepTimeMillis() != 0) || (getIdleTimeMillis() != 0));
+        return ((getIdleTimeMillis() >= 0) && (totalTxTimeMs >= 0)
+                && (getSleepTimeMillis() >= 0) && (getIdleTimeMillis() >= 0));
     }
 }
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b089387..962a600 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1857,9 +1857,6 @@
         // to the list.
         number = extractNetworkPortionAlt(number);
 
-        Rlog.d(LOG_TAG, "subId:" + subId + ", defaultCountryIso:" +
-                ((defaultCountryIso == null) ? "NULL" : defaultCountryIso));
-
         String emergencyNumbers = "";
         int slotId = SubscriptionManager.getSlotId(subId);
 
@@ -1869,7 +1866,8 @@
 
         emergencyNumbers = SystemProperties.get(ecclist, "");
 
-        Rlog.d(LOG_TAG, "slotId:" + slotId + ", emergencyNumbers: " +  emergencyNumbers);
+        Rlog.d(LOG_TAG, "slotId:" + slotId + " subId:" + subId + " country:"
+                + defaultCountryIso + " emergencyNumbers: " +  emergencyNumbers);
 
         if (TextUtils.isEmpty(emergencyNumbers)) {
             // then read-only ecclist property since old RIL only uses this
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index c680999..ad007c6 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -37,6 +37,7 @@
 
     static final String LOG_TAG = "PHONE";
     static final boolean DBG = true;
+    static final boolean VDBG = false;  // STOPSHIP if true
 
     /**
      * Normal operation condition, the phone is registered
@@ -829,7 +830,7 @@
     /** @hide */
     public void setDataRegState(int state) {
         mDataRegState = state;
-        if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
+        if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
     }
 
     public void setRoaming(boolean roaming) {
@@ -1017,7 +1018,8 @@
     /** @hide */
     public void setRilDataRadioTechnology(int rt) {
         this.mRilDataRadioTechnology = rt;
-        if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setDataRadioTechnology=" + mRilDataRadioTechnology);
+        if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setRilDataRadioTechnology=" +
+                mRilDataRadioTechnology);
     }
 
     /** @hide */
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
index 5dffa28..069fcbf 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
@@ -16,8 +16,9 @@
 
 package com.android.internal.telephony;
 
-import android.os.Bundle;
+import com.android.internal.telephony.ITelephonyDebugSubscriber;
 
+import android.os.Bundle;
 
 /**
  * Interface used to interact with the Telephony debug service.
@@ -36,4 +37,7 @@
      * @param data optional
      */
     void writeEvent(long timestamp, int phoneId, int tag, int param1, int param2, in Bundle data);
+
+    void subscribe(in ITelephonyDebugSubscriber subscriber);
+    void unsubscribe(in ITelephonyDebugSubscriber subscriber);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
new file mode 100644
index 0000000..64eb0f1
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.TelephonyEvent;
+
+import android.os.Bundle;
+
+/**
+ * Interface used to subscribe for events from Telephony debug service.
+ *
+ * {@hide}
+ */
+oneway interface ITelephonyDebugSubscriber {
+
+    /**
+     * Called when Telephony debug service has events.
+     */
+    void onEvents(in TelephonyEvent[] events);
+}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 3c4c04b..7d5645e 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -336,6 +336,8 @@
     int RIL_REQUEST_PULL_LCEDATA = 134;
     int RIL_REQUEST_GET_ACTIVITY_INFO = 135;
 
+    int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
+
     int RIL_UNSOL_RESPONSE_BASE = 1000;
     int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
     int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl b/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
new file mode 100644
index 0000000..1e74b31
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+parcelable TelephonyEvent;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.java b/telephony/java/com/android/internal/telephony/TelephonyEvent.java
new file mode 100644
index 0000000..26d466d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyEvent.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ *  A parcelable used in ITelephonyDebugSubscriber.aidl
+ */
+public class TelephonyEvent implements Parcelable {
+
+    final public long timestamp;
+    final public int phoneId;
+    final public int tag;
+    final public int param1;
+    final public int param2;
+    final public Bundle data;
+
+    public TelephonyEvent(long timestamp, int phoneId, int tag,
+            int param1, int param2, Bundle data) {
+        this.timestamp = timestamp;
+        this.phoneId = phoneId;
+        this.tag = tag;
+        this.param1 = param1;
+        this.param2 = param2;
+        this.data = data;
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Parcelable.Creator<TelephonyEvent> CREATOR
+            = new Parcelable.Creator<TelephonyEvent> (){
+        public TelephonyEvent createFromParcel(Parcel source) {
+            final long timestamp = source.readLong();
+            final int phoneId = source.readInt();
+            final int tag = source.readInt();
+            final int param1 = source.readInt();
+            final int param2 = source.readInt();
+            final Bundle data = source.readBundle();
+            return new TelephonyEvent(timestamp, phoneId, tag, param1, param2, data);
+        }
+
+        public TelephonyEvent[] newArray(int size) {
+            return new TelephonyEvent[size];
+        }
+    };
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(timestamp);
+        dest.writeInt(phoneId);
+        dest.writeInt(tag);
+        dest.writeInt(param1);
+        dest.writeInt(param2);
+        dest.writeBundle(data);
+    }
+
+    public String toString() {
+        return String.format("%d,%d,%d,%d,%d,%s",
+                timestamp, phoneId, tag, param1, param2, data);
+    }
+}
diff --git a/test-runner/src/android/test/ActivityInstrumentationTestCase.java b/test-runner/src/android/test/ActivityInstrumentationTestCase.java
index a59ee35..aca1c16 100644
--- a/test-runner/src/android/test/ActivityInstrumentationTestCase.java
+++ b/test-runner/src/android/test/ActivityInstrumentationTestCase.java
@@ -23,15 +23,15 @@
  * be created using the system infrastructure (by calling InstrumentationTestCase.launchActivity())
  * and you will then be able to manipulate your Activity directly.  Most of the work is handled
  * automatically here by {@link #setUp} and {@link #tearDown}.
- * 
+ *
  * <p>If you prefer an isolated unit test, see {@link android.test.ActivityUnitTestCase}.
- * 
- * @deprecated new tests should be written using 
+ *
+ * @deprecated new tests should be written using
  * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
  * configuring the Activity under test
  */
 @Deprecated
-public abstract class ActivityInstrumentationTestCase<T extends Activity> 
+public abstract class ActivityInstrumentationTestCase<T extends Activity>
         extends ActivityTestCase {
     String mPackage;
     Class<T> mActivityClass;
@@ -39,7 +39,7 @@
 
     /**
      * Creates an {@link ActivityInstrumentationTestCase} in non-touch mode.
-     * 
+     *
      * @param pkg ignored - no longer in use.
      * @param activityClass The activity to test. This must be a class in the instrumentation
      * targetPackage specified in the AndroidManifest.xml
@@ -56,7 +56,7 @@
      * targetPackage specified in the AndroidManifest.xml
      * @param initialTouchMode true = in touch mode
      */
-    public ActivityInstrumentationTestCase(String pkg, Class<T> activityClass, 
+    public ActivityInstrumentationTestCase(String pkg, Class<T> activityClass,
             boolean initialTouchMode) {
         mActivityClass = activityClass;
         mInitialTouchMode = initialTouchMode;
@@ -80,8 +80,8 @@
     protected void tearDown() throws Exception {
         getActivity().finish();
         setActivity(null);
-        
-        // Scrub out members - protects against memory leaks in the case where someone 
+
+        // Scrub out members - protects against memory leaks in the case where someone
         // creates a non-static inner class (thus referencing the test case) and gives it to
         // someone else to hold onto
         scrubClass(ActivityInstrumentationTestCase.class);
diff --git a/test-runner/src/android/test/ActivityInstrumentationTestCase2.java b/test-runner/src/android/test/ActivityInstrumentationTestCase2.java
index c4bcf31..0e61ce7 100644
--- a/test-runner/src/android/test/ActivityInstrumentationTestCase2.java
+++ b/test-runner/src/android/test/ActivityInstrumentationTestCase2.java
@@ -25,26 +25,26 @@
  * This class provides functional testing of a single activity.  The activity under test will
  * be created using the system infrastructure (by calling InstrumentationTestCase.launchActivity())
  * and you will then be able to manipulate your Activity directly.
- * 
+ *
  * <p>Other options supported by this test case include:
  * <ul>
  * <li>You can run any test method on the UI thread (see {@link android.test.UiThreadTest}).</li>
- * <li>You can inject custom Intents into your Activity (see 
+ * <li>You can inject custom Intents into your Activity (see
  * {@link #setActivityIntent(Intent)}).</li>
  * </ul>
- * 
+ *
  * <p>This class replaces {@link android.test.ActivityInstrumentationTestCase}, which is deprecated.
  * New tests should be written using this base class.
- * 
+ *
  * <p>If you prefer an isolated unit test, see {@link android.test.ActivityUnitTestCase}.
  *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about application testing, read the
- * <a href="{@docRoot}guide/topics/testing/index.html">Testing</a> developer guide.</p>
- * </div>
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">
+ * ActivityTestRule</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
-public abstract class ActivityInstrumentationTestCase2<T extends Activity> 
+@Deprecated
+public abstract class ActivityInstrumentationTestCase2<T extends Activity>
         extends ActivityTestCase {
     Class<T> mActivityClass;
     boolean mInitialTouchMode = false;
@@ -78,18 +78,18 @@
      * Get the Activity under test, starting it if necessary.
      *
      * For each test method invocation, the Activity will not actually be created until the first
-     * time this method is called. 
-     * 
-     * <p>If you wish to provide custom setup values to your Activity, you may call 
-     * {@link #setActivityIntent(Intent)} and/or {@link #setActivityInitialTouchMode(boolean)} 
-     * before your first call to getActivity().  Calling them after your Activity has 
+     * time this method is called.
+     *
+     * <p>If you wish to provide custom setup values to your Activity, you may call
+     * {@link #setActivityIntent(Intent)} and/or {@link #setActivityInitialTouchMode(boolean)}
+     * before your first call to getActivity().  Calling them after your Activity has
      * started will have no effect.
      *
      * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
      * If your test method is annotated with {@link android.test.UiThreadTest}, then your Activity
      * will be started automatically just before your test method is run.  You still call this
      * method in order to get the Activity under test.
-     * 
+     *
      * @return the Activity under test
      */
     @Override
@@ -113,10 +113,10 @@
     /**
      * Call this method before the first call to {@link #getActivity} to inject a customized Intent
      * into the Activity under test.
-     * 
+     *
      * <p>If you do not call this, the default intent will be provided.  If you call this after
      * your Activity has been started, it will have no effect.
-     * 
+     *
      * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
      * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
      * {@link #setActivityIntent(Intent)} from {@link #setUp()}.
@@ -131,28 +131,28 @@
     public void setActivityIntent(Intent i) {
         mActivityIntent = i;
     }
-    
+
     /**
      * Call this method before the first call to {@link #getActivity} to set the initial touch
      * mode for the Activity under test.
-     * 
+     *
      * <p>If you do not call this, the touch mode will be false.  If you call this after
      * your Activity has been started, it will have no effect.
-     * 
+     *
      * <p><b>NOTE:</b> Activities under test may not be started from within the UI thread.
      * If your test method is annotated with {@link android.test.UiThreadTest}, then you must call
      * {@link #setActivityInitialTouchMode(boolean)} from {@link #setUp()}.
-     * 
+     *
      * @param initialTouchMode true if the Activity should be placed into "touch mode" when started
      */
     public void setActivityInitialTouchMode(boolean initialTouchMode) {
         mInitialTouchMode = initialTouchMode;
     }
-    
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        
+
         mInitialTouchMode = false;
         mActivityIntent = null;
     }
@@ -165,8 +165,8 @@
             a.finish();
             setActivity(null);
         }
-        
-        // Scrub out members - protects against memory leaks in the case where someone 
+
+        // Scrub out members - protects against memory leaks in the case where someone
         // creates a non-static inner class (thus referencing the test case) and gives it to
         // someone else to hold onto
         scrubClass(ActivityInstrumentationTestCase2.class);
diff --git a/test-runner/src/android/test/ActivityTestCase.java b/test-runner/src/android/test/ActivityTestCase.java
index c7b1d70..51dd3ef 100644
--- a/test-runner/src/android/test/ActivityTestCase.java
+++ b/test-runner/src/android/test/ActivityTestCase.java
@@ -25,7 +25,11 @@
  * This is common code used to support Activity test cases.  For more useful classes, please see
  * {@link android.test.ActivityUnitTestCase} and
  * {@link android.test.ActivityInstrumentationTestCase}.
+ *
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public abstract class ActivityTestCase extends InstrumentationTestCase {
 
     /**
diff --git a/test-runner/src/android/test/ActivityUnitTestCase.java b/test-runner/src/android/test/ActivityUnitTestCase.java
index 40cca90..a191445 100644
--- a/test-runner/src/android/test/ActivityUnitTestCase.java
+++ b/test-runner/src/android/test/ActivityUnitTestCase.java
@@ -32,14 +32,14 @@
 
 /**
  * This class provides isolated testing of a single activity.  The activity under test will
- * be created with minimal connection to the system infrastructure, and you can inject mocked or 
+ * be created with minimal connection to the system infrastructure, and you can inject mocked or
  * wrappered versions of many of Activity's dependencies.  Most of the work is handled
  * automatically here by {@link #setUp} and {@link #tearDown}.
- * 
+ *
  * <p>If you prefer a functional test, see {@link android.test.ActivityInstrumentationTestCase}.
- * 
+ *
  * <p>It must be noted that, as a true unit test, your Activity will not be running in the
- * normal system and will not participate in the normal interactions with other Activities.  
+ * normal system and will not participate in the normal interactions with other Activities.
  * The following methods should not be called in this configuration - most of them will throw
  * exceptions:
  * <ul>
@@ -54,17 +54,17 @@
  * <li>{@link android.app.Activity#isTaskRoot()}</li>
  * <li>{@link android.app.Activity#moveTaskToBack(boolean)}</li>
  * </ul>
- * 
- * <p>The following methods may be called but will not do anything.  For test purposes, you can use 
- * the methods {@link #getStartedActivityIntent()} and {@link #getStartedActivityRequest()} to 
+ *
+ * <p>The following methods may be called but will not do anything.  For test purposes, you can use
+ * the methods {@link #getStartedActivityIntent()} and {@link #getStartedActivityRequest()} to
  * inspect the parameters that they were called with.
  * <ul>
  * <li>{@link android.app.Activity#startActivity(Intent)}</li>
  * <li>{@link android.app.Activity#startActivityForResult(Intent, int)}</li>
  * </ul>
  *
- * <p>The following methods may be called but will not do anything.  For test purposes, you can use 
- * the methods {@link #isFinishCalled()} and {@link #getFinishedActivityRequest()} to inspect the 
+ * <p>The following methods may be called but will not do anything.  For test purposes, you can use
+ * the methods {@link #isFinishCalled()} and {@link #getFinishedActivityRequest()} to inspect the
  * parameters that they were called with.
  * <ul>
  * <li>{@link android.app.Activity#finish()}</li>
@@ -72,8 +72,12 @@
  * <li>{@link android.app.Activity#finishActivity(int requestCode)}</li>
  * </ul>
  *
+ * @deprecated Write
+ * <a href="{@docRoot}training/testing/unit-testing/local-unit-tests.html">Local Unit Tests</a>
+ * instead.
  */
-public abstract class ActivityUnitTestCase<T extends Activity> 
+@Deprecated
+public abstract class ActivityUnitTestCase<T extends Activity>
         extends ActivityTestCase {
 
     private static final String TAG = "ActivityUnitTestCase";
@@ -102,31 +106,31 @@
         // default value for target context, as a default
       mActivityContext = getInstrumentation().getTargetContext();
     }
-    
+
     /**
      * Start the activity under test, in the same way as if it was started by
-     * {@link android.content.Context#startActivity Context.startActivity()}, providing the 
+     * {@link android.content.Context#startActivity Context.startActivity()}, providing the
      * arguments it supplied.  When you use this method to start the activity, it will automatically
      * be stopped by {@link #tearDown}.
-     * 
-     * <p>This method will call onCreate(), but if you wish to further exercise Activity life 
+     *
+     * <p>This method will call onCreate(), but if you wish to further exercise Activity life
      * cycle methods, you must call them yourself from your test case.
-     * 
+     *
      * <p><i>Do not call from your setUp() method.  You must call this method from each of your
      * test methods.</i>
-     *  
+     *
      * @param intent The Intent as if supplied to {@link android.content.Context#startActivity}.
      * @param savedInstanceState The instance state, if you are simulating this part of the life
      * cycle.  Typically null.
-     * @param lastNonConfigurationInstance This Object will be available to the 
-     * Activity if it calls {@link android.app.Activity#getLastNonConfigurationInstance()}.  
+     * @param lastNonConfigurationInstance This Object will be available to the
+     * Activity if it calls {@link android.app.Activity#getLastNonConfigurationInstance()}.
      * Typically null.
      * @return Returns the Activity that was created
      */
     protected T startActivity(Intent intent, Bundle savedInstanceState,
             Object lastNonConfigurationInstance) {
         assertFalse("Activity already created", mCreated);
-        
+
         if (!mAttached) {
             assertNotNull(mActivityClass);
             setActivity(null);
@@ -154,7 +158,7 @@
 
             assertNotNull(newActivity);
             setActivity(newActivity);
-            
+
             mAttached = true;
         }
 
@@ -165,22 +169,22 @@
         }
         return result;
     }
-    
+
     @Override
     protected void tearDown() throws Exception {
-        
+
         setActivity(null);
-        
-        // Scrub out members - protects against memory leaks in the case where someone 
+
+        // Scrub out members - protects against memory leaks in the case where someone
         // creates a non-static inner class (thus referencing the test case) and gives it to
         // someone else to hold onto
         scrubClass(ActivityInstrumentationTestCase.class);
 
         super.tearDown();
     }
-    
+
     /**
-     * Set the application for use during the test.  You must call this function before calling 
+     * Set the application for use during the test.  You must call this function before calling
      * {@link #startActivity}.  If your test does not call this method,
      * @param application The Application object that will be injected into the Activity under test.
      */
@@ -198,7 +202,7 @@
     }
 
     /**
-     * This method will return the value if your Activity under test calls 
+     * This method will return the value if your Activity under test calls
      * {@link android.app.Activity#setRequestedOrientation}.
      */
     public int getRequestedOrientation() {
@@ -207,10 +211,10 @@
         }
         return 0;
     }
-    
+
     /**
-     * This method will return the launch intent if your Activity under test calls 
-     * {@link android.app.Activity#startActivity(Intent)} or 
+     * This method will return the launch intent if your Activity under test calls
+     * {@link android.app.Activity#startActivity(Intent)} or
      * {@link android.app.Activity#startActivityForResult(Intent, int)}.
      * @return The Intent provided in the start call, or null if no start call was made.
      */
@@ -220,9 +224,9 @@
         }
         return null;
     }
-    
+
     /**
-     * This method will return the launch request code if your Activity under test calls 
+     * This method will return the launch request code if your Activity under test calls
      * {@link android.app.Activity#startActivityForResult(Intent, int)}.
      * @return The request code provided in the start call, or -1 if no start call was made.
      */
@@ -234,9 +238,9 @@
     }
 
     /**
-     * This method will notify you if the Activity under test called 
-     * {@link android.app.Activity#finish()}, 
-     * {@link android.app.Activity#finishFromChild(Activity)}, or 
+     * This method will notify you if the Activity under test called
+     * {@link android.app.Activity#finish()},
+     * {@link android.app.Activity#finishFromChild(Activity)}, or
      * {@link android.app.Activity#finishActivity(int)}.
      * @return Returns true if one of the listed finish methods was called.
      */
@@ -246,9 +250,9 @@
         }
         return false;
     }
-    
+
     /**
-     * This method will return the request code if the Activity under test called 
+     * This method will return the request code if the Activity under test called
      * {@link android.app.Activity#finishActivity(int)}.
      * @return The request code provided in the start call, or -1 if no finish call was made.
      */
@@ -258,7 +262,7 @@
         }
         return 0;
     }
-    
+
     /**
      * This mock Activity represents the "parent" activity.  By injecting this, we allow the user
      * to call a few more Activity methods, including:
@@ -269,7 +273,7 @@
      * <li>{@link android.app.Activity#finishActivity(int requestCode)}</li>
      * <li>{@link android.app.Activity#finishFromChild(Activity child)}</li>
      * </ul>
-     * 
+     *
      * TODO: Make this overrideable, and the unit test can look for calls to other methods
      */
     private static class MockParent extends Activity {
@@ -303,7 +307,7 @@
         public Window getWindow() {
             return null;
         }
-        
+
         /**
          * By defining this in the parent, we allow the tested activity to call
          * <ul>
@@ -316,7 +320,7 @@
             mStartedActivityIntent = intent;
             mStartedActivityRequest = requestCode;
         }
-        
+
         /**
          * By defining this in the parent, we allow the tested activity to call
          * <ul>
diff --git a/test-runner/src/android/test/AndroidTestRunner.java b/test-runner/src/android/test/AndroidTestRunner.java
index aa7c677..50eaafb 100644
--- a/test-runner/src/android/test/AndroidTestRunner.java
+++ b/test-runner/src/android/test/AndroidTestRunner.java
@@ -33,6 +33,13 @@
 import java.lang.reflect.InvocationTargetException;
 import java.util.List;
 
+/**
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
+ * AndroidJUnitRunner</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ */
+@Deprecated
 public class AndroidTestRunner extends BaseTestRunner {
 
     private TestResult mTestResult;
diff --git a/test-runner/src/android/test/ApplicationTestCase.java b/test-runner/src/android/test/ApplicationTestCase.java
index f093181..4d73f53 100644
--- a/test-runner/src/android/test/ApplicationTestCase.java
+++ b/test-runner/src/android/test/ApplicationTestCase.java
@@ -32,7 +32,7 @@
  * In order to support the lifecycle of a Application, this test case will make the
  * following calls at the following times.
  *
- * <ul><li>The test case will not call onCreate() until your test calls 
+ * <ul><li>The test case will not call onCreate() until your test calls
  * {@link #createApplication()}.  This gives you a chance
  * to set up or adjust any additional framework or test logic before
  * onCreate().</li>
@@ -40,22 +40,28 @@
  * automatically called, and it will stop & destroy your application by calling its
  * onDestroy() method.</li>
  * </ul>
- * 
+ *
  * <p><b>Dependency Injection.</b>
  * Every Application has one inherent dependency, the {@link android.content.Context Context} in
  * which it runs.
- * This framework allows you to inject a modified, mock, or isolated replacement for this 
+ * This framework allows you to inject a modified, mock, or isolated replacement for this
  * dependencies, and thus perform a true unit test.
- * 
+ *
  * <p>If simply run your tests as-is, your Application will be injected with a fully-functional
  * Context.
- * You can create and inject alternative types of Contexts by calling 
+ * You can create and inject alternative types of Contexts by calling
  * {@link AndroidTestCase#setContext(Context) setContext()}.  You must do this <i>before</i> calling
  * {@link #createApplication()}.  The test framework provides a
- * number of alternatives for Context, including {@link android.test.mock.MockContext MockContext}, 
- * {@link android.test.RenamingDelegatingContext RenamingDelegatingContext}, and 
+ * number of alternatives for Context, including {@link android.test.mock.MockContext MockContext},
+ * {@link android.test.RenamingDelegatingContext RenamingDelegatingContext}, and
  * {@link android.content.ContextWrapper ContextWrapper}.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public abstract class ApplicationTestCase<T extends Application> extends AndroidTestCase {
 
     Class<T> mApplicationClass;
@@ -78,17 +84,17 @@
     }
 
     /**
-     * This will do the work to instantiate the Application under test.  After this, your test 
+     * This will do the work to instantiate the Application under test.  After this, your test
      * code must also start and stop the Application.
      */
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        
+
         // get the real context, before the individual tests have a chance to muck with it
         mSystemContext = getContext();
     }
-    
+
     /**
      * Load and attach the application under test.
      */
@@ -101,26 +107,26 @@
         }
         mAttached = true;
     }
-    
+
     /**
-     * Start the Application under test, in the same way as if it was started by the system.  
+     * Start the Application under test, in the same way as if it was started by the system.
      * If you use this method to start the Application, it will automatically
      * be stopped by {@link #tearDown}.  If you wish to inject a specialized Context for your
-     * test, by calling {@link AndroidTestCase#setContext(Context) setContext()}, 
+     * test, by calling {@link AndroidTestCase#setContext(Context) setContext()},
      * you must do so  before calling this method.
      */
     final protected void createApplication() {
         assertFalse(mCreated);
-        
+
         if (!mAttached) {
             setupApplication();
         }
         assertNotNull(mApplication);
-        
+
         mApplication.onCreate();
         mCreated = true;
     }
-    
+
     /**
      * This will make the necessary calls to terminate the Application under test (it will
      * call onTerminate().  Ordinarily this will be called automatically (by {@link #tearDown}, but
@@ -131,13 +137,13 @@
             mApplication.onTerminate();
         }
     }
-    
+
     /**
-     * Shuts down the Application under test.  Also makes sure all resources are cleaned up and 
+     * Shuts down the Application under test.  Also makes sure all resources are cleaned up and
      * garbage collected before moving on to the next
      * test.  Subclasses that override this method should make sure they call super.tearDown()
      * at the end of the overriding method.
-     * 
+     *
      * @throws Exception
      */
     @Override
@@ -145,7 +151,7 @@
         terminateApplication();
         mApplication = null;
 
-        // Scrub out members - protects against memory leaks in the case where someone 
+        // Scrub out members - protects against memory leaks in the case where someone
         // creates a non-static inner class (thus referencing the test case) and gives it to
         // someone else to hold onto
         scrubClass(ApplicationTestCase.class);
@@ -156,7 +162,7 @@
     /**
      * Return a real (not mocked or instrumented) system Context that can be used when generating
      * Mock or other Context objects for your Application under test.
-     * 
+     *
      * @return Returns a reference to a normal Context.
      */
     public Context getSystemContext() {
@@ -165,7 +171,7 @@
 
     /**
      * This test simply confirms that the Application class can be instantiated properly.
-     * 
+     *
      * @throws Exception
      */
     final public void testApplicationTestCaseSetUpProperly() throws Exception {
diff --git a/test-runner/src/android/test/AssertionFailedError.java b/test-runner/src/android/test/AssertionFailedError.java
index b3ac6d1..fc3e98e 100644
--- a/test-runner/src/android/test/AssertionFailedError.java
+++ b/test-runner/src/android/test/AssertionFailedError.java
@@ -18,17 +18,18 @@
 
 /**
  * Thrown when an assertion failed.
- * 
+ *
  * @deprecated use junit.framework.AssertionFailedError
  */
+@Deprecated
 public class AssertionFailedError extends Error {
-    
+
     /**
      * It is more typical to call {@link #AssertionFailedError(String)}.
      */
     public AssertionFailedError() {
     }
-    
+
     public AssertionFailedError(String errorMessage) {
         super(errorMessage);
     }
diff --git a/test-runner/src/android/test/ClassPathPackageInfo.java b/test-runner/src/android/test/ClassPathPackageInfo.java
index 1f6e647..1ab7c7f 100644
--- a/test-runner/src/android/test/ClassPathPackageInfo.java
+++ b/test-runner/src/android/test/ClassPathPackageInfo.java
@@ -24,9 +24,10 @@
 /**
  * The Package object doesn't allow you to iterate over the contained
  * classes and subpackages of that package.  This is a version that does.
- * 
+ *
  * {@hide} Not needed for 1.0 SDK.
  */
+@Deprecated
 public class ClassPathPackageInfo {
 
     private final ClassPathPackageInfoSource source;
diff --git a/test-runner/src/android/test/ClassPathPackageInfoSource.java b/test-runner/src/android/test/ClassPathPackageInfoSource.java
index 0ffecdb..89bb494 100644
--- a/test-runner/src/android/test/ClassPathPackageInfoSource.java
+++ b/test-runner/src/android/test/ClassPathPackageInfoSource.java
@@ -33,9 +33,10 @@
 
 /**
  * Generate {@link ClassPathPackageInfo}s by scanning apk paths.
- * 
+ *
  * {@hide} Not needed for 1.0 SDK.
  */
+@Deprecated
 public class ClassPathPackageInfoSource {
 
     private static final String CLASS_EXTENSION = ".class";
@@ -82,7 +83,7 @@
                 // Don't try to load classes that are generated. They usually aren't in test apks.
                 continue;
             }
-            
+
             try {
                 // We get errors in the emulator if we don't use the caller's class loader.
                 topLevelClasses.add(Class.forName(className, false,
diff --git a/test-runner/src/android/test/DatabaseTestUtils.java b/test-runner/src/android/test/DatabaseTestUtils.java
index 23e0aba..42ef48b 100644
--- a/test-runner/src/android/test/DatabaseTestUtils.java
+++ b/test-runner/src/android/test/DatabaseTestUtils.java
@@ -27,6 +27,7 @@
  * A collection of utilities for writing unit tests for database code.
  * @hide pending API council approval
  */
+@Deprecated
 public class DatabaseTestUtils {
 
     /**
diff --git a/test-runner/src/android/test/InstrumentationCoreTestRunner.java b/test-runner/src/android/test/InstrumentationCoreTestRunner.java
index 655a65c..2b05e4a 100644
--- a/test-runner/src/android/test/InstrumentationCoreTestRunner.java
+++ b/test-runner/src/android/test/InstrumentationCoreTestRunner.java
@@ -41,6 +41,7 @@
  *
  * @hide
  */
+@Deprecated
 public class InstrumentationCoreTestRunner extends InstrumentationTestRunner {
 
     /**
diff --git a/test-runner/src/android/test/InstrumentationTestRunner.java b/test-runner/src/android/test/InstrumentationTestRunner.java
index db80ef951..9bd4c96 100644
--- a/test-runner/src/android/test/InstrumentationTestRunner.java
+++ b/test-runner/src/android/test/InstrumentationTestRunner.java
@@ -155,6 +155,10 @@
  * -e coverageFile /sdcard/myFile.ec
  * <br/>
  * in addition to the other arguments.
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">
+ * AndroidJUnitRunner</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
 
 /* (not JavaDoc)
@@ -170,6 +174,7 @@
  *
  * This model is used by many existing app tests, but can probably be deprecated.
  */
+@Deprecated
 public class InstrumentationTestRunner extends Instrumentation implements TestSuiteProvider {
 
     /** @hide */
diff --git a/test-runner/src/android/test/InstrumentationUtils.java b/test-runner/src/android/test/InstrumentationUtils.java
index 1a7002a..cc50813 100644
--- a/test-runner/src/android/test/InstrumentationUtils.java
+++ b/test-runner/src/android/test/InstrumentationUtils.java
@@ -17,17 +17,17 @@
 package android.test;
 
 /**
- * 
  * The InstrumentationUtils class has all the utility functions needed for
  * instrumentation tests.
  *
  * {@hide} - Not currently used.
  */
+@Deprecated
 public class InstrumentationUtils {
     /**
      * An utility function that returns the menu identifier for a particular
      * menu item.
-     * 
+     *
      * @param cls Class object of the class that handles the menu ite,.
      * @param identifier Menu identifier.
      * @return The integer corresponding to the menu item.
@@ -35,7 +35,7 @@
     public static int getMenuIdentifier(Class cls, String identifier) {
         int id = -1;
         try {
-            Integer field = (Integer)cls.getDeclaredField(identifier).get(cls);   
+            Integer field = (Integer)cls.getDeclaredField(identifier).get(cls);
             id = field.intValue();
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index f971b5d..3abf38f 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -43,9 +43,13 @@
 
 
 /**
-     * A mock context which prevents its users from talking to the rest of the device while
+ * A mock context which prevents its users from talking to the rest of the device while
  * stubbing enough methods to satify code that tries to talk to other packages.
+ *
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class IsolatedContext extends ContextWrapper {
 
     private ContentResolver mResolver;
diff --git a/test-runner/src/android/test/LaunchPerformanceBase.java b/test-runner/src/android/test/LaunchPerformanceBase.java
index d423e62..62c90d6 100644
--- a/test-runner/src/android/test/LaunchPerformanceBase.java
+++ b/test-runner/src/android/test/LaunchPerformanceBase.java
@@ -26,6 +26,7 @@
  *
  * @hide
  */
+@Deprecated
 public class LaunchPerformanceBase extends Instrumentation {
 
     public static final String LOG_TAG = "Launch Performance";
@@ -39,7 +40,7 @@
         mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         setAutomaticPerformanceSnapshots();
     }
-   
+
     /**
      * Launches intent, and waits for idle before returning.
      *
diff --git a/test-runner/src/android/test/MoreAsserts.java b/test-runner/src/android/test/MoreAsserts.java
index 3364895..d33911a 100644
--- a/test-runner/src/android/test/MoreAsserts.java
+++ b/test-runner/src/android/test/MoreAsserts.java
@@ -30,7 +30,10 @@
 
 /**
  * Contains additional assertion methods not found in JUnit.
+ * @deprecated Use
+ * <a href="https://github.com/hamcrest">Hamcrest matchers</a> instead.
  */
+@Deprecated
 public final class MoreAsserts {
 
     private MoreAsserts() { }
@@ -375,7 +378,7 @@
                 failWithMessage(message, "Extra object in actual: (" + actualObj.toString() + ")");
             }
         }
-        
+
         if (expectedMap.size() > 0) {
             failWithMessage(message, "Extra objects in expected.");
         }
diff --git a/test-runner/src/android/test/NoExecTestResult.java b/test-runner/src/android/test/NoExecTestResult.java
index 1ee62c1..a01b6aa 100644
--- a/test-runner/src/android/test/NoExecTestResult.java
+++ b/test-runner/src/android/test/NoExecTestResult.java
@@ -19,11 +19,12 @@
 import junit.framework.TestResult;
 
 /**
- * A benign test result that does no actually test execution, just runs 
+ * A benign test result that does no actually test execution, just runs
  * through the motions
- * 
+ *
  * {@hide} Not needed for SDK.
  */
+@Deprecated
 class NoExecTestResult extends TestResult {
 
     /**
diff --git a/test-runner/src/android/test/PackageInfoSources.java b/test-runner/src/android/test/PackageInfoSources.java
index ef37449..205f86b 100644
--- a/test-runner/src/android/test/PackageInfoSources.java
+++ b/test-runner/src/android/test/PackageInfoSources.java
@@ -19,6 +19,7 @@
 /**
  * {@hide} Not needed for SDK.
  */
+@Deprecated
 public class PackageInfoSources {
 
     private static ClassPathPackageInfoSource classPathSource;
diff --git a/test-runner/src/android/test/PerformanceCollectorTestCase.java b/test-runner/src/android/test/PerformanceCollectorTestCase.java
index 4309ff7..3a5dafc 100644
--- a/test-runner/src/android/test/PerformanceCollectorTestCase.java
+++ b/test-runner/src/android/test/PerformanceCollectorTestCase.java
@@ -30,6 +30,7 @@
  *
  * {@hide} Not needed for SDK.
  */
+@Deprecated
 public interface PerformanceCollectorTestCase {
     public PerformanceCollector mPerfCollector = new PerformanceCollector();
 
diff --git a/test-runner/src/android/test/RenamingDelegatingContext.java b/test-runner/src/android/test/RenamingDelegatingContext.java
index 3c4da9e..36786b0 100644
--- a/test-runner/src/android/test/RenamingDelegatingContext.java
+++ b/test-runner/src/android/test/RenamingDelegatingContext.java
@@ -36,7 +36,11 @@
  * This is a class which delegates to the given context, but performs database
  * and file operations with a renamed database/file name (prefixes default
  * names with a given prefix).
+ *
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class RenamingDelegatingContext extends ContextWrapper {
 
     private Context mFileContext;
@@ -168,7 +172,7 @@
             return false;
         }
     }
-    
+
     @Override
     public File getDatabasePath(String name) {
         return mFileContext.getDatabasePath(renamedFileName(name));
@@ -216,7 +220,7 @@
     public String[] fileList() {
         return mFileNames.toArray(new String[]{});
     }
-    
+
     /**
      * In order to support calls to getCacheDir(), we create a temp cache dir (inside the real
      * one) and return it instead.  This code is basically getCacheDir(), except it uses the real
@@ -241,21 +245,4 @@
         }
         return mCacheDir;
     }
-
-
-//    /**
-//     * Given an array of files returns only those whose names indicate that they belong to this
-//     * context.
-//     * @param allFiles the original list of files
-//     * @return the pruned list of files
-//     */
-//    private String[] prunedFileList(String[] allFiles) {
-//        List<String> files = Lists.newArrayList();
-//        for (String file : allFiles) {
-//            if (file.startsWith(mFilePrefix)) {
-//                files.add(file);
-//            }
-//        }
-//        return files.toArray(new String[]{});
-//    }
 }
diff --git a/test-runner/src/android/test/ServiceTestCase.java b/test-runner/src/android/test/ServiceTestCase.java
index ba20c09..c8ff0f9 100644
--- a/test-runner/src/android/test/ServiceTestCase.java
+++ b/test-runner/src/android/test/ServiceTestCase.java
@@ -92,7 +92,13 @@
  *      {@link android.test.RenamingDelegatingContext RenamingDelegatingContext},
  *      {@link android.content.ContextWrapper ContextWrapper}, and
  *      {@link android.test.IsolatedContext}.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/rule/ServiceTestRule.html">
+ * ServiceTestRule</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public abstract class ServiceTestCase<T extends Service> extends AndroidTestCase {
 
     Class<T> mServiceClass;
diff --git a/test-runner/src/android/test/SimpleCache.java b/test-runner/src/android/test/SimpleCache.java
index 44424ec..46143e4 100644
--- a/test-runner/src/android/test/SimpleCache.java
+++ b/test-runner/src/android/test/SimpleCache.java
@@ -19,6 +19,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+@Deprecated
 abstract class SimpleCache<K, V> {
     private Map<K, V> map = new HashMap<K, V>();
 
diff --git a/test-runner/src/android/test/SingleLaunchActivityTestCase.java b/test-runner/src/android/test/SingleLaunchActivityTestCase.java
index 72c93ce..af1448e 100644
--- a/test-runner/src/android/test/SingleLaunchActivityTestCase.java
+++ b/test-runner/src/android/test/SingleLaunchActivityTestCase.java
@@ -22,13 +22,19 @@
  * If you would like to test a single activity with an
  * {@link android.test.InstrumentationTestCase}, this provides some of the boiler plate to
  * launch and finish the activity in {@link #setUp} and {@link #tearDown}.
- * 
- * This launches the activity only once for the entire class instead of doing it 
+ *
+ * This launches the activity only once for the entire class instead of doing it
  * in every setup / teardown call.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/rule/ActivityTestRule.html">
+ * ActivityTestRule</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public abstract class SingleLaunchActivityTestCase<T extends Activity>
         extends InstrumentationTestCase {
-    
+
     String mPackage;
     Class<T> mActivityClass;
     private static int sTestCaseCounter = 0;
@@ -44,10 +50,10 @@
      */
     public SingleLaunchActivityTestCase(String pkg, Class<T> activityClass) {
         mPackage = pkg;
-        mActivityClass = activityClass;        
-        sTestCaseCounter ++;                
+        mActivityClass = activityClass;
+        sTestCaseCounter ++;
     }
-    
+
     /**
      * The activity that will be set up for use in each test method.
      */
@@ -66,7 +72,7 @@
             getInstrumentation().setInTouchMode(false);
             sActivity = launchActivity(mPackage, mActivityClass, null);
             sActivityLaunchedFlag = true;
-        }                        
+        }
     }
 
     @Override
@@ -75,7 +81,7 @@
         sTestCaseCounter --;
         if (sTestCaseCounter == 0) {
             sActivity.finish();
-        }        
+        }
         super.tearDown();
     }
 
diff --git a/test-runner/src/android/test/SyncBaseInstrumentation.java b/test-runner/src/android/test/SyncBaseInstrumentation.java
index 7d418f0..de36b4f 100644
--- a/test-runner/src/android/test/SyncBaseInstrumentation.java
+++ b/test-runner/src/android/test/SyncBaseInstrumentation.java
@@ -27,7 +27,13 @@
  * If you would like to test sync a single provider with an
  * {@link InstrumentationTestCase}, this provides some of the boiler plate in {@link #setUp} and
  * {@link #tearDown}.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
+ * InstrumentationRegistry</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class SyncBaseInstrumentation extends InstrumentationTestCase {
     private Context mTargetContext;
     ContentResolver mContentResolver;
diff --git a/test-runner/src/android/test/TestCase.java b/test-runner/src/android/test/TestCase.java
index 5432ce8..b234f44 100644
--- a/test-runner/src/android/test/TestCase.java
+++ b/test-runner/src/android/test/TestCase.java
@@ -23,14 +23,13 @@
  * More complex interface for test cases.
  *
  * <p>Just implementing Runnable is enough for many test cases.  If you
- * have additional setup or teardown, this interface might be for you, 
+ * have additional setup or teardown, this interface might be for you,
  * especially if you need to share it between different test cases, or your
  * teardown code must execute regardless of whether your test passed.
  *
  * <p>See the android.test package documentation (click the more... link)
  * for a full description
  */
-
 @Deprecated
 public interface TestCase extends Runnable
 {
diff --git a/test-runner/src/android/test/TestCaseUtil.java b/test-runner/src/android/test/TestCaseUtil.java
index 3ba9711..c46d403 100644
--- a/test-runner/src/android/test/TestCaseUtil.java
+++ b/test-runner/src/android/test/TestCaseUtil.java
@@ -35,6 +35,7 @@
  * @hide - This is part of a framework that is under development and should not be used for
  * active development.
  */
+@Deprecated
 public class TestCaseUtil {
 
     private TestCaseUtil() {
@@ -67,7 +68,7 @@
              */
             if (test instanceof TestCase &&
                     ((TestCase)test).getName() == null) {
-                workingTest = invokeSuiteMethodIfPossible(test.getClass(), 
+                workingTest = invokeSuiteMethodIfPossible(test.getClass(),
                         seen);
             }
             if (workingTest == null) {
@@ -155,7 +156,7 @@
     public static TestSuite createTestSuite(Class<? extends Test> testClass)
             throws InstantiationException, IllegalAccessException {
 
-        Test test = invokeSuiteMethodIfPossible(testClass, 
+        Test test = invokeSuiteMethodIfPossible(testClass,
                 new HashSet<Class<?>>());
         if (test == null) {
             return new TestSuite(testClass);
diff --git a/test-runner/src/android/test/TestPrinter.java b/test-runner/src/android/test/TestPrinter.java
index 37bd721..a23f06d 100644
--- a/test-runner/src/android/test/TestPrinter.java
+++ b/test-runner/src/android/test/TestPrinter.java
@@ -30,9 +30,10 @@
  * probably will not need to create or extend this class or call its methods manually.
  * See the full {@link android.test} package description for information about
  * getting test results.
- * 
+ *
  * {@hide} Not needed for 1.0 SDK.
  */
+@Deprecated
 public class TestPrinter implements TestRunner.Listener, TestListener {
 
     private String mTag;
@@ -89,7 +90,7 @@
         mFailedTests.add(test.toString());
         failed(test.toString(), t);
     }
-    
+
     public void addError(Test test, Throwable t) {
         failed(test, t);
     }
diff --git a/test-runner/src/android/test/TestRunner.java b/test-runner/src/android/test/TestRunner.java
index 012df35..beecc6f 100644
--- a/test-runner/src/android/test/TestRunner.java
+++ b/test-runner/src/android/test/TestRunner.java
@@ -42,6 +42,7 @@
  *
  * {@hide} Not needed for 1.0 SDK.
  */
+@Deprecated
 public class TestRunner implements PerformanceTestCase.Intermediates {
     public static final int REGRESSION = 0;
     public static final int PERFORMANCE = 1;
diff --git a/test-runner/src/android/test/TestSuiteProvider.java b/test-runner/src/android/test/TestSuiteProvider.java
index dc9ce6e..c74651c 100644
--- a/test-runner/src/android/test/TestSuiteProvider.java
+++ b/test-runner/src/android/test/TestSuiteProvider.java
@@ -21,6 +21,7 @@
 /**
  * Implementors will know how to get a test suite.
  */
+@Deprecated
 public interface TestSuiteProvider {
 
     TestSuite getTestSuite();
diff --git a/test-runner/src/android/test/TimedTest.java b/test-runner/src/android/test/TimedTest.java
index 95cc9bf..cb15ef9 100644
--- a/test-runner/src/android/test/TimedTest.java
+++ b/test-runner/src/android/test/TimedTest.java
@@ -30,6 +30,7 @@
  *
  * {@hide} Pending approval for public API.
  */
+@Deprecated
 @Retention(RetentionPolicy.RUNTIME)
 public @interface TimedTest {
     boolean includeDetailedStats() default false;
diff --git a/test-runner/src/android/test/TouchUtils.java b/test-runner/src/android/test/TouchUtils.java
index 1b854b0..28dc7b2 100644
--- a/test-runner/src/android/test/TouchUtils.java
+++ b/test-runner/src/android/test/TouchUtils.java
@@ -31,9 +31,15 @@
  * Reusable methods for generating touch events. These methods can be used with
  * InstrumentationTestCase or ActivityInstrumentationTestCase2 to simulate user interaction with
  * the application through a touch screen.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso UI testing
+ * framework</a> instead. New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class TouchUtils {
-    
+
     /**
      * Simulate touching in the center of the screen and dragging one quarter of the way down
      * @param test The test case that is being run
@@ -46,7 +52,7 @@
     public static void dragQuarterScreenDown(ActivityInstrumentationTestCase test) {
         dragQuarterScreenDown(test, test.getActivity());
     }
-    
+
     /**
      * Simulate touching in the center of the screen and dragging one quarter of the way down
      * @param test The test case that is being run
@@ -56,14 +62,14 @@
         Display display = activity.getWindowManager().getDefaultDisplay();
         final Point size = new Point();
         display.getSize(size);
-        
+
         final float x = size.x / 2.0f;
         final float fromY = size.y * 0.5f;
         final float toY = size.y * 0.75f;
-      
+
         drag(test, x, x, fromY, toY, 4);
     }
-    
+
     /**
      * Simulate touching in the center of the screen and dragging one quarter of the way up
      * @param test The test case that is being run
@@ -76,7 +82,7 @@
     public static void dragQuarterScreenUp(ActivityInstrumentationTestCase test) {
         dragQuarterScreenUp(test, test.getActivity());
     }
-    
+
     /**
      * Simulate touching in the center of the screen and dragging one quarter of the way up
      * @param test The test case that is being run
@@ -86,18 +92,18 @@
         Display display = activity.getWindowManager().getDefaultDisplay();
         final Point size = new Point();
         display.getSize(size);
-        
+
         final float x = size.x / 2.0f;
         final float fromY = size.y * 0.5f;
         final float toY = size.y * 0.25f;
-      
+
         drag(test, x, x, fromY, toY, 4);
     }
-    
+
     /**
      * Scroll a ViewGroup to the bottom by repeatedly calling
      * {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)}
-     * 
+     *
      * @param test The test case that is being run
      * @param v The ViewGroup that should be dragged
      *
@@ -109,11 +115,11 @@
     public static void scrollToBottom(ActivityInstrumentationTestCase test, ViewGroup v) {
         scrollToBottom(test, test.getActivity(), v);
     }
-    
+
     /**
      * Scroll a ViewGroup to the bottom by repeatedly calling
      * {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)}
-     * 
+     *
      * @param test The test case that is being run
      * @param activity The activity that is in the foreground of the test case
      * @param v The ViewGroup that should be dragged
@@ -132,7 +138,7 @@
     /**
      * Scroll a ViewGroup to the top by repeatedly calling
      * {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)}
-     * 
+     *
      * @param test The test case that is being run
      * @param v The ViewGroup that should be dragged
      *
@@ -144,11 +150,11 @@
     public static void scrollToTop(ActivityInstrumentationTestCase test, ViewGroup v) {
         scrollToTop(test, test.getActivity(), v);
     }
-    
+
     /**
      * Scroll a ViewGroup to the top by repeatedly calling
      * {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)}
-     * 
+     *
      * @param test The test case that is being run
      * @param activity The activity that is in the foreground of the test case
      * @param v The ViewGroup that should be dragged
@@ -162,10 +168,10 @@
             next = new ViewStateSnapshot(v);
         } while (!prev.equals(next));
     }
-    
+
     /**
      * Simulate touching the center of a view and dragging to the bottom of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      *
@@ -177,10 +183,10 @@
     public static void dragViewToBottom(ActivityInstrumentationTestCase test, View v) {
         dragViewToBottom(test, test.getActivity(), v, 4);
     }
-    
+
     /**
      * Simulate touching the center of a view and dragging to the bottom of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param activity The activity that is in the foreground of the test case
      * @param v The view that should be dragged
@@ -188,10 +194,10 @@
     public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v) {
         dragViewToBottom(test, activity, v, 4);
     }
-    
+
     /**
      * Simulate touching the center of a view and dragging to the bottom of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param stepCount How many move steps to include in the drag
@@ -205,10 +211,10 @@
             int stepCount) {
         dragViewToBottom(test, test.getActivity(), v, stepCount);
     }
-    
+
     /**
      * Simulate touching the center of a view and dragging to the bottom of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param activity The activity that is in the foreground of the test case
      * @param v The view that should be dragged
@@ -220,38 +226,38 @@
 
         int[] xy = new int[2];
         v.getLocationOnScreen(xy);
-        
+
         final int viewWidth = v.getWidth();
         final int viewHeight = v.getHeight();
-        
+
         final float x = xy[0] + (viewWidth / 2.0f);
         float fromY = xy[1] + (viewHeight / 2.0f);
         float toY = screenHeight - 1;
-        
+
         drag(test, x, x, fromY, toY, stepCount);
     }
 
     /**
      * Simulate touching the center of a view and releasing quickly (before the tap timeout).
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be clicked
      */
     public static void tapView(InstrumentationTestCase test, View v) {
         int[] xy = new int[2];
         v.getLocationOnScreen(xy);
-        
+
         final int viewWidth = v.getWidth();
         final int viewHeight = v.getHeight();
-        
+
         final float x = xy[0] + (viewWidth / 2.0f);
         float y = xy[1] + (viewHeight / 2.0f);
-        
+
         Instrumentation inst = test.getInstrumentation();
 
         long downTime = SystemClock.uptimeMillis();
         long eventTime = SystemClock.uptimeMillis();
-        
+
         MotionEvent event = MotionEvent.obtain(downTime, eventTime,
                 MotionEvent.ACTION_DOWN, x, y, 0);
         inst.sendPointerSync(event);
@@ -308,30 +314,30 @@
 
     /**
      * Simulate touching the center of a view and releasing.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be clicked
      */
     public static void clickView(InstrumentationTestCase test, View v) {
         int[] xy = new int[2];
         v.getLocationOnScreen(xy);
-        
+
         final int viewWidth = v.getWidth();
         final int viewHeight = v.getHeight();
-        
+
         final float x = xy[0] + (viewWidth / 2.0f);
         float y = xy[1] + (viewHeight / 2.0f);
-        
+
         Instrumentation inst = test.getInstrumentation();
 
         long downTime = SystemClock.uptimeMillis();
         long eventTime = SystemClock.uptimeMillis();
-        
+
         MotionEvent event = MotionEvent.obtain(downTime, eventTime,
                 MotionEvent.ACTION_DOWN, x, y, 0);
         inst.sendPointerSync(event);
         inst.waitForIdleSync();
-        
+
 
         eventTime = SystemClock.uptimeMillis();
         final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
@@ -344,7 +350,7 @@
         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
         inst.sendPointerSync(event);
         inst.waitForIdleSync();
-        
+
         try {
             Thread.sleep(1000);
         } catch (InterruptedException e) {
@@ -354,7 +360,7 @@
 
     /**
      * Simulate touching the center of a view, holding until it is a long press, and then releasing.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be clicked
      *
@@ -369,20 +375,20 @@
 
     /**
      * Simulate touching the center of a view, holding until it is a long press, and then releasing.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be clicked
      */
     public static void longClickView(InstrumentationTestCase test, View v) {
         int[] xy = new int[2];
         v.getLocationOnScreen(xy);
-        
+
         final int viewWidth = v.getWidth();
         final int viewHeight = v.getHeight();
-        
+
         final float x = xy[0] + (viewWidth / 2.0f);
         float y = xy[1] + (viewHeight / 2.0f);
-        
+
         Instrumentation inst = test.getInstrumentation();
 
         long downTime = SystemClock.uptimeMillis();
@@ -399,7 +405,7 @@
                 x + touchSlop / 2, y + touchSlop / 2, 0);
         inst.sendPointerSync(event);
         inst.waitForIdleSync();
-        
+
         try {
             Thread.sleep((long)(ViewConfiguration.getLongPressTimeout() * 1.5f));
         } catch (InterruptedException e) {
@@ -414,7 +420,7 @@
 
     /**
      * Simulate touching the center of a view and dragging to the top of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      *
@@ -426,10 +432,10 @@
     public static void dragViewToTop(ActivityInstrumentationTestCase test, View v) {
         dragViewToTop((InstrumentationTestCase) test, v, 4);
     }
-    
+
     /**
      * Simulate touching the center of a view and dragging to the top of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param stepCount How many move steps to include in the drag
@@ -442,20 +448,20 @@
     public static void dragViewToTop(ActivityInstrumentationTestCase test, View v, int stepCount) {
         dragViewToTop((InstrumentationTestCase) test, v, stepCount);
     }
-    
+
     /**
      * Simulate touching the center of a view and dragging to the top of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      */
     public static void dragViewToTop(InstrumentationTestCase test, View v) {
         dragViewToTop(test, v, 4);
     }
-    
+
     /**
      * Simulate touching the center of a view and dragging to the top of the screen.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param stepCount How many move steps to include in the drag
@@ -463,21 +469,21 @@
     public static void dragViewToTop(InstrumentationTestCase test, View v, int stepCount) {
         int[] xy = new int[2];
         v.getLocationOnScreen(xy);
-        
+
         final int viewWidth = v.getWidth();
         final int viewHeight = v.getHeight();
-        
+
         final float x = xy[0] + (viewWidth / 2.0f);
         float fromY = xy[1] + (viewHeight / 2.0f);
         float toY = 0;
-        
+
         drag(test, x, x, fromY, toY, stepCount);
     }
-    
+
     /**
      * Get the location of a view. Use the gravity param to specify which part of the view to
      * return.
-     * 
+     *
      * @param v View to find
      * @param gravity A combination of (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL,
      *        RIGHT)
@@ -488,7 +494,7 @@
 
         final int viewWidth = v.getWidth();
         final int viewHeight = v.getHeight();
-        
+
         switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
         case Gravity.TOP:
             break;
@@ -501,7 +507,7 @@
         default:
             // Same as top -- do nothing
         }
-        
+
         switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
         case Gravity.LEFT:
             break;
@@ -518,14 +524,14 @@
 
     /**
      * Simulate touching a view and dragging it by the specified amount.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param deltaX Amount to drag horizontally in pixels
      * @param deltaY Amount to drag vertically in pixels
-     * 
+     *
      * @return distance in pixels covered by the drag
      *
      * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
@@ -537,17 +543,17 @@
             int deltaX, int deltaY) {
         return dragViewBy((InstrumentationTestCase) test, v, gravity, deltaX, deltaY);
     }
-    
+
     /**
      * Simulate touching a view and dragging it by the specified amount.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param deltaX Amount to drag horizontally in pixels
      * @param deltaY Amount to drag vertically in pixels
-     * 
+     *
      * @return distance in pixels covered by the drag
      *
      * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
@@ -558,29 +564,29 @@
     public static int dragViewBy(InstrumentationTestCase test, View v, int gravity, int deltaX,
             int deltaY) {
         int[] xy = new int[2];
-        
+
         getStartLocation(v, gravity, xy);
 
         final int fromX = xy[0];
         final int fromY = xy[1];
-        
+
         int distance = (int) Math.hypot(deltaX, deltaY);
 
         drag(test, fromX, fromX + deltaX, fromY, fromY + deltaY, distance);
 
         return distance;
     }
-    
+
     /**
      * Simulate touching a view and dragging it to a specified location.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param toX Final location of the view after dragging
      * @param toY Final location of the view after dragging
-     * 
+     *
      * @return distance in pixels covered by the drag
      *
      * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
@@ -595,14 +601,14 @@
 
     /**
      * Simulate touching a view and dragging it to a specified location.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param toX Final location of the view after dragging
      * @param toY Final location of the view after dragging
-     * 
+     *
      * @return distance in pixels covered by the drag
      */
     public static int dragViewTo(InstrumentationTestCase test, View v, int gravity, int toX,
@@ -610,28 +616,28 @@
         int[] xy = new int[2];
 
         getStartLocation(v, gravity, xy);
-        
+
         final int fromX = xy[0];
         final int fromY = xy[1];
-        
+
         int deltaX = fromX - toX;
         int deltaY = fromY - toY;
-        
+
         int distance = (int)Math.hypot(deltaX, deltaY);
         drag(test, fromX, toX, fromY, toY, distance);
-        
+
         return distance;
     }
 
     /**
      * Simulate touching a view and dragging it to a specified location. Only moves horizontally.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param toX Final location of the view after dragging
-     * 
+     *
      * @return distance in pixels covered by the drag
      *
      * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
@@ -646,39 +652,39 @@
 
     /**
      * Simulate touching a view and dragging it to a specified location. Only moves horizontally.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param toX Final location of the view after dragging
-     * 
+     *
      * @return distance in pixels covered by the drag
      */
     public static int dragViewToX(InstrumentationTestCase test, View v, int gravity, int toX) {
         int[] xy = new int[2];
 
         getStartLocation(v, gravity, xy);
-        
+
         final int fromX = xy[0];
         final int fromY = xy[1];
-        
+
         int deltaX = fromX - toX;
 
         drag(test, fromX, toX, fromY, fromY, deltaX);
-        
+
         return deltaX;
     }
-    
+
     /**
      * Simulate touching a view and dragging it to a specified location. Only moves vertically.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param toY Final location of the view after dragging
-     * 
+     *
      * @return distance in pixels covered by the drag
      *
      * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
@@ -690,37 +696,37 @@
             int toY) {
         return dragViewToY((InstrumentationTestCase) test, v, gravity, toY);
     }
-    
+
     /**
      * Simulate touching a view and dragging it to a specified location. Only moves vertically.
-     * 
+     *
      * @param test The test case that is being run
      * @param v The view that should be dragged
      * @param gravity Which part of the view to use for the initial down event. A combination of
      *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
      * @param toY Final location of the view after dragging
-     * 
+     *
      * @return distance in pixels covered by the drag
      */
     public static int dragViewToY(InstrumentationTestCase test, View v, int gravity, int toY) {
         int[] xy = new int[2];
 
         getStartLocation(v, gravity, xy);
-       
+
         final int fromX = xy[0];
         final int fromY = xy[1];
-        
+
         int deltaY = fromY - toY;
 
         drag(test, fromX, fromX, fromY, toY, deltaY);
-        
+
         return deltaY;
     }
-    
+
 
     /**
      * Simulate touching a specific location and dragging to a new location.
-     * 
+     *
      * @param test The test case that is being run
      * @param fromX X coordinate of the initial touch, in screen coordinates
      * @param toX Xcoordinate of the drag destination, in screen coordinates
@@ -737,10 +743,10 @@
             float fromY, float toY, int stepCount) {
         drag((InstrumentationTestCase) test, fromX, toX, fromY, toY, stepCount);
     }
-    
+
     /**
      * Simulate touching a specific location and dragging to a new location.
-     * 
+     *
      * @param test The test case that is being run
      * @param fromX X coordinate of the initial touch, in screen coordinates
      * @param toX Xcoordinate of the drag destination, in screen coordinates
@@ -757,7 +763,7 @@
 
         float y = fromY;
         float x = fromX;
-        
+
         float yStep = (toY - fromY) / stepCount;
         float xStep = (toX - fromX) / stepCount;
 
diff --git a/test-runner/src/android/test/ViewAsserts.java b/test-runner/src/android/test/ViewAsserts.java
index c575fc5..00ab443 100644
--- a/test-runner/src/android/test/ViewAsserts.java
+++ b/test-runner/src/android/test/ViewAsserts.java
@@ -23,7 +23,15 @@
 
 /**
  * Some useful assertions about views.
+ *
+ * @deprecated Use
+ * <a href="{@docRoot}reference/android/support/test/espresso/matcher/ViewMatchers.html">Espresso
+ * View Matchers</a> instead. New test should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
+ * For more information about UI testing, take the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Espresso UI testing</a> training.
  */
+@Deprecated
 public class ViewAsserts {
 
     private ViewAsserts() {}
diff --git a/test-runner/src/android/test/mock/MockApplication.java b/test-runner/src/android/test/mock/MockApplication.java
index 572dfbf..3257ecf 100644
--- a/test-runner/src/android/test/mock/MockApplication.java
+++ b/test-runner/src/android/test/mock/MockApplication.java
@@ -20,12 +20,17 @@
 import android.content.res.Configuration;
 
 /**
- * A mock {@link android.app.Application} class.  All methods are non-functional and throw 
- * {@link java.lang.UnsupportedOperationException}.  Override it as necessary to provide the 
+ * A mock {@link android.app.Application} class.  All methods are non-functional and throw
+ * {@link java.lang.UnsupportedOperationException}.  Override it as necessary to provide the
  * operations that you need.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class MockApplication extends Application {
-    
+
     public MockApplication() {
     }
 
@@ -38,7 +43,7 @@
     public void onTerminate() {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         throw new UnsupportedOperationException();
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-runner/src/android/test/mock/MockContentProvider.java
index 5ef71df..3743fb0 100644
--- a/test-runner/src/android/test/mock/MockContentProvider.java
+++ b/test-runner/src/android/test/mock/MockContentProvider.java
@@ -41,7 +41,12 @@
  * Mock implementation of ContentProvider.  All methods are non-functional and throw
  * {@link java.lang.UnsupportedOperationException}.  Tests can extend this class to
  * implement behavior needed for tests.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class MockContentProvider extends ContentProvider {
     /*
      * Note: if you add methods to ContentProvider, you must add similar methods to
diff --git a/test-runner/src/android/test/mock/MockContentResolver.java b/test-runner/src/android/test/mock/MockContentResolver.java
index aec6c77..75c8335 100644
--- a/test-runner/src/android/test/mock/MockContentResolver.java
+++ b/test-runner/src/android/test/mock/MockContentResolver.java
@@ -49,8 +49,12 @@
  * <p>For more information about application testing, read the
  * <a href="{@docRoot}guide/topics/testing/index.html">Testing</a> developer guide.</p>
  * </div>
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
-
+@Deprecated
 public class MockContentResolver extends ContentResolver {
     Map<String, ContentProvider> mProviders;
 
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 64d2978..9b93bda 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -52,10 +52,15 @@
 import java.io.InputStream;
 
 /**
- * A mock {@link android.content.Context} class.  All methods are non-functional and throw 
+ * A mock {@link android.content.Context} class.  All methods are non-functional and throw
  * {@link java.lang.UnsupportedOperationException}.  You can use this to inject other dependencies,
  * mocks, or monitors into the classes you are testing.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class MockContext extends Context {
 
     @Override
@@ -82,12 +87,12 @@
     public Looper getMainLooper() {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public Context getApplicationContext() {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public void setTheme(int resid) {
         throw new UnsupportedOperationException();
@@ -124,7 +129,7 @@
     public ApplicationInfo getApplicationInfo() {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public String getPackageResourcePath() {
         throw new UnsupportedOperationException();
@@ -194,7 +199,7 @@
     public File getObbDir() {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public File getCacheDir() {
         throw new UnsupportedOperationException();
@@ -216,7 +221,7 @@
     }
 
     @Override
-    public SQLiteDatabase openOrCreateDatabase(String file, int mode, 
+    public SQLiteDatabase openOrCreateDatabase(String file, int mode,
             SQLiteDatabase.CursorFactory factory) {
         throw new UnsupportedOperationException();
     }
@@ -310,7 +315,7 @@
             Bundle options) throws IntentSender.SendIntentException {
         startIntentSender(intent, fillInIntent, flagsMask, flagsValues, extraFlags);
     }
-    
+
     @Override
     public void sendBroadcast(Intent intent) {
         throw new UnsupportedOperationException();
diff --git a/test-runner/src/android/test/mock/MockCursor.java b/test-runner/src/android/test/mock/MockCursor.java
index 28fa0f8..576f24a 100644
--- a/test-runner/src/android/test/mock/MockCursor.java
+++ b/test-runner/src/android/test/mock/MockCursor.java
@@ -25,15 +25,18 @@
 import android.os.Bundle;
 
 /**
- * <P>
  * A mock {@link android.database.Cursor} class that isolates the test code from real
  * Cursor implementation.
- * </P>
- * <P>
+ *
+ * <p>
  * All methods including ones related to querying the state of the cursor are
  * are non-functional and throw {@link java.lang.UnsupportedOperationException}.
- * </P>
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class MockCursor implements Cursor {
     @Override
     public int getColumnCount() {
diff --git a/test-runner/src/android/test/mock/MockDialogInterface.java b/test-runner/src/android/test/mock/MockDialogInterface.java
index e4dd0ba..d0a5a09 100644
--- a/test-runner/src/android/test/mock/MockDialogInterface.java
+++ b/test-runner/src/android/test/mock/MockDialogInterface.java
@@ -1,14 +1,33 @@
-// Copyright 2008 The Android Open Source Project
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 package android.test.mock;
 
 import android.content.DialogInterface;
 
 /**
- * A mock {@link android.content.DialogInterface} class.  All methods are non-functional and throw 
- * {@link java.lang.UnsupportedOperationException}. Override it to provide the operations that you 
+ * A mock {@link android.content.DialogInterface} class.  All methods are non-functional and throw
+ * {@link java.lang.UnsupportedOperationException}. Override it to provide the operations that you
  * need.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class MockDialogInterface implements DialogInterface {
     public void cancel() {
         throw new UnsupportedOperationException("not implemented yet");
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 5296d4d..ffb73f6 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -60,7 +60,12 @@
  * A mock {@link android.content.pm.PackageManager} class.  All methods are non-functional and throw
  * {@link java.lang.UnsupportedOperationException}. Override it to provide the operations that you
  * need.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class MockPackageManager extends PackageManager {
 
     @Override
diff --git a/test-runner/src/android/test/mock/MockResources.java b/test-runner/src/android/test/mock/MockResources.java
index 18752ce..880343e 100644
--- a/test-runner/src/android/test/mock/MockResources.java
+++ b/test-runner/src/android/test/mock/MockResources.java
@@ -32,10 +32,15 @@
 import java.io.InputStream;
 
 /**
- * A mock {@link android.content.res.Resources} class.  All methods are non-functional and throw 
- * {@link java.lang.UnsupportedOperationException}. Override it to provide the operations that you 
+ * A mock {@link android.content.res.Resources} class. All methods are non-functional and throw
+ * {@link java.lang.UnsupportedOperationException}. Override it to provide the operations that you
  * need.
+ *
+ * @deprecated Use a mocking framework like <a href="https://github.com/mockito/mockito">Mockito</a>.
+ * New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 public class MockResources extends Resources {
 
     public MockResources() {
diff --git a/tests/SoundTriggerTestApp/Android.mk b/tests/SoundTriggerTestApp/Android.mk
new file mode 100644
index 0000000..7bcab5e
--- /dev/null
+++ b/tests/SoundTriggerTestApp/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := SoundTriggerTestApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_PRIVILEGED_MODULE := true
+
+include $(BUILD_PACKAGE)
diff --git a/tests/SoundTriggerTestApp/AndroidManifest.xml b/tests/SoundTriggerTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..40619da
--- /dev/null
+++ b/tests/SoundTriggerTestApp/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.test.soundtrigger">
+
+    <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+    <application
+         android:permission="android.permission.MANAGE_SOUND_TRIGGER">
+        <activity
+            android:name="TestSoundTriggerActivity"
+            android:label="SoundTrigger Test Application"
+            android:theme="@android:style/Theme.Material.Light.Voice">
+            <intent-filter>
+                <action android:name="com.android.intent.action.MANAGE_SOUND_TRIGGER" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
new file mode 100644
index 0000000..9d2b9d9
--- /dev/null
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 Google Inc.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    >
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/enroll"
+        android:onClick="onEnrollButtonClicked"
+        android:padding="20dp" />
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/reenroll"
+        android:onClick="onReEnrollButtonClicked"
+        android:padding="20dp" />
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/unenroll"
+        android:onClick="onUnEnrollButtonClicked"
+        android:padding="20dp" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/SoundTriggerTestApp/res/values/strings.xml b/tests/SoundTriggerTestApp/res/values/strings.xml
new file mode 100644
index 0000000..07bac2a
--- /dev/null
+++ b/tests/SoundTriggerTestApp/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 Google Inc.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <string name="enroll">Enroll</string>
+    <string name="reenroll">Re-enroll</string>
+    <string name="unenroll">Un-enroll</string>
+</resources>
\ No newline at end of file
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
new file mode 100644
index 0000000..4702835
--- /dev/null
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.soundtrigger;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.soundtrigger.SoundTriggerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.util.UUID;
+
+/**
+ * Utility class for the managing sound trigger sound models.
+ */
+public class SoundTriggerUtil {
+    private static final String TAG = "TestSoundTriggerUtil:Hotsound";
+
+    private final ISoundTriggerService mSoundTriggerService;
+    private final SoundTriggerManager mSoundTriggerManager;
+    private final Context mContext;
+
+    public SoundTriggerUtil(Context context) {
+        mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+                ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+        mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+                Context.SOUND_TRIGGER_SERVICE);
+        mContext = context;
+    }
+
+    /**
+     * Adds/Updates a sound model.
+     * The sound model must contain a valid UUID.
+     *
+     * @param soundModel The sound model to add/update.
+     */
+    public boolean addOrUpdateSoundModel(GenericSoundModel soundModel) {
+        try {
+            mSoundTriggerService.updateSoundModel(soundModel);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in updateSoundModel", e);
+        }
+        return true;
+    }
+
+    public void addOrUpdateSoundModel(SoundTriggerManager.Model soundModel) {
+        mSoundTriggerManager.updateModel(soundModel);
+    }
+
+    /**
+     * Gets the sound model for the given keyphrase, null if none exists.
+     * If a sound model for a given keyphrase exists, and it needs to be updated,
+     * it should be obtained using this method, updated and then passed in to
+     * {@link #addOrUpdateSoundModel(GenericSoundModel)} without changing the IDs.
+     *
+     * @param modelId The model ID to look-up the sound model for.
+     * @return The sound model if one was found, null otherwise.
+     */
+    @Nullable
+    public GenericSoundModel getSoundModel(UUID modelId) {
+        GenericSoundModel model = null;
+        try {
+            model = mSoundTriggerService.getSoundModel(new ParcelUuid(modelId));
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in updateKeyphraseSoundModel");
+        }
+
+        if (model == null) {
+            Log.w(TAG, "No models present for the gien keyphrase ID");
+            return null;
+        } else {
+            return model;
+        }
+    }
+
+    /**
+     * Deletes the sound model for the given keyphrase id.
+     *
+     * @param modelId The model ID to look-up the sound model for.
+     * @return {@code true} if the call succeeds, {@code false} otherwise.
+     */
+    @Nullable
+    public boolean deleteSoundModel(UUID modelId) {
+        try {
+            mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelId));
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in updateSoundModel");
+        }
+        return true;
+    }
+
+    public void deleteSoundModelUsingManager(UUID modelId) {
+            mSoundTriggerManager.deleteModel(modelId);
+    }
+}
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
new file mode 100644
index 0000000..966179b
--- /dev/null
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.soundtrigger;
+
+import java.util.Random;
+import java.util.UUID;
+
+import android.app.Activity;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.soundtrigger.SoundTriggerManager;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+public class TestSoundTriggerActivity extends Activity {
+    private static final String TAG = "TestSoundTriggerActivity";
+    private static final boolean DBG = true;
+
+    private SoundTriggerUtil mSoundTriggerUtil;
+    private Random mRandom;
+    private UUID mModelUuid = UUID.randomUUID();
+    private UUID mModelUuid2 = UUID.randomUUID();
+    private UUID mVendorUuid = UUID.randomUUID();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        if (DBG) Log.d(TAG, "onCreate");
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+        mSoundTriggerUtil = new SoundTriggerUtil(this);
+        mRandom = new Random();
+    }
+
+    /**
+     * Called when the user clicks the enroll button.
+     * Performs a fresh enrollment.
+     */
+    public void onEnrollButtonClicked(View v) {
+        // Generate a fake model to push.
+        byte[] data = new byte[1024];
+        mRandom.nextBytes(data);
+        GenericSoundModel model = new GenericSoundModel(mModelUuid, mVendorUuid, data);
+
+        boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(model);
+        if (status) {
+            Toast.makeText(
+                    this, "Successfully created sound trigger model UUID=" + mModelUuid, Toast.LENGTH_SHORT)
+                    .show();
+        } else {
+            Toast.makeText(this, "Failed to enroll!!!" + mModelUuid, Toast.LENGTH_SHORT).show();
+        }
+
+        // Test the SoundManager API.
+        SoundTriggerManager.Model tmpModel = SoundTriggerManager.Model.create(mModelUuid2,
+                mVendorUuid, data);
+        mSoundTriggerUtil.addOrUpdateSoundModel(tmpModel);
+    }
+
+    /**
+     * Called when the user clicks the un-enroll button.
+     * Clears the enrollment information for the user.
+     */
+    public void onUnEnrollButtonClicked(View v) {
+        GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(mModelUuid);
+        if (soundModel == null) {
+            Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
+            return;
+        }
+        boolean status = mSoundTriggerUtil.deleteSoundModel(mModelUuid);
+        if (status) {
+            Toast.makeText(this, "Successfully deleted model UUID=" + soundModel.uuid,
+                    Toast.LENGTH_SHORT)
+                    .show();
+        } else {
+            Toast.makeText(this, "Failed to delete sound model!!!", Toast.LENGTH_SHORT).show();
+        }
+        mSoundTriggerUtil.deleteSoundModelUsingManager(mModelUuid2);
+    }
+
+    /**
+     * Called when the user clicks the re-enroll button.
+     * Uses the previously enrolled sound model and makes changes to it before pushing it back.
+     */
+    public void onReEnrollButtonClicked(View v) {
+        GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(mModelUuid);
+        if (soundModel == null) {
+            Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
+            return;
+        }
+        // Generate a fake model to push.
+        byte[] data = new byte[2048];
+        mRandom.nextBytes(data);
+        GenericSoundModel updated = new GenericSoundModel(soundModel.uuid,
+                soundModel.vendorUuid, data);
+        boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
+        if (status) {
+            Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid,
+                    Toast.LENGTH_SHORT)
+                    .show();
+        } else {
+            Toast.makeText(this, "Failed to re-enroll!!!", Toast.LENGTH_SHORT).show();
+        }
+    }
+}
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml
new file mode 100644
index 0000000..e0e3f03
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#00ff0000"
+          android:startX="0"
+          android:startY="0"
+          android:endX="100"
+          android:endY="100"
+          android:type="linear">
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml
new file mode 100644
index 0000000..cfb1236
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="100"
+          android:endY="100"
+          android:type="linear">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml
new file mode 100644
index 0000000..18274b9
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_linear_item_overlap.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:startColor="?android:attr/colorPrimary"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerColor="#f00"
+          android:startX="0"
+          android:startY="0"
+          android:endX="100"
+          android:endY="100"
+          android:type="linear">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#f00"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml
new file mode 100644
index 0000000..ef6fd70
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="?android:attr/colorControlActivated"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="100"
+          android:startColor="?android:attr/colorPrimary"
+          android:type="radial">
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml
new file mode 100644
index 0000000..51b0e17
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+    <!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="100"
+          android:startColor="#ffffffff"
+          android:type="radial">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml
new file mode 100644
index 0000000..8caa1b4
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_radial_item_short.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+    <!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="300"
+          android:centerY="300"
+          android:gradientRadius="100"
+          android:type="radial">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml
new file mode 100644
index 0000000..e1fbd10
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep">
+</gradient>
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml
new file mode 100644
index 0000000..332b938
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerColor="#ff0000"
+          android:endColor="#ff0000ff"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:startColor="#ffffffff"
+          android:type="sweep">
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#fff"/>
+    <item android:offset="0.9" android:color="?android:attr/colorControlActivated"/>
+</gradient>
diff --git a/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml
new file mode 100644
index 0000000..3931288
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/fill_gradient_sweep_item_long.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:centerX="500"
+          android:centerY="500"
+          android:gradientRadius="10"
+          android:type="sweep">
+    <item android:offset="-0.3" android:color="#f00"/>
+    <item android:offset="0.1" android:color="?android:attr/colorPrimary"/>
+    <item android:offset="0.4" android:color="#0f0"/>
+    <item android:offset="0.6" android:color="#00f"/>
+    <item android:offset="0.7" android:color="?android:attr/colorControlActivated"/>
+    <item android:offset="1.5" android:color="#00f"/>
+</gradient>
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient.xml b/tests/VectorDrawableTest/res/color/stroke_gradient.xml
new file mode 100644
index 0000000..cb324c9
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="100"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear">
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml
new file mode 100644
index 0000000..15d948c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:angle="90"
+          android:centerColor="#7f7f7f"
+          android:endColor="#ffffff"
+          android:startColor="#000000"
+          android:startX="0"
+          android:endX="100"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml
new file mode 100644
index 0000000..fda2b88
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/stroke_gradient_item_alpha.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+          android:startX="0"
+          android:endX="100"
+          android:startY="0"
+          android:endY="0"
+          android:type="linear">
+    <item android:offset="0.1" android:color="#f00"/>
+    <item android:offset="0.2" android:color="#2f0f"/>
+    <item android:offset="0.9" android:color="#f00f"/>
+</gradient>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml
new file mode 100644
index 0000000..45d88b5
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorPrimary" android:state_pressed="true" />
+    <item android:color="?android:attr/colorControlActivated" />
+</selector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml
new file mode 100644
index 0000000..0e2467f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="#f00" android:state_pressed="true" />
+    <item android:color="#00f" />
+</selector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml
new file mode 100644
index 0000000..16251c8
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorControlActivated" android:state_pressed="true" />
+    <item android:color="?android:attr/colorPrimary" />
+</selector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml
new file mode 100644
index 0000000..7e6c8ce
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="#00f" android:state_pressed="true" />
+    <item android:color="#f00" />
+</selector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 2be99be..89afde2 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -27,8 +27,8 @@
         <path
             android:name="box1"
             android:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
-            android:fillColor="?android:attr/colorControlNormal"
-            android:strokeColor="?android:attr/colorControlNormal"
+            android:fillColor="?android:attr/colorPrimary"
+            android:strokeColor="?android:attr/colorPrimary"
             android:strokeLineCap="round"
             android:strokeLineJoin="round" />
     </group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml
new file mode 100644
index 0000000..d67aca7
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_1.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fillColor="@color/fill_gradient_linear"
+                        android:strokeColor="@color/stroke_gradient"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml
new file mode 100644
index 0000000..abf3c7a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_2.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml
new file mode 100644
index 0000000..5f9726f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_gradient_3.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+<group android:name="backgroundGroup"
+       android:scaleX="0.5"
+       android:scaleY="0.5">
+    <path
+            android:name="background1"
+            android:fillColor="@color/fill_gradient_linear_item_overlap"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background2"
+            android:fillColor="@color/fill_gradient_radial_item_short"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+    <path
+            android:name="background3"
+            android:fillColor="@color/fill_gradient_sweep_item_long"
+            android:pathData="M 400,400 l 200,0 l 0, 200 l -200, 0 z" />
+</group>
+<group
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
+    <path
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="@color/stroke_gradient_item_alpha"
+            android:strokeWidth="20" />
+
+    <group
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
+        <path
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="@color/stroke_gradient_item_alpha"
+                android:strokeWidth="20" />
+
+        <group
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+
+        <group
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+            <group android:name="scaleGroup" >
+                <path
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="@color/stroke_gradient_item_alpha"
+                        android:strokeWidth="20" />
+            </group>
+        </group>
+    </group>
+</group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml
new file mode 100644
index 0000000..9f08fe8
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="24"
+        android:viewportWidth="24" >
+
+    <path
+        android:fillColor="@color/vector_icon_fill_state_list_simple"
+        android:strokeColor="@color/vector_icon_stroke_state_list_simple"
+        android:strokeWidth="3"
+        android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"/>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml
new file mode 100644
index 0000000..b1ed850
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="24"
+        android:viewportWidth="24" >
+
+    <path
+        android:fillColor="@color/vector_icon_fill_state_list"
+        android:strokeColor="@color/vector_icon_stroke_state_list"
+        android:strokeWidth="3"
+        android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"/>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index b4a93f6..7172147 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -35,6 +35,11 @@
 public class VectorDrawablePerformance extends Activity {
     private static final String LOGCAT = "VectorDrawable1";
     protected int[] icon = {
+            R.drawable.vector_icon_gradient_1,
+            R.drawable.vector_icon_gradient_2,
+            R.drawable.vector_icon_gradient_3,
+            R.drawable.vector_icon_state_list_simple,
+            R.drawable.vector_icon_state_list_theme,
             R.drawable.vector_drawable01,
             R.drawable.vector_drawable02,
             R.drawable.vector_drawable03,
@@ -102,7 +107,7 @@
         ScrollView scrollView = new ScrollView(this);
         GridLayout container = new GridLayout(this);
         scrollView.addView(container);
-        container.setColumnCount(5);
+        container.setColumnCount(4);
         Resources res = this.getResources();
         container.setBackgroundColor(0xFF888888);
         VectorDrawable []d = new VectorDrawable[icon.length];
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index a3f3821..2000fbc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -50,7 +50,7 @@
 
     @Override
     public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6,
-            boolean b, Configuration configuration, Rect rect7) throws RemoteException {
+            boolean b, Configuration configuration, Rect rect7, boolean b2) throws RemoteException {
         // pass for now.
     }
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 274e985..4c22460 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -704,24 +704,6 @@
      */
     public int numUserTriggeredJoinAttempts;
 
-    /**
-     * @hide
-     * Connect choices
-     *
-     * remember the keys identifying the known WifiConfiguration over which this configuration
-     * was preferred by user or a "WiFi Network Management app", that is,
-     * a WifiManager.CONNECT_NETWORK or SELECT_NETWORK was received while this configuration
-     * was visible to the user:
-     * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP
-     *
-     * The integer represents the configuration's RSSI at that time (useful?)
-     *
-     * The overall auto-join algorithm make use of past connect choice so as to sort configuration,
-     * the exact algorithm still fluctuating as of 5/7/2014
-     *
-     */
-    public HashMap<String, Integer> connectChoices;
-
     /** @hide
      * Boost given to RSSI on a home network for the purpose of calculating the score
      * This adds stickiness to home networks, as defined by:
@@ -831,6 +813,16 @@
          */
         public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L;
 
+        /**
+         *  This constant indicates the current configuration has connect choice set
+         */
+        private static final int CONNECT_CHOICE_EXISTS = 1;
+
+        /**
+         *  This constant indicates the current configuration does not have connect choice set
+         */
+        private static final int CONNECT_CHOICE_NOT_EXISTS = -1;
+
         // fields for QualityNetwork Selection
         /**
          * Network selection status, should be in one of three status: enable, temporaily disabled
@@ -854,7 +846,128 @@
         private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX];
 
         /**
-         * return current Quality network selection status in String (for debug purpose)
+         * Connect Choice over this configuration
+         *
+         * When current wifi configuration is visible to the user but user explicitly choose to
+         * connect to another network X, the another networks X's configure key will be stored here.
+         * We will consider user has a preference of X over this network. And in the future,
+         * network selection will always give X a higher preference over this configuration.
+         * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP
+         */
+        private String mConnectChoice;
+
+        /**
+         * The system timestamp when we records the connectChoice. This value is obtained from
+         * System.currentTimeMillis
+         */
+        private long mConnectChoiceTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
+
+        /**
+         * Used to cache the temporary candidate during the network selection procedure. It will be
+         * kept updating once a new scan result has a higher score than current one
+         */
+        private ScanResult mCandidate;
+
+        /**
+         * Used to cache the score of the current temporary candidate during the network
+         * selection procedure.
+         */
+        private int mCandidateScore;
+
+        /**
+         * Indicate whether this network is visible in latest Qualified Network Selection. This
+         * means there is scan result found related to this Configuration and meet the minimum
+         * requirement. The saved network need not join latest Qualified Network Selection. For
+         * example, it is disabled. True means network is visible in latest Qualified Network
+         * Selection and false means network is invisible
+         */
+        private boolean mSeenInLastQualifiedNetworkSelection;
+
+        /**
+         * set whether this network is visible in latest Qualified Network Selection
+         * @param seen value set to candidate
+         */
+        public void setSeenInLastQualifiedNetworkSelection(boolean seen) {
+            mSeenInLastQualifiedNetworkSelection =  seen;
+        }
+
+        /**
+         * get whether this network is visible in latest Qualified Network Selection
+         * @return returns true -- network is visible in latest Qualified Network Selection
+         *         false -- network is invisible in latest Qualified Network Selection
+         */
+        public boolean getSeenInLastQualifiedNetworkSelection() {
+            return mSeenInLastQualifiedNetworkSelection;
+        }
+        /**
+         * set the temporary candidate of current network selection procedure
+         * @param scanCandidate {@link ScanResult} the candidate set to mCandidate
+         */
+        public void setCandidate(ScanResult scanCandidate) {
+            mCandidate = scanCandidate;
+        }
+
+        /**
+         * get the temporary candidate of current network selection procedure
+         * @return  returns {@link ScanResult} temporary candidate of current network selection
+         * procedure
+         */
+        public ScanResult getCandidate() {
+            return mCandidate;
+        }
+
+        /**
+         * set the score of the temporary candidate of current network selection procedure
+         * @param score value set to mCandidateScore
+         */
+        public void setCandidateScore(int score) {
+            mCandidateScore = score;
+        }
+
+        /**
+         * get the score of the temporary candidate of current network selection procedure
+         * @return returns score of the temporary candidate of current network selection procedure
+         */
+        public int getCandidateScore() {
+            return mCandidateScore;
+        }
+
+        /**
+         * get user preferred choice over this configuration
+         *@return returns configKey of user preferred choice over this configuration
+         */
+        public String getConnectChoice() {
+            return mConnectChoice;
+        }
+
+        /**
+         * set user preferred choice over this configuration
+         * @param newConnectChoice, the configKey of user preferred choice over this configuration
+         */
+        public void setConnectChoice(String newConnectChoice) {
+            mConnectChoice = newConnectChoice;
+        }
+
+        /**
+         * get the timeStamp when user select a choice over this configuration
+         * @return returns when current connectChoice is set (time from System.currentTimeMillis)
+         */
+        public long getConnectChoiceTimestamp() {
+            return mConnectChoiceTimestamp;
+        }
+
+        /**
+         * set the timeStamp when user select a choice over this configuration
+         * @param timeStamp, the timestamp set to connectChoiceTimestamp, expected timestamp should
+         *        be obtained from System.currentTimeMillis
+         */
+        public void setConnectChoiceTimestamp(long timeStamp) {
+            mConnectChoiceTimestamp = timeStamp;
+        }
+
+        /**
+         * get current Quality network selection status
+         * @return returns current Quality network selection status in String (for debug purpose)
          */
         public String getNetworkStatusString() {
             return QUALITY_NETWORK_SELECTION_STATUS[mStatus];
@@ -874,6 +987,7 @@
             }
         }
         /**
+         * get current network disable reason
          * @return current network disable reason in String (for debug purpose)
          */
         public String getNetworkDisableReasonString() {
@@ -882,6 +996,7 @@
 
         /**
          * get current network network selection status
+         * @return return current network network selection status
          */
         public int getNetworkSelectionStatus() {
             return mStatus;
@@ -901,12 +1016,14 @@
         }
 
         /**
-         * return whether current network is permanently disabled
+         * @return returns whether current network is permanently disabled
          */
         public boolean isNetworkPermanentlyDisabled() {
             return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED;
         }
+
         /**
+         * set current networ work selection status
          * @param status network selection status to set
          */
         public void setNetworkSelectionStatus(int status) {
@@ -914,14 +1031,16 @@
                 mStatus = status;
             }
         }
+
         /**
-         * @return current network's disable reason
+         * @return returns current network's disable reason
          */
         public int getNetworkSelectionDisableReason() {
             return mNetworkSelectionDisableReason;
         }
 
         /**
+         * set Network disable reason
          * @param  reason Network disable reason
          */
         public void setNetworkSelectionDisableReason(int reason) {
@@ -931,12 +1050,17 @@
                 throw new IllegalArgumentException("Illegal reason value: " + reason);
             }
         }
+
         /**
-         * @param reason whether current network is disabled by this reason
+         * check whether network is disabled by this reason
+         * @param reason a specific disable reason
+         * @return true -- network is disabled for this reason
+         *         false -- network is not disabled for this reason
          */
         public boolean isDisabledByReason(int reason) {
             return mNetworkSelectionDisableReason == reason;
         }
+
         /**
          * @param timeStamp Set when current network is disabled in millisecond since January 1,
          * 1970 00:00:00.0 UTC
@@ -946,7 +1070,7 @@
         }
 
         /**
-         * @return Get when current network is disabled in millisecond since January 1,
+         * @return returns when current network is disabled in millisecond since January 1,
          * 1970 00:00:00.0 UTC
          */
         public long getDisableTime() {
@@ -954,6 +1078,7 @@
         }
 
         /**
+         * get the disable counter of a specific reason
          * @param  reason specific failure reason
          * @exception throw IllegalArgumentException for illegal input
          * @return counter number for specific error reason.
@@ -992,6 +1117,7 @@
                 throw new IllegalArgumentException("Illegal reason value: " + reason);
             }
         }
+
         /**
          * clear the counter of a specific failure reason
          * @hide
@@ -1005,6 +1131,7 @@
                 throw new IllegalArgumentException("Illegal reason value: " + reason);
             }
         }
+
         /**
          * clear all the failure reason counters
          */
@@ -1043,6 +1170,8 @@
             }
             mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp;
             mNetworkSelectionBSSID = source.mNetworkSelectionBSSID;
+            setConnectChoice(source.getConnectChoice());
+            setConnectChoiceTimestamp(source.getConnectChoiceTimestamp());
         }
 
         public void writeToParcel(Parcel dest) {
@@ -1054,6 +1183,13 @@
             }
             dest.writeLong(getDisableTime());
             dest.writeString(getNetworkSelectionBSSID());
+            if (getConnectChoice() != null) {
+                dest.writeInt(CONNECT_CHOICE_EXISTS);
+                dest.writeString(getConnectChoice());
+                dest.writeLong(getConnectChoiceTimestamp());
+            } else {
+                dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
+            }
         }
 
         public void readFromParcel(Parcel in) {
@@ -1065,6 +1201,13 @@
             }
             setDisableTime(in.readLong());
             setNetworkSelectionBSSID(in.readString());
+            if (in.readInt() == CONNECT_CHOICE_EXISTS) {
+                setConnectChoice(in.readString());
+                setConnectChoiceTimestamp(in.readLong());
+            } else {
+                setConnectChoice(null);
+                setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
+            }
         }
     }
 
@@ -1184,7 +1327,11 @@
                 }
             }
         }
-
+        if (mNetworkSelectionStatus.getConnectChoice() != null) {
+            sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
+            sbuf.append(" connect choice set time: ").append(mNetworkSelectionStatus
+                    .getConnectChoiceTimestamp());
+        }
 
         if (this.numAssociation > 0) {
             sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
@@ -1336,16 +1483,7 @@
                 sbuf.append('\n');
             }
         }
-        if (this.connectChoices != null) {
-            for(String key : this.connectChoices.keySet()) {
-                Integer choice = this.connectChoices.get(key);
-                if (choice != null) {
-                    sbuf.append(" choice: ").append(key);
-                    sbuf.append(" = ").append(choice);
-                    sbuf.append('\n');
-                }
-            }
-        }
+
         sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI);
         sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI);
         sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI);
@@ -1632,11 +1770,6 @@
 
             mIpConfiguration = new IpConfiguration(source.mIpConfiguration);
 
-            if ((source.connectChoices != null) && (source.connectChoices.size() > 0)) {
-                connectChoices = new HashMap<String, Integer>();
-                connectChoices.putAll(source.connectChoices);
-            }
-
             if ((source.linkedConfigurations != null)
                     && (source.linkedConfigurations.size() > 0)) {
                 linkedConfigurations = new HashMap<String, Integer>();
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
index ff3d29f..ec9e462 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
@@ -43,7 +43,8 @@
     void publish(int sessionId, in PublishData publishData, in PublishSettings publishSettings);
     void subscribe(int sessionId, in SubscribeData subscribeData,
             in SubscribeSettings subscribeSettings);
-    void sendMessage(int sessionId, int peerId, in byte[] message, int messageLength);
+    void sendMessage(int sessionId, int peerId, in byte[] message, int messageLength,
+            int messageId);
     void stopSession(int sessionId);
     void destroySession(int sessionId);
 }
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl b/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
index 773f83b..50c34d9 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
@@ -32,7 +32,7 @@
     void onMatch(int peerId, in byte[] serviceSpecificInfo,
             int serviceSpecificInfoLength, in byte[] matchFilter, int matchFilterLength);
 
-    void onMessageSendSuccess();
-    void onMessageSendFail(int reason);
+    void onMessageSendSuccess(int messageId);
+    void onMessageSendFail(int messageId, int reason);
     void onMessageReceived(int peerId, in byte[] message, int messageLength);
 }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index 877f993..cb82268 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -319,13 +319,14 @@
     /**
      * {@hide}
      */
-    public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength) {
+    public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength,
+            int messageId) {
         try {
             if (VDBG) {
                 Log.v(TAG, "sendMessage(): sessionId=" + sessionId + ", peerId=" + peerId
-                        + ", messageLength=" + messageLength);
+                        + ", messageLength=" + messageLength + ", messageId=" + messageId);
             }
-            mService.sendMessage(sessionId, peerId, message, messageLength);
+            mService.sendMessage(sessionId, peerId, message, messageLength, messageId);
         } catch (RemoteException e) {
             Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
         }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java
index c6b384e..d0a9410 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java
@@ -103,8 +103,11 @@
      * @param message The message to be transmitted.
      * @param messageLength The number of bytes from the {@code message} to be
      *            transmitted.
+     * @param messageId An arbitrary integer used by the caller to identify the
+     *            message. The same integer ID will be returned in the callbacks
+     *            indicated message send success or failure.
      */
-    public void sendMessage(int peerId, byte[] message, int messageLength) {
-        mManager.sendMessage(mSessionId, peerId, message, messageLength);
+    public void sendMessage(int peerId, byte[] message, int messageLength, int messageId) {
+        mManager.sendMessage(mSessionId, peerId, message, messageLength, messageId);
     }
 }
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
index c9d08c7..d5e59f0 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
@@ -210,10 +210,10 @@
                                 msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2), msg.arg2);
                         break;
                     case LISTEN_MESSAGE_SEND_SUCCESS:
-                        WifiNanSessionListener.this.onMessageSendSuccess();
+                        WifiNanSessionListener.this.onMessageSendSuccess(msg.arg1);
                         break;
                     case LISTEN_MESSAGE_SEND_FAIL:
-                        WifiNanSessionListener.this.onMessageSendFail(msg.arg1);
+                        WifiNanSessionListener.this.onMessageSendFail(msg.arg1, msg.arg2);
                         break;
                     case LISTEN_MESSAGE_RECEIVED:
                         WifiNanSessionListener.this.onMessageReceived(msg.arg2,
@@ -306,7 +306,7 @@
      * {@link WifiNanSessionListener#onMessageSendFail(int)} will be received -
      * never both.
      */
-    public void onMessageSendSuccess() {
+    public void onMessageSendSuccess(int messageId) {
         if (VDBG) Log.v(TAG, "onMessageSendSuccess: called in stub - override if interested");
     }
 
@@ -325,7 +325,7 @@
      * @param reason The failure reason using {@code NanSessionListener.FAIL_*}
      *            codes.
      */
-    public void onMessageSendFail(int reason) {
+    public void onMessageSendFail(int messageId, int reason) {
         if (VDBG) Log.v(TAG, "onMessageSendFail: called in stub - override if interested");
     }
 
@@ -401,19 +401,21 @@
         }
 
         @Override
-        public void onMessageSendSuccess() {
+        public void onMessageSendSuccess(int messageId) {
             if (VDBG) Log.v(TAG, "onMessageSendSuccess");
 
             Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_SUCCESS);
+            msg.arg1 = messageId;
             mHandler.sendMessage(msg);
         }
 
         @Override
-        public void onMessageSendFail(int reason) {
+        public void onMessageSendFail(int messageId, int reason) {
             if (VDBG) Log.v(TAG, "onMessageSendFail: reason=" + reason);
 
             Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_FAIL);
-            msg.arg1 = reason;
+            msg.arg1 = messageId;
+            msg.arg2 = reason;
             mHandler.sendMessage(msg);
         }