Merge "Added a constant to be used as an Intent extra"
diff --git a/Android.mk b/Android.mk
index 1d797c4..5983b30 100644
--- a/Android.mk
+++ b/Android.mk
@@ -288,6 +288,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 +331,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 +385,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 \
diff --git a/api/current.txt b/api/current.txt
index 946a205..0ca7560 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";
@@ -5788,6 +5789,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);
@@ -13356,6 +13358,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();
@@ -13370,11 +13373,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";
@@ -13382,6 +13387,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";
@@ -13393,11 +13399,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
@@ -13405,6 +13413,7 @@
     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
@@ -13438,6 +13447,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[]);
@@ -13445,6 +13455,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);
@@ -13453,6 +13465,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);
@@ -13517,6 +13530,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;
@@ -19017,6 +19036,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();
@@ -19101,8 +19402,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);
@@ -19110,14 +19413,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);
@@ -19135,6 +19445,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";
@@ -19201,6 +19514,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
@@ -19320,6 +19634,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
@@ -19597,6 +19912,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();
@@ -19618,6 +19934,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();
@@ -19625,6 +19942,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);
@@ -20083,6 +20401,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;
@@ -20224,6 +20543,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;
   }
@@ -20451,6 +20788,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";
@@ -20466,11 +20813,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";
@@ -20792,9 +21143,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);
@@ -28549,6 +28902,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 {
@@ -32278,6 +32632,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";
@@ -32292,8 +32647,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";
@@ -32391,6 +32751,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);
@@ -32406,9 +32767,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();
@@ -35349,6 +35713,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);
@@ -35588,6 +35976,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";
@@ -35848,6 +36237,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
@@ -35999,6 +36389,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";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 9f36d92..d29c496 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";
@@ -7607,6 +7608,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);
   }
@@ -13755,6 +13758,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();
@@ -13765,16 +13769,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";
@@ -13782,6 +13789,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";
@@ -13789,16 +13797,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
@@ -13806,6 +13817,7 @@
     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
@@ -13840,6 +13852,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[]);
@@ -13849,6 +13862,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);
@@ -13857,6 +13872,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);
@@ -13921,6 +13937,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;
@@ -20050,7 +20072,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();
@@ -20059,6 +20112,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();
@@ -20084,16 +20138,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();
@@ -20116,6 +20174,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();
@@ -20184,6 +20244,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);
@@ -20214,7 +20276,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();
@@ -20226,12 +20294,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();
@@ -20249,30 +20321,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 {
@@ -20379,10 +20458,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);
@@ -20390,16 +20469,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);
@@ -20419,6 +20503,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";
@@ -20525,6 +20612,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
@@ -20658,6 +20746,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
@@ -20947,6 +21036,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();
@@ -20968,6 +21058,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();
@@ -20975,6 +21066,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);
@@ -21433,6 +21525,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;
@@ -21574,6 +21667,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;
   }
@@ -21801,6 +21912,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";
@@ -21816,11 +21937,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";
@@ -22142,9 +22267,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);
@@ -30627,6 +30754,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
@@ -34503,6 +34631,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";
@@ -34517,8 +34646,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";
@@ -34616,6 +34750,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);
@@ -34631,9 +34766,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();
@@ -37654,6 +37792,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);
@@ -37903,6 +38065,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";
@@ -37984,6 +38147,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 {
@@ -38243,6 +38407,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
@@ -38396,6 +38561,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";
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 5ddbf38..3797805 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";
@@ -5790,6 +5791,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);
@@ -13364,6 +13366,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();
@@ -13378,11 +13381,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";
@@ -13390,6 +13395,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";
@@ -13401,11 +13407,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
@@ -13413,6 +13421,7 @@
     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
@@ -13446,6 +13455,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[]);
@@ -13453,6 +13463,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);
@@ -13461,6 +13473,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);
@@ -13525,6 +13538,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;
@@ -19025,6 +19044,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();
@@ -19109,8 +19410,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);
@@ -19118,14 +19421,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);
@@ -19143,6 +19454,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";
@@ -19209,6 +19523,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
@@ -19328,6 +19643,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
@@ -19605,6 +19921,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();
@@ -19626,6 +19943,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();
@@ -19633,6 +19951,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);
@@ -20091,6 +20410,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;
@@ -20232,6 +20552,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;
   }
@@ -20459,6 +20797,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";
@@ -20474,11 +20822,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";
@@ -20800,9 +21152,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);
@@ -28557,6 +28911,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 {
@@ -32292,6 +32647,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";
@@ -32306,8 +32662,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";
@@ -32405,6 +32766,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);
@@ -32420,9 +32782,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();
@@ -35363,6 +35728,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);
@@ -35602,6 +35991,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";
@@ -35862,6 +36252,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
@@ -36013,6 +36404,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";
   }
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index fc1a355..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;
@@ -708,12 +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/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1c1526f..fef2a0e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2770,6 +2770,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.
@@ -3205,15 +3244,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 {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a80ed9b..20d4a29 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -230,6 +230,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);
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/Context.java b/core/java/android/content/Context.java
index 27cdd50..3142b40 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2613,6 +2613,7 @@
             MIDI_SERVICE,
             RADIO_SERVICE,
             HARDWARE_PROPERTIES_SERVICE,
+            //@hide: SOUND_TRIGGER_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -3195,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.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e18fde5..49b8363 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2626,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";
@@ -3218,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";
 
@@ -5706,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();
@@ -5815,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]",
@@ -5828,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>]"
         };
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/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/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..e91195c 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
@@ -297,7 +503,6 @@
         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;
@@ -348,7 +553,7 @@
                         mActiveSensors.put(handle, false);
                         removeSensorEvent(sensor);
                     } else {
-                        // it should never happen -- just ignore.
+                        // sensor just disconnected -- just ignore.
                     }
                 }
             }
@@ -456,6 +661,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);
@@ -485,6 +695,10 @@
         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;
@@ -523,6 +737,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/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/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/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/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/provider/Settings.java b/core/java/android/provider/Settings.java
index a9fd3c8..bc0d7d6 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5073,6 +5073,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 +5892,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/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/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/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/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/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/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index dbec740..1244987 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -100,7 +100,7 @@
             final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null ||
                     !"android".equals(ri.activityInfo.packageName) ||
                     !(ResolverActivity.class.getName().equals(ri.activityInfo.name)
-                    || ChooserActivity.class.getName().equals(ri.activityInfo.name));
+                    || "com.android.systemui.chooser.ChooserActivity".equals(ri.activityInfo.name));
 
             try {
                 startActivityAsCaller(newIntent, null, false, targetUserId);
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..4e48c1b4 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -22,6 +22,7 @@
 import android.app.VoiceInteractor.PickOptionRequest;
 import android.app.VoiceInteractor.PickOptionRequest.Option;
 import android.app.VoiceInteractor.Prompt;
+import android.content.pm.ComponentInfo;
 import android.os.AsyncTask;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -336,12 +337,12 @@
     /**
      * Perform any initialization needed for voice interaction.
      */
-    void onSetupVoiceInteraction() {
+    public void onSetupVoiceInteraction() {
         // Do it right now. Subclasses may delay this and send it later.
         sendVoiceChoicesIfNeeded();
     }
 
-    void sendVoiceChoicesIfNeeded() {
+    public void sendVoiceChoicesIfNeeded() {
         if (!isVoiceInteraction()) {
             // Clearly not needed.
             return;
@@ -382,7 +383,7 @@
         return null;
     }
 
-    int getLayoutResource() {
+    public int getLayoutResource() {
         return R.layout.resolver_list;
     }
 
@@ -591,7 +592,7 @@
                 mAlwaysUseOption);
     }
 
-    void startSelected(int which, boolean always, boolean filtered) {
+    public void startSelected(int which, boolean always, boolean filtered) {
         if (isFinishing()) {
             return;
         }
@@ -761,7 +762,7 @@
         return true;
     }
 
-    void safelyStartActivity(TargetInfo cti) {
+    public void safelyStartActivity(TargetInfo cti) {
         // If needed, show that intent is forwarded
         // from managed profile to owner or other way around.
         if (mProfileSwitchMessageId != -1) {
@@ -791,26 +792,26 @@
         }
     }
 
-    void onActivityStarted(TargetInfo cti) {
+    public void onActivityStarted(TargetInfo cti) {
         // Do nothing
     }
 
-    boolean shouldGetActivityMetadata() {
+    public boolean shouldGetActivityMetadata() {
         return false;
     }
 
-    boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
+    public boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
         return true;
     }
 
-    void showAppDetails(ResolveInfo ri) {
+    public void showTargetDetails(ResolveInfo ri) {
         Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                 .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
         startActivity(in);
     }
 
-    ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
+    public ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
             boolean filterLastUsed) {
         return new ResolveListAdapter(context, payloadIntents, initialIntents, rList,
@@ -820,7 +821,7 @@
     /**
      * Returns true if the activity is finishing and creation should halt
      */
-    boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
+    public boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
             List<ResolveInfo> rList, boolean alwaysUseOption) {
         // The last argument of createAdapter is whether to do special handling
         // of the last used choice to highlight it in the list.  We need to always
@@ -867,7 +868,7 @@
         return false;
     }
 
-    void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
+    public void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
             boolean alwaysUseOption) {
         final boolean useHeader = adapter.hasFilteredItem();
         final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null;
@@ -898,7 +899,7 @@
                 && Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName);
     }
 
-    final class DisplayResolveInfo implements TargetInfo {
+    public final class DisplayResolveInfo implements TargetInfo {
         private final ResolveInfo mResolveInfo;
         private final CharSequence mDisplayLabel;
         private Drawable mDisplayIcon;
@@ -906,8 +907,9 @@
         private final CharSequence mExtendedInfo;
         private final Intent mResolvedIntent;
         private final List<Intent> mSourceIntents = new ArrayList<>();
+        private boolean mPinned;
 
-        DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
+        public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel,
                 CharSequence pInfo, Intent pOrigIntent) {
             mSourceIntents.add(originalIntent);
             mResolveInfo = pri;
@@ -932,6 +934,7 @@
             mExtendedInfo = other.mExtendedInfo;
             mResolvedIntent = new Intent(other.mResolvedIntent);
             mResolvedIntent.fillIn(fillInIntent, flags);
+            mPinned = other.mPinned;
         }
 
         public ResolveInfo getResolveInfo() {
@@ -1026,6 +1029,15 @@
             activity.startActivityAsUser(mResolvedIntent, options, user);
             return false;
         }
+
+        @Override
+        public boolean isPinned() {
+            return mPinned;
+        }
+
+        public void setPinned(boolean pinned) {
+            mPinned = pinned;
+        }
     }
 
     /**
@@ -1039,7 +1051,7 @@
          *
          * @return the resolved intent for this target
          */
-        public Intent getResolvedIntent();
+        Intent getResolvedIntent();
 
         /**
          * Get the resolved component name that represents this target. Note that this may not
@@ -1048,7 +1060,7 @@
          *
          * @return the resolved ComponentName for this target
          */
-        public ComponentName getResolvedComponentName();
+        ComponentName getResolvedComponentName();
 
         /**
          * Start the activity referenced by this target.
@@ -1057,7 +1069,7 @@
          * @param options ActivityOptions bundle
          * @return true if the start completed successfully
          */
-        public boolean start(Activity activity, Bundle options);
+        boolean start(Activity activity, Bundle options);
 
         /**
          * Start the activity referenced by this target as if the ResolverActivity's caller
@@ -1068,7 +1080,7 @@
          * @param userId userId to start as or {@link UserHandle#USER_NULL} for activity's caller
          * @return true if the start completed successfully
          */
-        public boolean startAsCaller(Activity activity, Bundle options, int userId);
+        boolean startAsCaller(Activity activity, Bundle options, int userId);
 
         /**
          * Start the activity referenced by this target as a given user.
@@ -1078,7 +1090,7 @@
          * @param user handle for the user to start the activity as
          * @return true if the start completed successfully
          */
-        public boolean startAsUser(Activity activity, Bundle options, UserHandle user);
+        boolean startAsUser(Activity activity, Bundle options, UserHandle user);
 
         /**
          * Return the ResolveInfo about how and why this target matched the original query
@@ -1086,14 +1098,14 @@
          *
          * @return ResolveInfo representing this target's match
          */
-        public ResolveInfo getResolveInfo();
+        ResolveInfo getResolveInfo();
 
         /**
          * Return the human-readable text label for this target.
          *
          * @return user-visible target label
          */
-        public CharSequence getDisplayLabel();
+        CharSequence getDisplayLabel();
 
         /**
          * Return any extended info for this target. This may be used to disambiguate
@@ -1101,35 +1113,40 @@
          *
          * @return human-readable disambig string or null if none present
          */
-        public CharSequence getExtendedInfo();
+        CharSequence getExtendedInfo();
 
         /**
          * @return The drawable that should be used to represent this target
          */
-        public Drawable getDisplayIcon();
+        Drawable getDisplayIcon();
 
         /**
          * @return The (small) icon to badge the target with
          */
-        public Drawable getBadgeIcon();
+        Drawable getBadgeIcon();
 
         /**
          * @return The content description for the badge icon
          */
-        public CharSequence getBadgeContentDescription();
+        CharSequence getBadgeContentDescription();
 
         /**
          * Clone this target with the given fill-in information.
          */
-        public TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
+        TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
 
         /**
          * @return the list of supported source intents deduped against this single target
          */
-        public List<Intent> getAllSourceIntents();
+        List<Intent> getAllSourceIntents();
+
+        /**
+         * @return true if this target should be pinned to the front by the request of the user
+         */
+        boolean isPinned();
     }
 
-    class ResolveListAdapter extends BaseAdapter {
+    public class ResolveListAdapter extends BaseAdapter {
         private final List<Intent> mIntents;
         private final Intent[] mInitialIntents;
         private final List<ResolveInfo> mBaseResolveList;
@@ -1372,9 +1389,12 @@
                     }
                 }
                 if (!found) {
-                    into.add(new ResolvedComponentInfo(new ComponentName(
-                            newInfo.activityInfo.packageName, newInfo.activityInfo.name),
-                            intent, newInfo));
+                    final ComponentName name = new ComponentName(
+                            newInfo.activityInfo.packageName, newInfo.activityInfo.name);
+                    final ResolvedComponentInfo rci = new ResolvedComponentInfo(name,
+                            intent, newInfo);
+                    rci.setPinned(isComponentPinned(name));
+                    into.add(rci);
                 }
             }
         }
@@ -1450,6 +1470,8 @@
             final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent);
             final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel,
                     extraInfo, replaceIntent);
+            final ComponentInfo ci = add.getComponentInfo();
+            dri.setPinned(rci.isPinned());
             addResolveInfo(dri);
             if (replaceIntent == intent) {
                 // Only add alternates if we didn't get a specific replacement from
@@ -1533,11 +1555,11 @@
             return false;
         }
 
-        protected int getDisplayResolveInfoCount() {
+        public int getDisplayResolveInfoCount() {
             return mDisplayList.size();
         }
 
-        protected DisplayResolveInfo getDisplayResolveInfo(int index) {
+        public DisplayResolveInfo getDisplayResolveInfo(int index) {
             // Used to query services. We only query services for primary targets, not alternates.
             return mDisplayList.get(index);
         }
@@ -1567,6 +1589,10 @@
             return !TextUtils.isEmpty(info.getExtendedInfo());
         }
 
+        public boolean isComponentPinned(ComponentName name) {
+            return false;
+        }
+
         public final void bindView(int position, View view) {
             onBindView(view, getItem(position));
         }
@@ -1603,6 +1629,7 @@
 
     static final class ResolvedComponentInfo {
         public final ComponentName name;
+        private boolean mPinned;
         private final List<Intent> mIntents = new ArrayList<>();
         private final List<ResolveInfo> mResolveInfos = new ArrayList<>();
 
@@ -1645,6 +1672,14 @@
             }
             return -1;
         }
+
+        public boolean isPinned() {
+            return mPinned;
+        }
+
+        public void setPinned(boolean pinned) {
+            mPinned = pinned;
+        }
     }
 
     static class ViewHolder {
@@ -1698,7 +1733,7 @@
                 return false;
             }
             ResolveInfo ri = mAdapter.resolveInfoForPosition(position, true);
-            showAppDetails(ri);
+            showTargetDetails(ri);
             return true;
         }
 
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 31556e2..964a7f5 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -48,7 +48,7 @@
     private static final boolean DEBUG = false;
 
     // Two weeks
-    private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14;
+    private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 7;
 
     private static final long RECENCY_TIME_PERIOD = 1000 * 60 * 60 * 12;
 
@@ -171,15 +171,27 @@
             }
         }
 
-        if (mStats != null) {
-            final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
-                    lhs.activityInfo.packageName, lhs.activityInfo.name));
-            final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
-                    rhs.activityInfo.packageName, rhs.activityInfo.name));
-            final float diff = rhsTarget.score - lhsTarget.score;
+        final boolean lPinned = lhsp.isPinned();
+        final boolean rPinned = rhsp.isPinned();
 
-            if (diff != 0) {
-                return diff > 0 ? 1 : -1;
+        if (lPinned && !rPinned) {
+            return -1;
+        } else if (!lPinned && rPinned) {
+            return 1;
+        }
+
+        // Pinned items stay stable within a normal lexical sort and ignore scoring.
+        if (!lPinned && !rPinned) {
+            if (mStats != null) {
+                final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
+                        lhs.activityInfo.packageName, lhs.activityInfo.name));
+                final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
+                        rhs.activityInfo.packageName, rhs.activityInfo.name));
+                final float diff = rhsTarget.score - lhsTarget.score;
+
+                if (diff != 0) {
+                    return diff > 0 ? 1 : -1;
+                }
             }
         }
 
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/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/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..a582492 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>
@@ -45,6 +46,7 @@
 
 struct SensorOffsets
 {
+    jclass      clazz;
     jfieldID    name;
     jfieldID    vendor;
     jfieldID    version;
@@ -60,8 +62,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 +77,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 +97,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 +158,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 +237,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();
@@ -235,6 +310,11 @@
                     // 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);
+                } 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(mScratch, 0, 2, value);
                 } else {
                     env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
                 }
@@ -355,6 +435,10 @@
             "(JLandroid/hardware/Sensor;I)Z",
             (void*)nativeGetSensorAtIndex },
 
+    {"nativeGetDynamicSensors",
+            "(JLjava/util/List;)V",
+            (void*)nativeGetDynamicSensors },
+
     {"nativeIsDataInjectionEnabled",
             "(J)Z",
             (void*)nativeIsDataInjectionEnabled},
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 56c3fc8..4ab81e9 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"
@@ -2872,19 +2887,6 @@
                  android:theme="@style/Theme.Material.DayNight.DarkActionBar"
                  android:forceDeviceEncrypted="true"
                  android:encryptionAware="true">
-        <activity android:name="com.android.internal.app.ChooserActivity"
-                android:theme="@style/Theme.DeviceDefault.Resolver"
-                android:finishOnCloseSystemDialogs="true"
-                android:excludeFromRecents="true"
-                android:documentLaunchMode="never"
-                android:relinquishTaskIdentity="true"
-                android:process=":ui">
-            <intent-filter>
-                <action android:name="android.intent.action.CHOOSER" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
-            </intent-filter>
-        </activity>
         <activity android:name="com.android.internal.app.IntentForwarderActivity"
                 android:finishOnCloseSystemDialogs="true"
                 android:theme="@style/Theme.NoDisplay"
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/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/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/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index f3baa5e..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;
@@ -2585,14 +2685,18 @@
         /**
          * 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/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/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
new file mode 100644
index 0000000..ebba343
--- /dev/null
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -0,0 +1,180 @@
+/**
+ * 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
+ */
+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;
+    }
+
+    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..4ae8e72
--- /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
+ * TODO: Mark this as a SystemApi and get approval.
+ */
+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/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/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index ff7b7b9..aefdc67 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>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index ad8b0d1..5ffc435 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;
@@ -204,6 +206,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 +264,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 +423,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/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 5abe7f6..89a6912 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -296,12 +296,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/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/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..880da9c0 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/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/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 21abb90..52b7b7d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -155,6 +155,10 @@
     <!-- TV picture-in-picture -->
     <uses-permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE" />
 
+    <!-- ChooserActivity -->
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+    <uses-permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
@@ -438,5 +442,20 @@
                 <action android:name="com.android.systemui.action.CLEAR_TUNER" />
             </intent-filter>
         </receiver>
+
+        <activity android:name=".chooser.ChooserActivity"
+                android:theme="@*android:style/Theme.DeviceDefault.Resolver"
+                android:finishOnCloseSystemDialogs="true"
+                android:excludeFromRecents="true"
+                android:documentLaunchMode="never"
+                android:relinquishTaskIdentity="true"
+                android:process=":chooser">
+            <intent-filter>
+                <action android:name="android.intent.action.CHOOSER" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.VOICE" />
+            </intent-filter>
+        </activity>
+
     </application>
 </manifest>
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/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/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/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index bf0cba2..32025e0 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -51,4 +51,16 @@
         <item>0</item><item>3</item>
         <item>3</item><item>3</item>
     </array>
+
+    <!-- Used in ResolverTargetActionsDialogFragment -->
+    <string-array name="resolver_target_actions_pin">
+        <item>@string/pin_target</item>
+        <item>@string/app_info</item>
+    </string-array>
+
+    <string-array name="resolver_target_actions_unpin">
+        <item>@string/unpin_target</item>
+        <item>@string/app_info</item>
+    </string-array>
+
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e245c24..8b0350a 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 -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 02158ac..3efa52f 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>
@@ -1337,4 +1340,9 @@
     <!-- Accessibility description for data saver being off [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_saver_off">Data Saver is off</string>
 
+    <!-- Resolver target actions strings -->
+    <string name="pin_target">Pin</string>
+    <string name="unpin_target">Unpin</string>
+    <string name="app_info">App info</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 4329f78..e40a0f4 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 -->
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/core/java/com/android/internal/app/ChooserActivity.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
similarity index 94%
rename from core/java/com/android/internal/app/ChooserActivity.java
rename to packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
index b7b7400..a8bc36e 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.app;
+package com.android.systemui.chooser;
 
 import android.animation.ObjectAnimator;
 import android.annotation.NonNull;
@@ -25,6 +25,7 @@
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
 import android.content.ServiceConnection;
+import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
 import android.content.pm.LabeledIntent;
 import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -65,8 +67,12 @@
 import android.widget.BaseAdapter;
 import android.widget.ListView;
 import com.android.internal.R;
+import com.android.internal.app.IntentForwarderActivity;
+import com.android.internal.app.ResolverActivity;
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -90,6 +96,11 @@
     private ChooserListAdapter mChooserListAdapter;
     private ChooserRowAdapter mChooserRowAdapter;
 
+    private SharedPreferences mPinnedSharedPrefs;
+    private static final float PINNED_TARGET_SCORE_BOOST = 1000.f;
+    private static final String PINNED_SHARED_PREFS_NAME = "chooser_pin_settings";
+    private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment";
+
     private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
 
     private static final int CHOOSER_TARGET_SERVICE_RESULT = 1;
@@ -206,10 +217,16 @@
         mRefinementIntentSender = intent.getParcelableExtra(
                 Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER);
         setSafeForwardingMode(true);
+
+        mPinnedSharedPrefs = getPinnedSharedPrefs(this);
         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);
+    }
+
+    static SharedPreferences getPinnedSharedPrefs(Context context) {
+        return context.getSharedPreferences(PINNED_SHARED_PREFS_NAME, MODE_PRIVATE);
     }
 
     @Override
@@ -242,7 +259,7 @@
     }
 
     @Override
-    void onActivityStarted(TargetInfo cti) {
+    public void onActivityStarted(TargetInfo cti) {
         if (mChosenComponentSender != null) {
             final ComponentName target = cti.getResolvedComponentName();
             if (target != null) {
@@ -258,7 +275,7 @@
     }
 
     @Override
-    void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
+    public void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
             boolean alwaysUseOption) {
         final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null;
         mChooserListAdapter = (ChooserListAdapter) adapter;
@@ -271,17 +288,17 @@
     }
 
     @Override
-    int getLayoutResource() {
+    public int getLayoutResource() {
         return R.layout.chooser_grid;
     }
 
     @Override
-    boolean shouldGetActivityMetadata() {
+    public boolean shouldGetActivityMetadata() {
         return true;
     }
 
     @Override
-    boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
+    public boolean shouldAutoLaunchSingleChoice(TargetInfo target) {
         final Intent intent = target.getResolvedIntent();
         final ResolveInfo resolve = target.getResolveInfo();
 
@@ -298,6 +315,16 @@
         return false;
     }
 
+    @Override
+    public void showTargetDetails(ResolveInfo ri) {
+        ComponentName name = ri.activityInfo.getComponentName();
+        boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
+        ResolverTargetActionsDialogFragment f =
+                new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()),
+                        name, pinned);
+        f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
+    }
+
     private void modifyTargetIntent(Intent in) {
         final String action = in.getAction();
         if (Intent.ACTION_SEND.equals(action) ||
@@ -339,7 +366,7 @@
     }
 
     @Override
-    void startSelected(int which, boolean always, boolean filtered) {
+    public void startSelected(int which, boolean always, boolean filtered) {
         super.startSelected(which, always, filtered);
 
         if (mChooserListAdapter != null) {
@@ -349,14 +376,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;
@@ -470,7 +497,7 @@
         mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
     }
 
-    void onSetupVoiceInteraction() {
+    public void onSetupVoiceInteraction() {
         // Do nothing. We'll send the voice stuff ourselves.
     }
 
@@ -542,7 +569,7 @@
     }
 
     @Override
-    ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
+    public ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
             Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
             boolean filterLastUsed) {
         final ChooserListAdapter adapter = new ChooserListAdapter(context, payloadIntents,
@@ -710,6 +737,11 @@
             }
             return results;
         }
+
+        @Override
+        public boolean isPinned() {
+            return mSourceInfo != null ? mSourceInfo.isPinned() : false;
+        }
     }
 
     public class ChooserListAdapter extends ResolveListAdapter {
@@ -776,6 +808,20 @@
         }
 
         @Override
+        public boolean isComponentPinned(ComponentName name) {
+            return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false);
+        }
+
+        @Override
+        public float getScore(DisplayResolveInfo target) {
+            float score = super.getScore(target);
+            if (target.isPinned()) {
+                score += PINNED_TARGET_SCORE_BOOST;
+            }
+            return score;
+        }
+
+        @Override
         public View onCreateView(ViewGroup parent) {
             return mInflater.inflate(
                     com.android.internal.R.layout.resolve_grid_item, parent, false);
@@ -1120,7 +1166,7 @@
                 v.setOnLongClickListener(new OnLongClickListener() {
                     @Override
                     public boolean onLongClick(View v) {
-                        showAppDetails(
+                        showTargetDetails(
                                 mChooserListAdapter.resolveInfoForPosition(
                                         holder.itemIndices[column], true));
                         return true;
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ResolverTargetActionsDialogFragment.java b/packages/SystemUI/src/com/android/systemui/chooser/ResolverTargetActionsDialogFragment.java
new file mode 100644
index 0000000..839aa45
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/chooser/ResolverTargetActionsDialogFragment.java
@@ -0,0 +1,98 @@
+/*
+ * 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.chooser;
+
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.systemui.R;
+
+/**
+ * Shows a dialog with actions to take on a chooser target
+ */
+public class ResolverTargetActionsDialogFragment extends DialogFragment
+        implements DialogInterface.OnClickListener {
+    private static final String NAME_KEY = "componentName";
+    private static final String PINNED_KEY = "pinned";
+    private static final String TITLE_KEY = "title";
+
+    // Sync with R.array.resolver_target_actions_* resources
+    private static final int TOGGLE_PIN_INDEX = 0;
+    private static final int APP_INFO_INDEX = 1;
+
+    public ResolverTargetActionsDialogFragment() {
+    }
+
+    public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
+            boolean pinned) {
+        Bundle args = new Bundle();
+        args.putCharSequence(TITLE_KEY, title);
+        args.putParcelable(NAME_KEY, name);
+        args.putBoolean(PINNED_KEY, pinned);
+        setArguments(args);
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final Bundle args = getArguments();
+        final int itemRes = args.getBoolean(PINNED_KEY, false)
+                ? R.array.resolver_target_actions_unpin
+                : R.array.resolver_target_actions_pin;
+        return new Builder(getContext())
+                .setCancelable(true)
+                .setItems(itemRes, this)
+                .setTitle(args.getCharSequence(TITLE_KEY))
+                .create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        final Bundle args = getArguments();
+        ComponentName name = args.getParcelable(NAME_KEY);
+        switch (which) {
+            case TOGGLE_PIN_INDEX:
+                SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext());
+                final String key = name.flattenToString();
+                boolean currentVal = sp.getBoolean(name.flattenToString(), false);
+                if (currentVal) {
+                    sp.edit().remove(key).apply();
+                } else {
+                    sp.edit().putBoolean(key, true).apply();
+                }
+
+                // Force the chooser to requery and resort things
+                getActivity().recreate();
+                break;
+            case APP_INFO_INDEX:
+                Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+                        .setData(Uri.fromParts("package", name.getPackageName(), null))
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+                startActivity(in);
+                break;
+        }
+        dismiss();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 72629a3..20e2fa4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -82,9 +82,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();
 
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/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..6a07a07 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;
@@ -127,7 +129,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsLogger.QS_BLUETOOTH;
+        return MetricsEvent.QS_BLUETOOTH;
     }
 
     @Override
@@ -181,14 +183,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..db86047 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles;
 
 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;
@@ -75,7 +76,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..724659c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles;
 
 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;
@@ -99,7 +100,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/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..278ac54 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;
@@ -132,7 +135,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 +167,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 +211,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) {
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/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/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..efa3ded 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());
         }
@@ -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/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index efa56bc..5359dd2 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);
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/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..ba08ee7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -14,6 +14,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -37,20 +38,20 @@
 
     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";
+    protected static final String MENU_IME = "menu_ime";
+    protected static final String BACK = "back";
+    protected static final String HOME = "home";
+    protected static final String RECENT = "recent";
+    protected static final String NAVSPACE = "space";
 
     public static final String GRAVITY_SEPARATOR = ";";
     public static final String BUTTON_SEPARATOR = ",";
 
-    private final LayoutInflater mLayoutInflater;
-    private final LayoutInflater mLandscapeInflater;
+    protected final LayoutInflater mLayoutInflater;
+    protected final LayoutInflater mLandscapeInflater;
 
-    private FrameLayout mRot0;
-    private FrameLayout mRot90;
+    protected FrameLayout mRot0;
+    protected FrameLayout mRot90;
     private SparseArray<ButtonDispatcher> mButtonDispatchers;
     private String mCurrentLayout;
 
@@ -72,7 +73,7 @@
         inflateLayout(getDefaultLayout());
     }
 
-    private String getDefaultLayout() {
+    protected String getDefaultLayout() {
         return mContext.getString(R.string.config_navBarLayout);
     }
 
@@ -128,9 +129,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 +166,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,35 +205,33 @@
         return new LayoutParams(layoutParams.width, layoutParams.height);
     }
 
-    private View inflateButton(String button, ViewGroup parent, boolean landscape) {
-        View v = null;
+    @Nullable
+    protected View inflateButton(String button, ViewGroup parent, boolean landscape) {
+        View v;
+        LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
         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 {
-            throw new IllegalArgumentException("Unknown button " + button);
+            return null;
         }
+
         parent.addView(v);
         addToDispatchers(v);
         return v;
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..f2dea3c 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) {
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/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..e4ded67 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;
@@ -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/ColorMatrixTile.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
index 1fd2352..3206882 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ColorMatrixTile.java
@@ -17,7 +17,7 @@
 
 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;
@@ -102,6 +102,6 @@
 
     @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/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/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index a3fe6bb..427b5e8 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;
@@ -84,7 +85,7 @@
         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 +93,7 @@
         super.onPause();
         getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
 
-        MetricsLogger.visibility(getContext(), MetricsLogger.TUNER, false);
+        MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, false);
     }
 
     @Override
@@ -141,7 +142,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/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/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/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..c3c3e3f 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);
 
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/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/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/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/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/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/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/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 2833b35..f02e49e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -587,6 +587,7 @@
                 outBounds.top = dockedBounds.bottom + dockDividerWidth;
             }
         }
+        DockedDividerUtils.sanitizeStackBounds(outBounds);
     }
 
     /** Resizes all non-docked stacks in the system to either fullscreen or the appropriate size
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e8de90c..c541b3f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2061,7 +2061,8 @@
             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) {
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 4fd8990..b94e6d6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -471,6 +471,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";
@@ -559,6 +560,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;
@@ -749,6 +751,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));
@@ -919,7 +926,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(
@@ -1150,6 +1160,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=");
@@ -1971,7 +1983,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 +2420,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() {
@@ -4789,6 +4809,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 +5379,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 +5423,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 +5433,6 @@
             admin.disableCamera = false;
             admin.userRestrictions = null;
             clearUserPoliciesLocked(callingUser);
-            final int userId = callingUser.getIdentifier();
             mOwners.removeProfileOwner(userId);
             mOwners.writeProfileOwner(userId);
         }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c186a12..9f320e4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -84,6 +84,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;
@@ -959,6 +960,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 +979,7 @@
                     Slog.i(TAG, "Gesture Launcher Service");
                     mSystemServiceManager.startService(GestureLauncherService.class);
                 }
+                mSystemServiceManager.startService(SensorNotificationService.class);
             }
 
             traceBeginAndSlog("StartDiskStatsService");
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..de902025 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 497864e8..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/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index ea96e7c..c65e8ba 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -58,6 +58,7 @@
         return "ModemActivityInfo{"
             + " mTimestamp=" + mTimestamp
             + " mSleepTimeMs=" + mSleepTimeMs
+            + " mIdleTimeMs=" + mIdleTimeMs
             + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
             + " mRxTimeMs=" + mRxTimeMs
             + " mEnergyUsed=" + mEnergyUsed
@@ -153,7 +154,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/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/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/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>();