Merge "Work on issue #24403813: ANR traces are too heavyweight." into nyc-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2fe5cbe..cee8fdb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -240,6 +240,7 @@
 $(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IRemoteControlDisplay.*)
 $(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit1_intermediates/src/com/android/test/split/feature/R.java)
 $(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit2_intermediates/src/com/android/test/split/feature/R.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware)
 
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index aeaae55..a4f6607 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5711,6 +5711,7 @@
 
   public class WallpaperManager {
     method public void clear() throws java.io.IOException;
+    method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
     method public void forgetLoadedWallpaper();
     method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -19155,168 +19156,110 @@
 
   public final class GnssClock 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 double getBiasNanos();
+    method public double getBiasUncertaintyNanos();
+    method public double getDriftNanosPerSecond();
+    method public double getDriftUncertaintyNanosPerSecond();
+    method public long getFullBiasNanos();
     method public int getHardwareClockDiscontinuityCount();
-    method public short getLeapSecond();
-    method public long getTimeInNs();
-    method public double getTimeUncertaintyInNs();
-    method public boolean hasBiasInNs();
-    method public boolean hasBiasUncertaintyInNs();
-    method public boolean hasDriftInNsPerSec();
-    method public boolean hasDriftUncertaintyInNsPerSec();
-    method public boolean hasFullBiasInNs();
+    method public int getLeapSecond();
+    method public long getTimeNanos();
+    method public double getTimeUncertaintyNanos();
+    method public boolean hasBiasNanos();
+    method public boolean hasBiasUncertaintyNanos();
+    method public boolean hasDriftNanosPerSecond();
+    method public boolean hasDriftUncertaintyNanosPerSecond();
+    method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
-    method public boolean hasTimeUncertaintyInNs();
+    method public boolean hasTimeUncertaintyNanos();
     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 resetBiasNanos();
+    method public void resetBiasUncertaintyNanos();
+    method public void resetDriftNanosPerSecond();
+    method public void resetDriftUncertaintyNanosPerSecond();
+    method public void resetFullBiasNanos();
     method public void resetLeapSecond();
-    method public void resetTimeUncertaintyInNs();
+    method public void resetTimeUncertaintyNanos();
     method public void set(android.location.GnssClock);
-    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 setBiasNanos(double);
+    method public void setBiasUncertaintyNanos(double);
+    method public void setDriftNanosPerSecond(double);
+    method public void setDriftUncertaintyNanosPerSecond(double);
+    method public void setFullBiasNanos(long);
     method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(short);
-    method public void setTimeInNs(long);
-    method public void setTimeUncertaintyInNs(double);
+    method public void setLeapSecond(int);
+    method public void setTimeNanos(long);
+    method public void setTimeUncertaintyNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
   public final class GnssMeasurement 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 double getAccumulatedDeltaRangeMeters();
+    method public int getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyMeters();
     method public long getCarrierCycles();
-    method public float getCarrierFrequencyInHz();
+    method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
     method public double getCarrierPhaseUncertainty();
-    method public double getCn0InDbHz();
-    method public double getCodePhaseInChips();
-    method public double getCodePhaseUncertaintyInChips();
-    method public byte getConstellationType();
-    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 double getPseudorangeInMeters();
-    method public double getPseudorangeRateInMetersPerSec();
-    method public double getPseudorangeRateUncertaintyInMetersPerSec();
-    method public double getPseudorangeUncertaintyInMeters();
-    method public long getReceivedSvTimeInNs();
-    method public long getReceivedSvTimeUncertaintyInNs();
+    method public double getCn0DbHz();
+    method public int getConstellationType();
+    method public int getMultipathIndicator();
+    method public double getPseudorangeRateMetersPerSecond();
+    method public double getPseudorangeRateUncertaintyMetersPerSecond();
+    method public long getReceivedSvTimeNanos();
+    method public long getReceivedSvTimeUncertaintyNanos();
     method public double getSnrInDb();
-    method public short getState();
-    method public short getSvid();
-    method public short getTimeFromLastBitInMs();
-    method public double getTimeOffsetInNs();
-    method public boolean hasAzimuthInDeg();
-    method public boolean hasAzimuthUncertaintyInDeg();
-    method public boolean hasBitNumber();
+    method public int getState();
+    method public int getSvid();
+    method public double getTimeOffsetNanos();
     method public boolean hasCarrierCycles();
-    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierFrequencyHz();
     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 resetCarrierFrequencyHz();
     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.GnssMeasurement);
-    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 setAccumulatedDeltaRangeMeters(double);
+    method public void setAccumulatedDeltaRangeState(int);
+    method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
     method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyInHz(float);
+    method public void setCarrierFrequencyHz(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 setConstellationType(byte);
-    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 setPseudorangeInMeters(double);
-    method public void setPseudorangeRateInMetersPerSec(double);
-    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
-    method public void setPseudorangeUncertaintyInMeters(double);
-    method public void setReceivedSvTimeInNs(long);
-    method public void setReceivedSvTimeUncertaintyInNs(long);
+    method public void setCn0DbHz(double);
+    method public void setConstellationType(int);
+    method public void setMultipathIndicator(int);
+    method public void setPseudorangeRateMetersPerSecond(double);
+    method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+    method public void setReceivedSvTimeNanos(long);
+    method public void setReceivedSvTimeUncertaintyNanos(long);
     method public void setSnrInDb(double);
-    method public void setState(short);
-    method public void setSvid(short);
-    method public void setTimeFromLastBitInMs(short);
-    method public void setTimeOffsetInNs(double);
-    method public void setUsedInFix(boolean);
+    method public void setState(int);
+    method public void setSvid(int);
+    method public void setTimeOffsetNanos(double);
     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 int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final int ADR_STATE_RESET = 2; // 0x2
+    field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final int ADR_STATE_VALID = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> 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 GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+    field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final int STATE_BIT_SYNC = 2; // 0x2
+    field public static final int STATE_CODE_LOCK = 1; // 0x1
+    field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final int STATE_TOW_DECODED = 8; // 0x8
+    field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19329,7 +19272,7 @@
     method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19346,34 +19289,34 @@
   public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
-    method public short getMessageId();
-    method public short getStatus();
-    method public short getSubmessageId();
-    method public short getSvid();
-    method public short getType();
+    method public int getMessageId();
+    method public int getStatus();
+    method public int getSubmessageId();
+    method public int getSvid();
+    method public int getType();
     method public void reset();
     method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
-    method public void setMessageId(short);
-    method public void setStatus(short);
-    method public void setSubmessageId(short);
-    method public void setSvid(short);
-    method public void setType(short);
+    method public void setMessageId(int);
+    method public void setStatus(int);
+    method public void setSubmessageId(int);
+    method public void setSvid(int);
+    method public void setType(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
-    field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
-    field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
-    field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
-    field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
-    field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
-    field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
-    field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
-    field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
-    field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
-    field public static final short 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 int STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final int STATUS_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_BDS_D1 = 1281; // 0x501
+    field public static final int TYPE_BDS_D2 = 1282; // 0x502
+    field public static final int TYPE_GAL_F = 1538; // 0x602
+    field public static final int TYPE_GAL_I = 1537; // 0x601
+    field public static final int TYPE_GLO_L1CA = 769; // 0x301
+    field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+    field public static final int TYPE_GPS_L1CA = 257; // 0x101
+    field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+    field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19385,7 +19328,7 @@
     method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19404,22 +19347,22 @@
   }
 
   public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public byte getConstellationType(int);
-    method public float getElevation(int);
+    method public float getAzimuthDegrees(int);
+    method public float getCn0DbHz(int);
+    method public int getConstellationType(int);
+    method public float getElevationDegrees(int);
     method public int getNumSatellites();
-    method public float getSnr(int);
     method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
-    field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final byte CONSTELLATION_GPS = 1; // 0x1
-    field public static final byte CONSTELLATION_QZSS = 4; // 0x4
-    field public static final byte CONSTELLATION_SBAS = 2; // 0x2
-    field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+    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 static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -19534,8 +19477,8 @@
     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 boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
     method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19560,7 +19503,7 @@
     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 unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -20992,6 +20935,7 @@
     field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
     field public static final java.lang.String KEY_STRIDE = "stride";
     field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+    field public static final java.lang.String KEY_TRACK_ID = "track-id";
     field public static final java.lang.String KEY_WIDTH = "width";
     field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -29104,6 +29048,8 @@
     ctor public Process();
     method public static final long getElapsedCpuTime();
     method public static final int getGidForName(java.lang.String);
+    method public static final long getStartElapsedRealtime();
+    method public static final long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(java.lang.String);
     method public static final boolean is64Bit();
@@ -58068,6 +58014,54 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
+  public final class Optional {
+    method public static java.util.Optional<T> empty();
+    method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public T get();
+    method public void ifPresent(java.util.function.Consumer<? super T>);
+    method public boolean isPresent();
+    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Optional<T> of(T);
+    method public static java.util.Optional<T> ofNullable(T);
+    method public T orElse(T);
+    method public T orElseGet(java.util.function.Supplier<? extends T>);
+    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalDouble {
+    method public static java.util.OptionalDouble empty();
+    method public double getAsDouble();
+    method public void ifPresent(java.util.function.DoubleConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalDouble of(double);
+    method public double orElse(double);
+    method public double orElseGet(java.util.function.DoubleSupplier);
+    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalInt {
+    method public static java.util.OptionalInt empty();
+    method public int getAsInt();
+    method public void ifPresent(java.util.function.IntConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalInt of(int);
+    method public int orElse(int);
+    method public int orElseGet(java.util.function.IntSupplier);
+    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalLong {
+    method public static java.util.OptionalLong empty();
+    method public long getAsLong();
+    method public void ifPresent(java.util.function.LongConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalLong of(long);
+    method public long orElse(long);
+    method public long orElseGet(java.util.function.LongSupplier);
+    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 1a2c854..2d5e7f6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5843,6 +5843,7 @@
 
   public class WallpaperManager {
     method public void clear() throws java.io.IOException;
+    method public void clear(int) throws java.io.IOException;
     method public void clearWallpaper();
     method public void clearWallpaper(int, int);
     method public void clearWallpaperOffsets(android.os.IBinder);
@@ -20326,168 +20327,110 @@
 
   public final class GnssClock 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 double getBiasNanos();
+    method public double getBiasUncertaintyNanos();
+    method public double getDriftNanosPerSecond();
+    method public double getDriftUncertaintyNanosPerSecond();
+    method public long getFullBiasNanos();
     method public int getHardwareClockDiscontinuityCount();
-    method public short getLeapSecond();
-    method public long getTimeInNs();
-    method public double getTimeUncertaintyInNs();
-    method public boolean hasBiasInNs();
-    method public boolean hasBiasUncertaintyInNs();
-    method public boolean hasDriftInNsPerSec();
-    method public boolean hasDriftUncertaintyInNsPerSec();
-    method public boolean hasFullBiasInNs();
+    method public int getLeapSecond();
+    method public long getTimeNanos();
+    method public double getTimeUncertaintyNanos();
+    method public boolean hasBiasNanos();
+    method public boolean hasBiasUncertaintyNanos();
+    method public boolean hasDriftNanosPerSecond();
+    method public boolean hasDriftUncertaintyNanosPerSecond();
+    method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
-    method public boolean hasTimeUncertaintyInNs();
+    method public boolean hasTimeUncertaintyNanos();
     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 resetBiasNanos();
+    method public void resetBiasUncertaintyNanos();
+    method public void resetDriftNanosPerSecond();
+    method public void resetDriftUncertaintyNanosPerSecond();
+    method public void resetFullBiasNanos();
     method public void resetLeapSecond();
-    method public void resetTimeUncertaintyInNs();
+    method public void resetTimeUncertaintyNanos();
     method public void set(android.location.GnssClock);
-    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 setBiasNanos(double);
+    method public void setBiasUncertaintyNanos(double);
+    method public void setDriftNanosPerSecond(double);
+    method public void setDriftUncertaintyNanosPerSecond(double);
+    method public void setFullBiasNanos(long);
     method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(short);
-    method public void setTimeInNs(long);
-    method public void setTimeUncertaintyInNs(double);
+    method public void setLeapSecond(int);
+    method public void setTimeNanos(long);
+    method public void setTimeUncertaintyNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
   public final class GnssMeasurement 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 double getAccumulatedDeltaRangeMeters();
+    method public int getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyMeters();
     method public long getCarrierCycles();
-    method public float getCarrierFrequencyInHz();
+    method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
     method public double getCarrierPhaseUncertainty();
-    method public double getCn0InDbHz();
-    method public double getCodePhaseInChips();
-    method public double getCodePhaseUncertaintyInChips();
-    method public byte getConstellationType();
-    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 double getPseudorangeInMeters();
-    method public double getPseudorangeRateInMetersPerSec();
-    method public double getPseudorangeRateUncertaintyInMetersPerSec();
-    method public double getPseudorangeUncertaintyInMeters();
-    method public long getReceivedSvTimeInNs();
-    method public long getReceivedSvTimeUncertaintyInNs();
+    method public double getCn0DbHz();
+    method public int getConstellationType();
+    method public int getMultipathIndicator();
+    method public double getPseudorangeRateMetersPerSecond();
+    method public double getPseudorangeRateUncertaintyMetersPerSecond();
+    method public long getReceivedSvTimeNanos();
+    method public long getReceivedSvTimeUncertaintyNanos();
     method public double getSnrInDb();
-    method public short getState();
-    method public short getSvid();
-    method public short getTimeFromLastBitInMs();
-    method public double getTimeOffsetInNs();
-    method public boolean hasAzimuthInDeg();
-    method public boolean hasAzimuthUncertaintyInDeg();
-    method public boolean hasBitNumber();
+    method public int getState();
+    method public int getSvid();
+    method public double getTimeOffsetNanos();
     method public boolean hasCarrierCycles();
-    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierFrequencyHz();
     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 resetCarrierFrequencyHz();
     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.GnssMeasurement);
-    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 setAccumulatedDeltaRangeMeters(double);
+    method public void setAccumulatedDeltaRangeState(int);
+    method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
     method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyInHz(float);
+    method public void setCarrierFrequencyHz(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 setConstellationType(byte);
-    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 setPseudorangeInMeters(double);
-    method public void setPseudorangeRateInMetersPerSec(double);
-    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
-    method public void setPseudorangeUncertaintyInMeters(double);
-    method public void setReceivedSvTimeInNs(long);
-    method public void setReceivedSvTimeUncertaintyInNs(long);
+    method public void setCn0DbHz(double);
+    method public void setConstellationType(int);
+    method public void setMultipathIndicator(int);
+    method public void setPseudorangeRateMetersPerSecond(double);
+    method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+    method public void setReceivedSvTimeNanos(long);
+    method public void setReceivedSvTimeUncertaintyNanos(long);
     method public void setSnrInDb(double);
-    method public void setState(short);
-    method public void setSvid(short);
-    method public void setTimeFromLastBitInMs(short);
-    method public void setTimeOffsetInNs(double);
-    method public void setUsedInFix(boolean);
+    method public void setState(int);
+    method public void setSvid(int);
+    method public void setTimeOffsetNanos(double);
     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 int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final int ADR_STATE_RESET = 2; // 0x2
+    field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final int ADR_STATE_VALID = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> 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 GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+    field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final int STATE_BIT_SYNC = 2; // 0x2
+    field public static final int STATE_CODE_LOCK = 1; // 0x1
+    field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final int STATE_TOW_DECODED = 8; // 0x8
+    field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -20500,7 +20443,7 @@
     method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -20517,34 +20460,34 @@
   public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
-    method public short getMessageId();
-    method public short getStatus();
-    method public short getSubmessageId();
-    method public short getSvid();
-    method public short getType();
+    method public int getMessageId();
+    method public int getStatus();
+    method public int getSubmessageId();
+    method public int getSvid();
+    method public int getType();
     method public void reset();
     method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
-    method public void setMessageId(short);
-    method public void setStatus(short);
-    method public void setSubmessageId(short);
-    method public void setSvid(short);
-    method public void setType(short);
+    method public void setMessageId(int);
+    method public void setStatus(int);
+    method public void setSubmessageId(int);
+    method public void setSvid(int);
+    method public void setType(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
-    field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
-    field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
-    field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
-    field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
-    field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
-    field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
-    field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
-    field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
-    field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
-    field public static final short 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 int STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final int STATUS_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_BDS_D1 = 1281; // 0x501
+    field public static final int TYPE_BDS_D2 = 1282; // 0x502
+    field public static final int TYPE_GAL_F = 1538; // 0x602
+    field public static final int TYPE_GAL_I = 1537; // 0x601
+    field public static final int TYPE_GLO_L1CA = 769; // 0x301
+    field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+    field public static final int TYPE_GPS_L1CA = 257; // 0x101
+    field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+    field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -20556,7 +20499,7 @@
     method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -20575,22 +20518,22 @@
   }
 
   public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public byte getConstellationType(int);
-    method public float getElevation(int);
+    method public float getAzimuthDegrees(int);
+    method public float getCn0DbHz(int);
+    method public int getConstellationType(int);
+    method public float getElevationDegrees(int);
     method public int getNumSatellites();
-    method public float getSnr(int);
     method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
-    field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final byte CONSTELLATION_GPS = 1; // 0x1
-    field public static final byte CONSTELLATION_QZSS = 4; // 0x4
-    field public static final byte CONSTELLATION_SBAS = 2; // 0x2
-    field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+    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 static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -20952,8 +20895,8 @@
     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 boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
     method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -20982,7 +20925,7 @@
     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 unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -22482,6 +22425,7 @@
     field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
     field public static final java.lang.String KEY_STRIDE = "stride";
     field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+    field public static final java.lang.String KEY_TRACK_ID = "track-id";
     field public static final java.lang.String KEY_WIDTH = "width";
     field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -26719,7 +26663,6 @@
     method public boolean reconnect();
     method public boolean removeNetwork(int);
     method public boolean saveConfiguration();
-    method public boolean setMetered(int, boolean);
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
     method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -31396,6 +31339,8 @@
     ctor public Process();
     method public static final long getElapsedCpuTime();
     method public static final int getGidForName(java.lang.String);
+    method public static final long getStartElapsedRealtime();
+    method public static final long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(java.lang.String);
     method public static final boolean is64Bit();
@@ -61171,6 +61116,54 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
+  public final class Optional {
+    method public static java.util.Optional<T> empty();
+    method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public T get();
+    method public void ifPresent(java.util.function.Consumer<? super T>);
+    method public boolean isPresent();
+    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Optional<T> of(T);
+    method public static java.util.Optional<T> ofNullable(T);
+    method public T orElse(T);
+    method public T orElseGet(java.util.function.Supplier<? extends T>);
+    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalDouble {
+    method public static java.util.OptionalDouble empty();
+    method public double getAsDouble();
+    method public void ifPresent(java.util.function.DoubleConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalDouble of(double);
+    method public double orElse(double);
+    method public double orElseGet(java.util.function.DoubleSupplier);
+    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalInt {
+    method public static java.util.OptionalInt empty();
+    method public int getAsInt();
+    method public void ifPresent(java.util.function.IntConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalInt of(int);
+    method public int orElse(int);
+    method public int orElseGet(java.util.function.IntSupplier);
+    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalLong {
+    method public static java.util.OptionalLong empty();
+    method public long getAsLong();
+    method public void ifPresent(java.util.function.LongConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalLong of(long);
+    method public long orElse(long);
+    method public long orElseGet(java.util.function.LongSupplier);
+    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 1039fed..dcb2f32 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5715,6 +5715,7 @@
 
   public class WallpaperManager {
     method public void clear() throws java.io.IOException;
+    method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
     method public void forgetLoadedWallpaper();
     method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -19165,168 +19166,110 @@
 
   public final class GnssClock 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 double getBiasNanos();
+    method public double getBiasUncertaintyNanos();
+    method public double getDriftNanosPerSecond();
+    method public double getDriftUncertaintyNanosPerSecond();
+    method public long getFullBiasNanos();
     method public int getHardwareClockDiscontinuityCount();
-    method public short getLeapSecond();
-    method public long getTimeInNs();
-    method public double getTimeUncertaintyInNs();
-    method public boolean hasBiasInNs();
-    method public boolean hasBiasUncertaintyInNs();
-    method public boolean hasDriftInNsPerSec();
-    method public boolean hasDriftUncertaintyInNsPerSec();
-    method public boolean hasFullBiasInNs();
+    method public int getLeapSecond();
+    method public long getTimeNanos();
+    method public double getTimeUncertaintyNanos();
+    method public boolean hasBiasNanos();
+    method public boolean hasBiasUncertaintyNanos();
+    method public boolean hasDriftNanosPerSecond();
+    method public boolean hasDriftUncertaintyNanosPerSecond();
+    method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
-    method public boolean hasTimeUncertaintyInNs();
+    method public boolean hasTimeUncertaintyNanos();
     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 resetBiasNanos();
+    method public void resetBiasUncertaintyNanos();
+    method public void resetDriftNanosPerSecond();
+    method public void resetDriftUncertaintyNanosPerSecond();
+    method public void resetFullBiasNanos();
     method public void resetLeapSecond();
-    method public void resetTimeUncertaintyInNs();
+    method public void resetTimeUncertaintyNanos();
     method public void set(android.location.GnssClock);
-    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 setBiasNanos(double);
+    method public void setBiasUncertaintyNanos(double);
+    method public void setDriftNanosPerSecond(double);
+    method public void setDriftUncertaintyNanosPerSecond(double);
+    method public void setFullBiasNanos(long);
     method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(short);
-    method public void setTimeInNs(long);
-    method public void setTimeUncertaintyInNs(double);
+    method public void setLeapSecond(int);
+    method public void setTimeNanos(long);
+    method public void setTimeUncertaintyNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
 
   public final class GnssMeasurement 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 double getAccumulatedDeltaRangeMeters();
+    method public int getAccumulatedDeltaRangeState();
+    method public double getAccumulatedDeltaRangeUncertaintyMeters();
     method public long getCarrierCycles();
-    method public float getCarrierFrequencyInHz();
+    method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
     method public double getCarrierPhaseUncertainty();
-    method public double getCn0InDbHz();
-    method public double getCodePhaseInChips();
-    method public double getCodePhaseUncertaintyInChips();
-    method public byte getConstellationType();
-    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 double getPseudorangeInMeters();
-    method public double getPseudorangeRateInMetersPerSec();
-    method public double getPseudorangeRateUncertaintyInMetersPerSec();
-    method public double getPseudorangeUncertaintyInMeters();
-    method public long getReceivedSvTimeInNs();
-    method public long getReceivedSvTimeUncertaintyInNs();
+    method public double getCn0DbHz();
+    method public int getConstellationType();
+    method public int getMultipathIndicator();
+    method public double getPseudorangeRateMetersPerSecond();
+    method public double getPseudorangeRateUncertaintyMetersPerSecond();
+    method public long getReceivedSvTimeNanos();
+    method public long getReceivedSvTimeUncertaintyNanos();
     method public double getSnrInDb();
-    method public short getState();
-    method public short getSvid();
-    method public short getTimeFromLastBitInMs();
-    method public double getTimeOffsetInNs();
-    method public boolean hasAzimuthInDeg();
-    method public boolean hasAzimuthUncertaintyInDeg();
-    method public boolean hasBitNumber();
+    method public int getState();
+    method public int getSvid();
+    method public double getTimeOffsetNanos();
     method public boolean hasCarrierCycles();
-    method public boolean hasCarrierFrequencyInHz();
+    method public boolean hasCarrierFrequencyHz();
     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 resetCarrierFrequencyHz();
     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.GnssMeasurement);
-    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 setAccumulatedDeltaRangeMeters(double);
+    method public void setAccumulatedDeltaRangeState(int);
+    method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
     method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyInHz(float);
+    method public void setCarrierFrequencyHz(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 setConstellationType(byte);
-    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 setPseudorangeInMeters(double);
-    method public void setPseudorangeRateInMetersPerSec(double);
-    method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
-    method public void setPseudorangeUncertaintyInMeters(double);
-    method public void setReceivedSvTimeInNs(long);
-    method public void setReceivedSvTimeUncertaintyInNs(long);
+    method public void setCn0DbHz(double);
+    method public void setConstellationType(int);
+    method public void setMultipathIndicator(int);
+    method public void setPseudorangeRateMetersPerSecond(double);
+    method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+    method public void setReceivedSvTimeNanos(long);
+    method public void setReceivedSvTimeUncertaintyNanos(long);
     method public void setSnrInDb(double);
-    method public void setState(short);
-    method public void setSvid(short);
-    method public void setTimeFromLastBitInMs(short);
-    method public void setTimeOffsetInNs(double);
-    method public void setUsedInFix(boolean);
+    method public void setState(int);
+    method public void setSvid(int);
+    method public void setTimeOffsetNanos(double);
     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 int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+    field public static final int ADR_STATE_RESET = 2; // 0x2
+    field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+    field public static final int ADR_STATE_VALID = 1; // 0x1
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> 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 GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+    field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+    field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+    field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+    field public static final int STATE_BIT_SYNC = 2; // 0x2
+    field public static final int STATE_CODE_LOCK = 1; // 0x1
+    field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+    field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+    field public static final int STATE_TOW_DECODED = 8; // 0x8
+    field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19339,7 +19282,7 @@
     method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19356,34 +19299,34 @@
   public final class GnssNavigationMessage implements android.os.Parcelable {
     method public int describeContents();
     method public byte[] getData();
-    method public short getMessageId();
-    method public short getStatus();
-    method public short getSubmessageId();
-    method public short getSvid();
-    method public short getType();
+    method public int getMessageId();
+    method public int getStatus();
+    method public int getSubmessageId();
+    method public int getSvid();
+    method public int getType();
     method public void reset();
     method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
-    method public void setMessageId(short);
-    method public void setStatus(short);
-    method public void setSubmessageId(short);
-    method public void setSvid(short);
-    method public void setType(short);
+    method public void setMessageId(int);
+    method public void setStatus(int);
+    method public void setSubmessageId(int);
+    method public void setSvid(int);
+    method public void setType(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
-    field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
-    field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
-    field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
-    field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
-    field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
-    field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
-    field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
-    field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
-    field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
-    field public static final short 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 int STATUS_PARITY_PASSED = 1; // 0x1
+    field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+    field public static final int STATUS_UNKNOWN = 0; // 0x0
+    field public static final int TYPE_BDS_D1 = 1281; // 0x501
+    field public static final int TYPE_BDS_D2 = 1282; // 0x502
+    field public static final int TYPE_GAL_F = 1538; // 0x602
+    field public static final int TYPE_GAL_I = 1537; // 0x601
+    field public static final int TYPE_GLO_L1CA = 769; // 0x301
+    field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+    field public static final int TYPE_GPS_L1CA = 257; // 0x101
+    field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+    field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+    field public static final int TYPE_UNKNOWN = 0; // 0x0
   }
 
   public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19395,7 +19338,7 @@
     method public android.location.GnssNavigationMessage getNavigationMessage();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
-    field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+    field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
     field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
     field public static final int STATUS_READY = 1; // 0x1
   }
@@ -19414,22 +19357,22 @@
   }
 
   public final class GnssStatus {
-    method public float getAzimuth(int);
-    method public byte getConstellationType(int);
-    method public float getElevation(int);
+    method public float getAzimuthDegrees(int);
+    method public float getCn0DbHz(int);
+    method public int getConstellationType(int);
+    method public float getElevationDegrees(int);
     method public int getNumSatellites();
-    method public float getSnr(int);
     method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
-    field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
-    field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
-    field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
-    field public static final byte CONSTELLATION_GPS = 1; // 0x1
-    field public static final byte CONSTELLATION_QZSS = 4; // 0x4
-    field public static final byte CONSTELLATION_SBAS = 2; // 0x2
-    field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+    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 static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -19545,8 +19488,8 @@
     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 boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
-    method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
     method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19571,7 +19514,7 @@
     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 unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+    method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
     method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
     field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -21003,6 +20946,7 @@
     field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
     field public static final java.lang.String KEY_STRIDE = "stride";
     field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+    field public static final java.lang.String KEY_TRACK_ID = "track-id";
     field public static final java.lang.String KEY_WIDTH = "width";
     field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
     field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -29115,6 +29059,8 @@
     ctor public Process();
     method public static final long getElapsedCpuTime();
     method public static final int getGidForName(java.lang.String);
+    method public static final long getStartElapsedRealtime();
+    method public static final long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(java.lang.String);
     method public static final boolean is64Bit();
@@ -58087,6 +58033,54 @@
     method public abstract void update(java.util.Observable, java.lang.Object);
   }
 
+  public final class Optional {
+    method public static java.util.Optional<T> empty();
+    method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+    method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+    method public T get();
+    method public void ifPresent(java.util.function.Consumer<? super T>);
+    method public boolean isPresent();
+    method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+    method public static java.util.Optional<T> of(T);
+    method public static java.util.Optional<T> ofNullable(T);
+    method public T orElse(T);
+    method public T orElseGet(java.util.function.Supplier<? extends T>);
+    method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalDouble {
+    method public static java.util.OptionalDouble empty();
+    method public double getAsDouble();
+    method public void ifPresent(java.util.function.DoubleConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalDouble of(double);
+    method public double orElse(double);
+    method public double orElseGet(java.util.function.DoubleSupplier);
+    method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalInt {
+    method public static java.util.OptionalInt empty();
+    method public int getAsInt();
+    method public void ifPresent(java.util.function.IntConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalInt of(int);
+    method public int orElse(int);
+    method public int orElseGet(java.util.function.IntSupplier);
+    method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
+  public final class OptionalLong {
+    method public static java.util.OptionalLong empty();
+    method public long getAsLong();
+    method public void ifPresent(java.util.function.LongConsumer);
+    method public boolean isPresent();
+    method public static java.util.OptionalLong of(long);
+    method public long orElse(long);
+    method public long orElseGet(java.util.function.LongSupplier);
+    method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index be89b20..b87e9fa2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6599,7 +6599,8 @@
         if (isAppDebuggable || isDlwarningEnabled) {
             String dlwarning = getDlWarning();
             if (dlwarning != null) {
-                String appName = getString(mApplication.getApplicationInfo().labelRes);
+                String appName = getApplicationInfo().loadLabel(getPackageManager())
+                        .toString();
                 String warning = "Detected problems with app native libraries\n" +
                                  "(please consult log for detail):\n" + dlwarning;
                 if (isAppDebuggable) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1e95c98..2415ce1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4909,6 +4909,9 @@
             DdmVmInternal.enableRecentAllocations(true);
         }
 
+        // Note when this process has started.
+        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+
         mBoundApplication = data;
         mConfiguration = new Configuration(data.config);
         mCompatConfiguration = new Configuration(data.config);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 53cc9ca..c841111 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1093,6 +1093,14 @@
     }
 
     @Override
+    public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+            int badgeDensity) {
+        Drawable badgeDrawable = getDrawableForDensity(
+            com.android.internal.R.drawable.ic_corp_badge, badgeDensity);
+        return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
+    }
+
+    @Override
     public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
         final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
         if (badgeResId == 0) {
@@ -1114,24 +1122,27 @@
 
     @Override
     public Drawable getUserBadgeForDensity(UserHandle user, int density) {
-        return getManagedProfileIconForDensity(user, density,
-                com.android.internal.R.drawable.ic_corp_badge);
+        return getManagedProfileIconForDensity(user, com.android.internal.R.drawable.ic_corp_badge,
+                density);
     }
 
     @Override
     public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
-        return getManagedProfileIconForDensity(user, density,
-                com.android.internal.R.drawable.ic_corp_badge_no_background);
+        return getManagedProfileIconForDensity(user,
+                com.android.internal.R.drawable.ic_corp_badge_no_background, density);
     }
 
-    private Drawable getManagedProfileIconForDensity(UserHandle user, int density,
-            int drawableId) {
+    private Drawable getDrawableForDensity(int drawableId, int density) {
+        if (density <= 0) {
+            density = mContext.getResources().getDisplayMetrics().densityDpi;
+        }
+        return Resources.getSystem().getDrawableForDensity(drawableId, density);
+    }
+
+    private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
         UserInfo userInfo = getUserIfProfile(user.getIdentifier());
         if (userInfo != null && userInfo.isManagedProfile()) {
-            if (density <= 0) {
-                density = mContext.getResources().getDisplayMetrics().densityDpi;
-            }
-            return Resources.getSystem().getDrawableForDensity(drawableId, density);
+            return getDrawableForDensity(drawableId, density);
         }
         return null;
     }
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 4d8d96b0..6bc03f7 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1433,6 +1433,25 @@
     }
 
     /**
+     * Remove one or more currently set wallpapers, reverting to the system default
+     * display for each one.  If {@link #FLAG_SET_SYSTEM} is set in the {@code which}
+     * parameter, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} will be broadcast
+     * upon success.
+     *
+     * @param which A bitwise combination of {@link #FLAG_SET_SYSTEM} or
+     *   {@link #FLAG_SET_LOCK}
+     * @throws IOException If an error occurs reverting to the built-in wallpaper.
+     */
+    public void clear(int which) throws IOException {
+        if ((which & FLAG_SET_SYSTEM) != 0) {
+            clear();
+        }
+        if ((which & FLAG_SET_LOCK) != 0) {
+            clearWallpaper(FLAG_SET_LOCK, mContext.getUserId());
+        }
+    }
+
+    /**
      * Open stream representing the default static image wallpaper.
      *
      * @hide
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c2d1bdd..27056a3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4339,6 +4339,32 @@
             throws NameNotFoundException;
 
     /**
+     * Returns a managed-user-style badged copy of the given drawable allowing the user to
+     * distinguish it from the original drawable.
+     * The caller can specify the location in the bounds of the drawable to be
+     * badged where the badge should be applied as well as the density of the
+     * badge to be used.
+     * <p>
+     * If the original drawable is a BitmapDrawable and the backing bitmap is
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
+     * is performed in place and the original drawable is returned.
+     * </p>
+     *
+     * @param drawable The drawable to badge.
+     * @param badgeLocation Where in the bounds of the badged drawable to place
+     *         the badge. If it's {@code null}, the badge is applied on top of the entire
+     *         drawable being badged.
+     * @param badgeDensity The optional desired density for the badge as per
+     *         {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
+     *         the density of the display is used.
+     * @return A drawable that combines the original drawable and a badge as
+     *         determined by the system.
+     * @hide
+     */
+    public abstract Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+        int badgeDensity);
+
+    /**
      * If the target user is a managed profile of the calling user or if the
      * target user is the caller and is itself a managed profile, then this
      * returns a badged copy of the given icon to be able to distinguish it from
@@ -4367,17 +4393,17 @@
      * badge to be used.
      * <p>
      * If the original drawable is a BitmapDrawable and the backing bitmap is
-     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
      * is performed in place and the original drawable is returned.
      * </p>
      *
      * @param drawable The drawable to badge.
      * @param user The target user.
      * @param badgeLocation Where in the bounds of the badged drawable to place
-     *         the badge. If not provided, the badge is applied on top of the entire
+     *         the badge. If it's {@code null}, the badge is applied on top of the entire
      *         drawable being badged.
      * @param badgeDensity The optional desired density for the badge as per
-     *         {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+     *         {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
      *         the density of the display is used.
      * @return A drawable that combines the original drawable and a badge as
      *         determined by the system.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ce6ddfd..0588a9d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4690,9 +4690,6 @@
         // preferred up order.
         public int mPreferredOrder = 0;
 
-        // For use by package manager to keep track of where it needs to do dexopt.
-        public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
-
         // For use by package manager to keep track of when a package was last used.
         public long mLastPackageUsageTimeInMills;
 
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index cc2b764..b635088 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -689,12 +689,19 @@
                 return false;
             if (triggerInData != other.triggerInData)
                 return false;
-            if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
-                return false;
-            if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
-                return false;
-            if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
-                return false;
+            if (captureFormat == null) {
+                if (other.captureFormat != null)
+                    return false;
+            } else {
+                if (other.captureFormat == null)
+                    return false;
+                if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
+                    return false;
+                if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
+                    return false;
+                if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
+                    return false;
+            }
             return true;
         }
 
@@ -1002,10 +1009,10 @@
                 int encoding = in.readInt();
                 int channelMask = in.readInt();
                 captureFormat = (new AudioFormat.Builder())
-                        .setChannelMask(channelMask)
-                        .setEncoding(encoding)
-                        .setSampleRate(sampleRate)
-                        .build();
+                    .setChannelMask(channelMask)
+                    .setEncoding(encoding)
+                    .setSampleRate(sampleRate)
+                    .build();
             }
             byte[] data = in.readBlob();
             KeyphraseRecognitionExtra[] keyphraseExtras =
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 20c2168..9e360e1 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -200,6 +200,14 @@
      */
     public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
 
+    /**
+     * Sent by ConnectivityService to the NetworkAgent to install an APF program in the network
+     * chipset for use to filter packets.
+     *
+     * obj = byte[] containing the APF program bytecode.
+     */
+    public static final int CMD_PUSH_APF_PROGRAM = BASE + 16;
+
     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
             NetworkCapabilities nc, LinkProperties lp, int score) {
         this(looper, context, logTag, ni, nc, lp, score, null);
@@ -319,6 +327,10 @@
                 preventAutomaticReconnect();
                 break;
             }
+            case CMD_PUSH_APF_PROGRAM: {
+                installPacketFilter((byte[]) msg.obj);
+                break;
+            }
         }
     }
 
@@ -494,6 +506,15 @@
     protected void preventAutomaticReconnect() {
     }
 
+    /**
+     * Install a packet filter.
+     * @param filter an APF program to filter incoming packets.
+     * @return {@code true} if filter successfully installed, {@code false} otherwise.
+     */
+    protected boolean installPacketFilter(byte[] filter) {
+        return false;
+    }
+
     protected void log(String s) {
         Log.d(LOG_TAG, "NetworkAgent: " + s);
     }
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 5511a24..748699e 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -56,6 +56,22 @@
      */
     public String subscriberId;
 
+    /**
+     * Version of APF instruction set supported for packet filtering. 0 indicates no support for
+     * packet filtering using APF programs.
+     */
+    public int apfVersionSupported;
+
+    /**
+     * Maximum size of APF program allowed.
+     */
+    public int maximumApfProgramSize;
+
+    /**
+     * Format of packets passed to APF filter. Should be one of ARPHRD_*
+     */
+    public int apfPacketFormat;
+
     public NetworkMisc() {
     }
 
@@ -65,6 +81,9 @@
             explicitlySelected = nm.explicitlySelected;
             acceptUnvalidated = nm.acceptUnvalidated;
             subscriberId = nm.subscriberId;
+            apfVersionSupported = nm.apfVersionSupported;
+            maximumApfProgramSize = nm.maximumApfProgramSize;
+            apfPacketFormat = nm.apfPacketFormat;
         }
     }
 
@@ -79,6 +98,9 @@
         out.writeInt(explicitlySelected ? 1 : 0);
         out.writeInt(acceptUnvalidated ? 1 : 0);
         out.writeString(subscriberId);
+        out.writeInt(apfVersionSupported);
+        out.writeInt(maximumApfProgramSize);
+        out.writeInt(apfPacketFormat);
     }
 
     public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -89,6 +111,9 @@
             networkMisc.explicitlySelected = in.readInt() != 0;
             networkMisc.acceptUnvalidated = in.readInt() != 0;
             networkMisc.subscriberId = in.readString();
+            networkMisc.apfVersionSupported = in.readInt();
+            networkMisc.maximumApfProgramSize = in.readInt();
+            networkMisc.apfPacketFormat = in.readInt();
             return networkMisc;
         }
 
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index c6d919f..555032d 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -62,6 +62,13 @@
     public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
 
     /**
+     * Attaches a socket filter that accepts ICMP6 router advertisement packets to the given socket.
+     * @param fd the socket's {@link FileDescriptor}.
+     * @param packetType the hardware address type, one of ARPHRD_*.
+     */
+    public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;
+
+    /**
      * Binds the current process to the network designated by {@code netId}.  All sockets created
      * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
      * {@link Network#getSocketFactory}) will be bound to this network.  Note that if this
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9984755..8fd3b0c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -383,6 +383,9 @@
     public static final int SIGNAL_KILL = 9;
     public static final int SIGNAL_USR1 = 10;
 
+    private static long sStartElapsedRealtime;
+    private static long sStartUptimeMillis;
+
     /**
      * State for communicating with the zygote process.
      *
@@ -772,6 +775,26 @@
     public static final native long getElapsedCpuTime();
 
     /**
+     * Return the {@link SystemClock#elapsedRealtime()} at which this process was started.
+     */
+    public static final long getStartElapsedRealtime() {
+        return sStartElapsedRealtime;
+    }
+
+    /**
+     * Return the {@link SystemClock#uptimeMillis()} at which this process was started.
+     */
+    public static final long getStartUptimeMillis() {
+        return sStartUptimeMillis;
+    }
+
+    /** @hide */
+    public static final void setStartTimes(long elapsedRealtime, long uptimeMillis) {
+        sStartElapsedRealtime = elapsedRealtime;
+        sStartUptimeMillis = uptimeMillis;
+    }
+
+    /**
      * Returns true if the current process is a 64-bit runtime.
      */
     public static final boolean is64Bit() {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 6e9e456..7223dfb 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1658,7 +1658,7 @@
      * android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
      * <p>
      * If the original drawable is a BitmapDrawable and the backing bitmap is
-     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
      * is performed in place and the original drawable is returned.
      * </p>
      *
@@ -1681,17 +1681,17 @@
      * badge to be used.
      * <p>
      * If the original drawable is a BitmapDrawable and the backing bitmap is
-     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+     * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
      * is performed in place and the original drawable is returned.
      * </p>
      *
      * @param badgedDrawable The drawable to badge.
      * @param user The target user.
      * @param badgeLocation Where in the bounds of the badged drawable to place
-     *         the badge. If not provided, the badge is applied on top of the entire
+     *         the badge. If it's {@code null}, the badge is applied on top of the entire
      *         drawable being badged.
      * @param badgeDensity The optional desired density for the badge as per
-     *         {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+     *         {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
      *         the density of the display is used.
      * @return A drawable that combines the original drawable and a badge as
      *         determined by the system.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 3788c74..03a1ca6 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -568,6 +568,22 @@
          * @hide
          */
         public static final int FLAG_HAS_SETTINGS = 1 << 17;
+
+        /**
+         * Flag indicating that this root is on removable SD card storage.
+         *
+         * @see #COLUMN_FLAGS
+         * @hide
+         */
+        public static final int FLAG_REMOVABLE_SD = 1 << 18;
+
+        /**
+         * Flag indicating that this root is on removable USB storage.
+         *
+         * @see #COLUMN_FLAGS
+         * @hide
+         */
+        public static final int FLAG_REMOVABLE_USB = 1 << 19;
     }
 
     /**
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index e79dfca..3564e11 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.graphics.Paint;
 import android.icu.lang.UCharacter;
 import android.icu.lang.UProperty;
 import android.view.KeyEvent;
@@ -25,6 +26,8 @@
 import android.text.style.ReplacementSpan;
 import android.widget.TextView;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.text.BreakIterator;
 import java.util.Arrays;
 import java.util.Collections;
@@ -45,6 +48,11 @@
         implements KeyListener {
     /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
 
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    static Paint sCachedPaint = null;
+
     /**
      * Performs the action that happens when you press the {@link KeyEvent#KEYCODE_DEL} key in
      * a {@link TextView}.  If there is a selection, deletes the selection; otherwise,
@@ -258,20 +266,15 @@
     }
 
     // Returns the end offset to be deleted by a forward delete key from the given offset.
-    private static int getOffsetForForwardDeleteKey(CharSequence text, int offset) {
+    private static int getOffsetForForwardDeleteKey(CharSequence text, int offset, Paint paint) {
         final int len = text.length();
 
         if (offset >= len - 1) {
             return len;
         }
 
-        int codePoint = Character.codePointAt(text, offset);
-        offset += Character.charCount(codePoint);
-        if (offset == len) {
-            return len;
-        }
-
-        // TODO: Handle emoji, combining chars, etc.
+        offset = paint.getTextRunCursor(text, offset, len, Paint.DIRECTION_LTR /* not used */,
+                offset, Paint.CURSOR_AFTER);
 
         return adjustReplacementSpan(text, offset, false /* move to the end */);
     }
@@ -311,7 +314,18 @@
         final int start = Selection.getSelectionEnd(content);
         final int end;
         if (isForwardDelete) {
-            end = getOffsetForForwardDeleteKey(content, start);
+            final Paint paint;
+            if (view instanceof TextView) {
+                paint = ((TextView)view).getPaint();
+            } else {
+                synchronized (mLock) {
+                    if (sCachedPaint == null) {
+                        sCachedPaint = new Paint();
+                    }
+                    paint = sCachedPaint;
+                }
+            }
+            end = getOffsetForForwardDeleteKey(content, start, paint);
         } else {
             end = getOffsetForBackspaceKey(content, start);
         }
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index fbd9924..bd376ea 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -224,7 +224,7 @@
         }
 
         if ((mask & EMAIL_ADDRESSES) != 0) {
-            gatherLinks(links, text, Patterns.EMAIL_ADDRESS,
+            gatherLinks(links, text, Patterns.AUTOLINK_EMAIL_ADDRESS,
                 new String[] { "mailto:" },
                 null, null);
         }
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 9f2bcfd..9ed4850 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -394,6 +394,36 @@
     public static final Pattern AUTOLINK_WEB_URL = Pattern.compile(
             "(" + WEB_URL_WITH_PROTOCOL + "|" + WEB_URL_WITHOUT_PROTOCOL + ")");
 
+    /**
+     * Regular expression for valid email characters. Does not include some of the valid characters
+     * defined in RFC5321: #&~!^`{}/=$*?|
+     */
+    private static final String EMAIL_CHAR = LABEL_CHAR + "\\+\\-_%'";
+
+    /**
+     * Regular expression for local part of an email address. RFC5321 section 4.5.3.1.1 limits
+     * the local part to be at most 64 octets.
+     */
+    private static final String EMAIL_ADDRESS_LOCAL_PART =
+            "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{1,62}[" + EMAIL_CHAR + "])?";
+
+    /**
+     * Regular expression for the domain part of an email address. RFC5321 section 4.5.3.1.2 limits
+     * the domain to be at most 255 octets.
+     */
+    private static final String EMAIL_ADDRESS_DOMAIN =
+            "(?=.{1,255}(?:\\s|$|^))" + HOST_NAME;
+
+    /**
+     * Regular expression pattern to match email addresses. It excludes double quoted local parts
+     * and the special characters #&~!^`{}/=$*?| that are included in RFC5321.
+     * @hide
+     */
+    public static final Pattern AUTOLINK_EMAIL_ADDRESS = Pattern.compile("(" + WORD_BOUNDARY +
+            "(?:" + EMAIL_ADDRESS_LOCAL_PART + "@" + EMAIL_ADDRESS_DOMAIN + ")" +
+            WORD_BOUNDARY + ")"
+    );
+
     public static final Pattern EMAIL_ADDRESS
         = Pattern.compile(
             "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 1d242d3..434e3eb 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -117,6 +117,16 @@
         Selection.extendSelection(getText(), index);
     }
 
+    /**
+     * Causes words in the text that are longer than the view's width to be ellipsized instead of
+     * broken in the middle. {@link TextUtils.TruncateAt#MARQUEE
+     * TextUtils.TruncateAt#MARQUEE} is not supported.
+     *
+     * @param ellipsis Type of ellipsis to be applied.
+     * @throws IllegalArgumentException When the value of <code>ellipsis</code> parameter is
+     *      {@link TextUtils.TruncateAt#MARQUEE}.
+     * @see TextView#setEllipsize(TextUtils.TruncateAt)
+     */
     @Override
     public void setEllipsize(TextUtils.TruncateAt ellipsis) {
         if (ellipsis == TextUtils.TruncateAt.MARQUEE) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f19bf02..18f1ae5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -20,6 +20,7 @@
 import android.R;
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
+import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
@@ -5835,8 +5836,7 @@
 
         final int layoutDirection = getLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-        if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
-                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+        if (isMarqueeFadeEnabled()) {
             if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
                     (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
                 final int width = mRight - mLeft;
@@ -7888,7 +7888,7 @@
     }
 
     /**
-     * Causes words in the text that are longer than the view is wide
+     * Causes words in the text that are longer than the view's width
      * to be ellipsized instead of broken in the middle.  You may also
      * want to {@link #setSingleLine} or {@link #setHorizontallyScrolling}
      * to constrain the text to a single line.  Use <code>null</code>
@@ -8616,78 +8616,59 @@
 
     @Override
     protected float getLeftFadingEdgeStrength() {
-        if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
-                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
-            if (mMarquee != null && !mMarquee.isStopped()) {
-                final Marquee marquee = mMarquee;
-                if (marquee.shouldDrawLeftFade()) {
-                    final float scroll = marquee.getScroll();
-                    return scroll / getHorizontalFadingEdgeLength();
-                } else {
-                    return 0.0f;
-                }
-            } else if (getLineCount() == 1) {
-                final int layoutDirection = getLayoutDirection();
-                final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-                    case Gravity.LEFT:
-                        return 0.0f;
-                    case Gravity.RIGHT:
-                        return (mLayout.getLineRight(0) - (mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight() -
-                                mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
-                    case Gravity.CENTER_HORIZONTAL:
-                    case Gravity.FILL_HORIZONTAL:
-                        final int textDirection = mLayout.getParagraphDirection(0);
-                        if (textDirection == Layout.DIR_LEFT_TO_RIGHT) {
-                            return 0.0f;
-                        } else {
-                            return (mLayout.getLineRight(0) - (mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight() -
-                                mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
-                        }
-                }
+        if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+            final Marquee marquee = mMarquee;
+            if (marquee.shouldDrawLeftFade()) {
+                return getHorizontalFadingEdgeStrength(marquee.getScroll(), 0.0f);
+            } else {
+                return 0.0f;
             }
+        } else if (getLineCount() == 1) {
+            final float lineLeft = getLayout().getLineLeft(0);
+            if(lineLeft > mScrollX) return 0.0f;
+            return getHorizontalFadingEdgeStrength(mScrollX, lineLeft);
         }
         return super.getLeftFadingEdgeStrength();
     }
 
     @Override
     protected float getRightFadingEdgeStrength() {
-        if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
-                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
-            if (mMarquee != null && !mMarquee.isStopped()) {
-                final Marquee marquee = mMarquee;
-                final float maxFadeScroll = marquee.getMaxFadeScroll();
-                final float scroll = marquee.getScroll();
-                return (maxFadeScroll - scroll) / getHorizontalFadingEdgeLength();
-            } else if (getLineCount() == 1) {
-                final int layoutDirection = getLayoutDirection();
-                final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-                    case Gravity.LEFT:
-                        final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
-                                getCompoundPaddingRight();
-                        final float lineWidth = mLayout.getLineWidth(0);
-                        return (lineWidth - textWidth) / getHorizontalFadingEdgeLength();
-                    case Gravity.RIGHT:
-                        return 0.0f;
-                    case Gravity.CENTER_HORIZONTAL:
-                    case Gravity.FILL_HORIZONTAL:
-                        final int textDirection = mLayout.getParagraphDirection(0);
-                        if (textDirection == Layout.DIR_RIGHT_TO_LEFT) {
-                            return 0.0f;
-                        } else {
-                            return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight())) /
-                                getHorizontalFadingEdgeLength();
-                        }
-                }
-            }
+        if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+            final Marquee marquee = mMarquee;
+            return getHorizontalFadingEdgeStrength(marquee.getMaxFadeScroll(), marquee.getScroll());
+        } else if (getLineCount() == 1) {
+            final float rightEdge = mScrollX + (getWidth() - getCompoundPaddingLeft() -
+                    getCompoundPaddingRight());
+            final float lineRight = getLayout().getLineRight(0);
+            if(lineRight < rightEdge) return 0.0f;
+            return getHorizontalFadingEdgeStrength(rightEdge, lineRight);
         }
         return super.getRightFadingEdgeStrength();
     }
 
+    /**
+     * Calculates the fading edge strength as the ratio of the distance between two
+     * horizontal positions to {@link View#getHorizontalFadingEdgeLength()}. Uses the absolute
+     * value for the distance calculation.
+     *
+     * @param position1 A horizontal position.
+     * @param position2 A horizontal position.
+     * @return Fading edge strength between [0.0f, 1.0f].
+     */
+    @FloatRange(from=0.0, to=1.0)
+    private final float getHorizontalFadingEdgeStrength(float position1, float position2) {
+        final int horizontalFadingEdgeLength = getHorizontalFadingEdgeLength();
+        if(horizontalFadingEdgeLength == 0) return 0.0f;
+        final float diff = Math.abs(position1 - position2);
+        if(diff > horizontalFadingEdgeLength) return 1.0f;
+        return diff / horizontalFadingEdgeLength;
+    }
+
+    private final boolean isMarqueeFadeEnabled() {
+        return mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+                mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+    }
+
     @Override
     protected int computeHorizontalScrollRange() {
         if (mLayout != null) {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 4e48e45..f04bcf2 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -547,23 +547,25 @@
         LocaleUtils.filterByLanguage(keyboardSubtypes, sSubtypeToLocale, systemLocales,
                 applicableSubtypes);
 
-        boolean hasAsciiCapableKeyboard = false;
-        final int numApplicationSubtypes = applicableSubtypes.size();
-        for (int i = 0; i < numApplicationSubtypes; ++i) {
-            final InputMethodSubtype subtype = applicableSubtypes.get(i);
-            if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
-                hasAsciiCapableKeyboard = true;
-                break;
+        if (!applicableSubtypes.isEmpty()) {
+            boolean hasAsciiCapableKeyboard = false;
+            final int numApplicationSubtypes = applicableSubtypes.size();
+            for (int i = 0; i < numApplicationSubtypes; ++i) {
+                final InputMethodSubtype subtype = applicableSubtypes.get(i);
+                if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
+                    hasAsciiCapableKeyboard = true;
+                    break;
+                }
             }
-        }
-        if (!hasAsciiCapableKeyboard) {
-            final int numKeyboardSubtypes = keyboardSubtypes.size();
-            for (int i = 0; i < numKeyboardSubtypes; ++i) {
-                final InputMethodSubtype subtype = keyboardSubtypes.get(i);
-                final String mode = subtype.getMode();
-                if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
-                        TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
-                    applicableSubtypes.add(subtype);
+            if (!hasAsciiCapableKeyboard) {
+                final int numKeyboardSubtypes = keyboardSubtypes.size();
+                for (int i = 0; i < numKeyboardSubtypes; ++i) {
+                    final InputMethodSubtype subtype = keyboardSubtypes.get(i);
+                    final String mode = subtype.getMode();
+                    if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
+                            TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
+                        applicableSubtypes.add(subtype);
+                    }
                 }
             }
         }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index eb509c2..3abea26 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -499,11 +499,11 @@
 
         try {
             for (String classPathElement : classPathElements) {
+                // System server is fully AOTed and never profiled
+                // for profile guided compilation.
                 final int dexoptNeeded = DexFile.getDexOptNeeded(
-                        classPathElement, "*", instructionSet, false /* defer */);
+                        classPathElement, instructionSet, DexFile.COMPILATION_TYPE_FULL);
                 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                    // System server is fully AOTed and never profiled
-                    // for profile guided compilation.
                     installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
                             dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
                             false /*useProfiles*/);
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index defb88a..880a79c 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,10 +26,13 @@
 #include <net/if.h>
 #include <linux/filter.h>
 #include <linux/if.h>
+#include <linux/if_arp.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 #include <net/if_ether.h>
+#include <netinet/icmp6.h>
 #include <netinet/ip.h>
+#include <netinet/ip6.h>
 #include <netinet/udp.h>
 #include <cutils/properties.h>
 
@@ -64,10 +67,9 @@
 
 static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
 {
-    int fd = jniGetFDFromFileDescriptor(env, javaFd);
     uint32_t ip_offset = sizeof(ether_header);
     uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
-    uint32_t flags_offset = ip_offset +  offsetof(iphdr, frag_off);
+    uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
     uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest);
     struct sock_filter filter_code[] = {
         // Check the protocol is UDP.
@@ -94,6 +96,45 @@
         filter_code,
     };
 
+    int fd = jniGetFDFromFileDescriptor(env, javaFd);
+    if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
+        jniThrowExceptionFmt(env, "java/net/SocketException",
+                "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
+    }
+}
+
+static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject javaFd,
+        jint hardwareAddressType)
+{
+    if (hardwareAddressType != ARPHRD_ETHER) {
+        jniThrowExceptionFmt(env, "java/net/SocketException",
+                "attachRaFilter only supports ARPHRD_ETHER");
+        return;
+    }
+
+    uint32_t ipv6_offset = sizeof(ether_header);
+    uint32_t ipv6_next_header_offset = ipv6_offset + offsetof(ip6_hdr, ip6_nxt);
+    uint32_t icmp6_offset = ipv6_offset + sizeof(ip6_hdr);
+    uint32_t icmp6_type_offset = icmp6_offset + offsetof(icmp6_hdr, icmp6_type);
+    struct sock_filter filter_code[] = {
+        // Check IPv6 Next Header is ICMPv6.
+        BPF_STMT(BPF_LD  | BPF_B   | BPF_ABS,  ipv6_next_header_offset),
+        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    IPPROTO_ICMPV6, 0, 3),
+
+        // Check ICMPv6 type is Router Advertisement.
+        BPF_STMT(BPF_LD  | BPF_B   | BPF_ABS,  icmp6_type_offset),
+        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    ND_ROUTER_ADVERT, 0, 1),
+
+        // Accept or reject.
+        BPF_STMT(BPF_RET | BPF_K,              0xffff),
+        BPF_STMT(BPF_RET | BPF_K,              0)
+    };
+    struct sock_fprog filter = {
+        sizeof(filter_code) / sizeof(filter_code[0]),
+        filter_code,
+    };
+
+    int fd = jniGetFDFromFileDescriptor(env, javaFd);
     if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
         jniThrowExceptionFmt(env, "java/net/SocketException",
                 "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
@@ -148,6 +189,7 @@
     { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
     { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
     { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
+    { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
 };
 
 int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index be28449..9a2a6eb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -443,6 +443,9 @@
     <!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
     <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">true</bool>
 
+    <!-- Integer size limit, in KB, for a single WifiLogger ringbuffer -->
+    <integer translatable="false" name="config_wifi_logger_ring_buffer_size_limit_kb">32</integer>
+
     <!-- Boolean indicating whether or not wifi should turn off when emergency call is made -->
     <bool translatable="false" name="config_wifi_turn_off_during_emergency_call">false</bool>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 786b3cc..11f42ec 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -298,6 +298,7 @@
   <java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
   <java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
   <java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
+  <java-symbol type="integer" name="config_wifi_logger_ring_buffer_size_limit_kb" />
   <java-symbol type="bool" name="config_wifi_turn_off_during_emergency_call" />
   <java-symbol type="bool" name="config_supportMicNearUltrasound" />
   <java-symbol type="bool" name="config_supportSpeakerNearUltrasound" />
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
new file mode 100644
index 0000000..da17045
--- /dev/null
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -0,0 +1,472 @@
+/*
+ * 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.text.method;
+
+import android.app.Activity;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.InputType;
+import android.text.method.BaseKeyListener;
+import android.text.method.KeyListenerTestCase;
+import android.view.KeyEvent;
+import android.widget.EditText;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test forward delete key handling of  {@link android.text.method.BaseKeyListener}.
+ *
+ * TODO: Move some of test cases to the CTS.
+ */
+public class ForwardDeleteTest extends KeyListenerTestCase {
+    private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
+        public int getInputType() {
+            return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+        }
+    };
+
+    // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
+    // Then update the state to the result of TextView.
+    private void forwardDelete(final EditorState state, int modifiers) {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.setText(state.mText, BufferType.EDITABLE);
+                mTextView.setKeyListener(mKeyListener);
+                mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mTextView.hasWindowFocus());
+
+        final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        state.mText = mTextView.getText();
+        state.mSelectionStart = mTextView.getSelectionStart();
+        state.mSelectionEnd = mTextView.getSelectionEnd();
+    }
+
+    @SmallTest
+    public void testSurrogatePairs() {
+        EditorState state = new EditorState();
+
+        // U+1F441 is EYE
+        state.setByString("| U+1F441");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+1F5E8 is LEFT SPEECH BUBBLE
+        state.setByString("| U+1F441 U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // TODO: introduce edge cases.
+    }
+
+    @SmallTest
+    public void testReplacementSpan() {
+        EditorState state = new EditorState();
+
+        state.setByString("| 'abc' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'bc' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'c' ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| ( 'de' ) 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("'abc' [ ( 'de' ) ] 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' | 'fg'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' | 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' |");
+        forwardDelete(state, 0);
+        state.assertEquals("'abc' |");
+
+        state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' | 'g'");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' |");
+        forwardDelete(state, 0);
+        state.assertEquals("'ab' |");
+
+        // TODO: introduce edge cases.
+    }
+
+    @SmallTest
+    public void testCombiningEnclosingKeycaps() {
+        EditorState state = new EditorState();
+
+        // U+20E3 is COMBINING ENCLOSING KEYCAP.
+        state.setByString("| '1' U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // multiple COMBINING ENCLOSING KEYCAP
+        state.setByString("| '1' U+20E3 U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+20E3 U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testVariationSelector() {
+        EditorState state = new EditorState();
+
+        // U+FE0F is VARIATION SELECTOR-16.
+        state.setByString("| '#' U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // U+E0100 is VARIATION SELECTOR-17.
+        state.setByString("| U+845B U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // Isolated variation selectors
+        state.setByString("| U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple variation selectors
+        state.setByString("| U+FE0F U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+FE0F U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+E0100 U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+E0100 U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Multiple variation selectors
+        state.setByString("| '#' U+FE0F U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| '#' U+FE0F U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+845B U+E0100 U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+845B U+E0100 U+E0100");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testEmojiZeroWidthJoinerSequence() {
+        EditorState state = new EditorState();
+
+        // U+200D is ZERO WIDTH JOINER.
+        state.setByString("| U+1F441 U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // End with ZERO WIDTH JOINER
+        state.setByString("| U+1F441 U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER
+        state.setByString("| U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Multiple ZERO WIDTH JOINER
+        state.setByString("| U+1F441 U+200D U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated ZERO WIDTH JOINER
+        state.setByString("| U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple ZERO WIDTH JOINER
+        state.setByString("| U+200D U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testFlags() {
+        EditorState state = new EditorState();
+
+        // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
+        // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
+        state.setByString("| U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA U+1F1F8");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // Isolated regional indicator symbol
+        state.setByString("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Odd numbered regional indicator symbols
+        state.setByString("| U+1F1FA U+1F1F8 U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testEmojiModifier() {
+        EditorState state = new EditorState();
+
+        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
+        state.setByString("| U+1F466 U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Edge cases
+        // Isolated emoji modifier
+        state.setByString("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Isolated multiple emoji modifier
+        state.setByString("| U+1F3FB U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Multiple emoji modifiers
+        state.setByString("| U+1F466 U+1F3FB U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+
+    @SmallTest
+    public void testMixedEdgeCases() {
+        EditorState state = new EditorState();
+
+        // COMBINING ENCLOSING KEYCAP + variation selector
+        state.setByString("| '1' U+20E3 U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+2665 U+FE0F U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + ending with ZERO WIDTH JOINER
+        state.setByString("| '1' U+20E3 U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + ZERO WIDTH JOINER
+        state.setByString("| '1' U+20E3 U+200D U+1F5E8");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F5E8 ");
+
+        // Start with ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+200D U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+1F441 U+200D U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + regional indicator symbol
+        state.setByString("| '1' U+20E3 U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+1F1FA U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // COMBINING ENCLOSING KEYCAP + emoji modifier
+        state.setByString("| '1' U+20E3 U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // Emoji modifier + COMBINING ENCLOSING KEYCAP
+        state.setByString("| U+1F466 U+1F3FB U+20E3");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + end with ZERO WIDTH JOINER
+        state.setByString("| U+2665 U+FE0F U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + ZERO WIDTH JOINER
+        state.setByString("| U+1F469 U+200D U+2764 U+FE0F U+200D U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER + variation selector
+        state.setByString("| U+200D U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // ZERO WIDTH JOINER + variation selector
+        state.setByString("| U+1F469 U+200D U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + regional indicator symbol
+        state.setByString("| U+2665 U+FE0F U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + variation selector
+        state.setByString("| U+1F1FA U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Variation selector + emoji modifier
+        state.setByString("| U+2665 U+FE0F U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // Emoji modifier + variation selector
+        state.setByString("| U+1F466 U+1F3FB U+FE0F");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER + regional indicator symbol
+        state.setByString("| U+200D U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // ZERO WIDTH JOINER + regional indicator symbol
+        state.setByString("| U+1F469 U+200D U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+
+        // Regional indicator symbol + end with ZERO WIDTH JOINER
+        state.setByString("| U+1F1FA U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + ZERO WIDTH JOINER
+        state.setByString("| U+1F1FA U+200D U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Start with ZERO WIDTH JOINER + emoji modifier
+        state.setByString("| U+200D U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // ZERO WIDTH JOINER + emoji modifier
+        state.setByString("| U+1F469 U+200D U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+
+        // Emoji modifier + end with ZERO WIDTH JOINER
+        state.setByString("| U+1F466 U+1F3FB U+200D");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Emoji modifier + ZERO WIDTH JOINER
+        state.setByString("| U+1F466 U+1F3FB U+200D U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F469");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Regional indicator symbol + emoji modifier
+        state.setByString("| U+1F1FA U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3FB");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+
+        // Emoji modifier + regional indicator symbol
+        state.setByString("| U+1F466 U+1F3FB U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F1FA");
+        forwardDelete(state, 0);
+        state.assertEquals("|");
+    }
+}
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index d383775..348f8fd 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -25,7 +25,7 @@
 
 public class PatternsTest extends TestCase {
 
-    //Tests for Patterns.TOP_LEVEL_DOMAIN
+    // Tests for Patterns.TOP_LEVEL_DOMAIN
 
     @SmallTest
     public void testTldPattern() throws Exception {
@@ -56,7 +56,7 @@
         assertFalse("Matched invalid TLD!", t);
     }
 
-    //Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
+    // Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
 
     @SmallTest
     public void testIanaTopLevelDomains_matchesValidTld() throws Exception {
@@ -94,7 +94,7 @@
         assertFalse("Should not match invalid Punycode TLD", pattern.matcher("xn").matches());
     }
 
-    //Tests for Patterns.WEB_URL
+    // Tests for Patterns.WEB_URL
 
     @SmallTest
     public void testWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -208,7 +208,7 @@
                 Patterns.WEB_URL.matcher(url).matches());
     }
 
-    //Tests for Patterns.AUTOLINK_WEB_URL
+    // Tests for Patterns.AUTOLINK_WEB_URL
 
     @SmallTest
     public void testAutoLinkWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -419,7 +419,7 @@
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
 
-    //Tests for Patterns.IP_ADDRESS
+    // Tests for Patterns.IP_ADDRESS
 
     @SmallTest
     public void testIpPattern() throws Exception {
@@ -432,7 +432,7 @@
         assertFalse("Invalid IP", t);
     }
 
-    //Tests for Patterns.DOMAIN_NAME
+    // Tests for Patterns.DOMAIN_NAME
 
     @SmallTest
     public void testDomain_matchesPunycodeTld() throws Exception {
@@ -508,7 +508,227 @@
                 Patterns.DOMAIN_NAME.matcher(domain).matches());
     }
 
-    //Tests for Patterns.PHONE
+    // Tests for Patterns.AUTOLINK_EMAIL_ADDRESS
+
+    public void testAutoLinkEmailAddress_matchesShortValidEmail() throws Exception {
+        String email = "a@a.co";
+        assertTrue("Should match short valid email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesRegularEmail() throws Exception {
+        String email = "email@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesEmailWithMultipleSubdomains() throws Exception {
+        String email = "email@e.somelongdomainnameforandroid.abc.uk";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithDot() throws Exception {
+        String email = "e.mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithPlus() throws Exception {
+        String email = "e+mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithUnderscore() throws Exception {
+        String email = "e_mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithDash() throws Exception {
+        String email = "e-mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithApostrophe() throws Exception {
+        String email = "e'mail@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithDigits() throws Exception {
+        String email = "123@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesUnicodeLocalPart() throws Exception {
+        String email = "\uD604\uAE08\uC601\uC218\uC99D@android.kr";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithEmoji() throws Exception {
+        String email = "smiley\u263A@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartWithSurrogatePairs() throws Exception {
+        String email = "\uD83C\uDF38@android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainWithDash() throws Exception {
+        String email = "email@an-droid.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesUnicodeDomain() throws Exception {
+        String email = "email@\uD604\uAE08\uC601\uC218\uC99D.kr";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesUnicodeLocalPartAndDomain() throws Exception {
+        String email = "\uD604\uAE08\uC601\uC218\uC99D@\uD604\uAE08\uC601\uC218\uC99D.kr";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainWithEmoji() throws Exception {
+        String email = "smiley@\u263Aandroid.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainWithSurrogatePairs() throws Exception {
+        String email = "email@\uD83C\uDF38android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartAndDomainWithSurrogatePairs()
+            throws Exception {
+        String email = "\uD83C\uDF38@\uD83C\uDF38android.com";
+        assertTrue("Should match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchStringWithoutAtSign() throws Exception {
+        String email = "android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchPlainString() throws Exception {
+        String email = "email";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchStringWithMultipleAtSigns() throws Exception {
+        String email = "email@android@android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchEmailWithoutTld() throws Exception {
+        String email = "email@android";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchLocalPartEndingWithDot() throws Exception {
+        String email = "email.@android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchLocalPartStartingWithDot() throws Exception {
+        String email = ".email@android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchDomainStartingWithDash() throws Exception {
+        String email = "email@-android.com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchDomainWithConsecutiveDots() throws Exception {
+        String email = "email@android..com";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchEmailWithIpAsDomain() throws Exception {
+        String email = "email@127.0.0.1";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_doesNotMatchEmailWithInvalidTld() throws Exception {
+        String email = "email@android.c";
+        assertFalse("Should not match email: " + email,
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesLocalPartUpTo64Chars() throws Exception {
+        String localPart = "";
+        for (int i = 0; i < 64; i++) {
+            localPart += "a";
+        }
+        String email = localPart + "@android.com";
+
+        assertTrue("Should match local part of length: " + localPart.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+        email = localPart + "a@android.com";
+        assertFalse("Should not match local part of length: " + localPart.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesSubdomainUpTo63Chars() throws Exception {
+        String subdomain = "";
+        for (int i = 0; i < 63; i++) {
+            subdomain += "a";
+        }
+        String email = "email@" + subdomain + ".com";
+
+        assertTrue("Should match subdomain of length: " + subdomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+        subdomain += "a";
+        email = "email@" + subdomain + ".com";
+        assertFalse("Should not match local part of length: " + subdomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    public void testAutoLinkEmailAddress_matchesDomainUpTo255Chars() throws Exception {
+        String longDomain = "";
+        while (longDomain.length() <= 250) {
+            longDomain += "d.";
+        }
+        longDomain += "com";
+        assertEquals(255, longDomain.length());
+        String email = "a@" + longDomain;
+
+        assertTrue("Should match domain of length: " + longDomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+        email = email + "m";
+        assertEquals(258, email.length());
+        assertFalse("Should not match domain of length: " + longDomain.length(),
+                Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+    }
+
+    // Tests for Patterns.PHONE
 
     @SmallTest
     public void testPhonePattern() throws Exception {
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index ac020e4..719b274 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -70,6 +70,7 @@
     private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
     private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
     private static final String SUBTYPE_MODE_VOICE = "voice";
+    private static final String SUBTYPE_MODE_HANDWRITING = "handwriting";
     private static final String SUBTYPE_MODE_ANY = null;
     private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
     private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
@@ -215,6 +216,12 @@
         final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
                 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
                 !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi",
+                SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+                !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en",
+                SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+                !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
         final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
                 createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
                         !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
@@ -349,6 +356,57 @@
             verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2));
         }
 
+        // Make sure that if there is no subtype that matches the language requested, then we just
+        // use the first keyboard subtype.
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoHi);
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(LOCALE_JA_JP), imi);
+            assertEquals(1, result.size());
+            verifyEquality(nonAutoHi, result.get(0));
+        }
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoHi);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(LOCALE_JA_JP), imi);
+            assertEquals(1, result.size());
+            verifyEquality(nonAutoEnUS, result.get(0));
+        }
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoHi);
+            subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(LOCALE_JA_JP), imi);
+            assertEquals(1, result.size());
+            verifyEquality(nonAutoEnUS, result.get(0));
+        }
+
         // Make sure that 3-letter language code can be handled.
         {
             final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 7adad8a..0886487 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -547,11 +547,8 @@
         Intent intent = new Intent(IKeyChainService.class.getName());
         ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
         intent.setComponent(comp);
-        boolean isBound = context.bindServiceAsUser(intent,
-                                                    keyChainServiceConnection,
-                                                    Context.BIND_AUTO_CREATE,
-                                                    user);
-        if (!isBound) {
+        if (comp == null || !context.bindServiceAsUser(
+                intent, keyChainServiceConnection, Context.BIND_AUTO_CREATE, user)) {
             throw new AssertionError("could not bind to KeyChainService");
         }
         return new KeyChainConnection(context, keyChainServiceConnection, q.take());
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 3c8a78d..6a7801e 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -26,26 +26,26 @@
 public final class GnssClock implements Parcelable {
     // The following enumerations must be in sync with the values declared in gps.h
 
-    private static final short HAS_NO_FLAGS = 0;
-    private static final short HAS_LEAP_SECOND = (1<<0);
-    private static final short HAS_TIME_UNCERTAINTY = (1<<1);
-    private static final short HAS_FULL_BIAS = (1<<2);
-    private static final short HAS_BIAS = (1<<3);
-    private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
-    private static final short HAS_DRIFT = (1<<5);
-    private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);
+    private static final int HAS_NO_FLAGS = 0;
+    private static final int HAS_LEAP_SECOND = (1<<0);
+    private static final int HAS_TIME_UNCERTAINTY = (1<<1);
+    private static final int HAS_FULL_BIAS = (1<<2);
+    private static final int HAS_BIAS = (1<<3);
+    private static final int HAS_BIAS_UNCERTAINTY = (1<<4);
+    private static final int HAS_DRIFT = (1<<5);
+    private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
 
     // End enumerations in sync with gps.h
 
-    private short mFlags;
-    private short mLeapSecond;
-    private long mTimeInNs;
-    private double mTimeUncertaintyInNs;
-    private long mFullBiasInNs;
-    private double mBiasInNs;
-    private double mBiasUncertaintyInNs;
-    private double mDriftInNsPerSec;
-    private double mDriftUncertaintyInNsPerSec;
+    private int mFlags;
+    private int mLeapSecond;
+    private long mTimeNanos;
+    private double mTimeUncertaintyNanos;
+    private long mFullBiasNanos;
+    private double mBiasNanos;
+    private double mBiasUncertaintyNanos;
+    private double mDriftNanosPerSecond;
+    private double mDriftUncertaintyNanosPerSecond;
     private int mHardwareClockDiscontinuityCount;
 
     GnssClock() {
@@ -58,13 +58,13 @@
     public void set(GnssClock clock) {
         mFlags = clock.mFlags;
         mLeapSecond = clock.mLeapSecond;
-        mTimeInNs = clock.mTimeInNs;
-        mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
-        mFullBiasInNs = clock.mFullBiasInNs;
-        mBiasInNs = clock.mBiasInNs;
-        mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
-        mDriftInNsPerSec = clock.mDriftInNsPerSec;
-        mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
+        mTimeNanos = clock.mTimeNanos;
+        mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos;
+        mFullBiasNanos = clock.mFullBiasNanos;
+        mBiasNanos = clock.mBiasNanos;
+        mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos;
+        mDriftNanosPerSecond = clock.mDriftNanosPerSecond;
+        mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond;
         mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
     }
 
@@ -89,14 +89,14 @@
      *
      * The value is only available if {@link #hasLeapSecond()} is true.
      */
-    public short getLeapSecond() {
+    public int getLeapSecond() {
         return mLeapSecond;
     }
 
     /**
      * Sets the leap second associated with the clock's time.
      */
-    public void setLeapSecond(short leapSecond) {
+    public void setLeapSecond(int leapSecond) {
         setFlag(HAS_LEAP_SECOND);
         mLeapSecond = leapSecond;
     }
@@ -106,7 +106,7 @@
      */
     public void resetLeapSecond() {
         resetFlag(HAS_LEAP_SECOND);
-        mLeapSecond = Short.MIN_VALUE;
+        mLeapSecond = Integer.MIN_VALUE;
     }
 
     /**
@@ -114,30 +114,30 @@
      *
      * For 'local hardware clock' this value is expected to be monotonically increasing during the
      * reporting session. The real GPS time can be derived by compensating
-     * {@link #getFullBiasInNs()} (when it is available) from this value.
+     * {@link #getFullBiasNanos()} (when it is available) from this value.
      *
      * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
-     * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
+     * receiver can achieve. {@link #getTimeUncertaintyNanos()} should be available when GPS time is
      * specified.
      *
-     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
-     * The reported time includes {@link #getTimeUncertaintyInNs()}.
+     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
+     * The reported time includes {@link #getTimeUncertaintyNanos()}.
      */
-    public long getTimeInNs() {
-        return mTimeInNs;
+    public long getTimeNanos() {
+        return mTimeNanos;
     }
 
     /**
-     * Sets the GPS receiver internal clock in nanoseconds.
+     * Sets the GNSS receiver internal clock in nanoseconds.
      */
-    public void setTimeInNs(long timeInNs) {
-        mTimeInNs = timeInNs;
+    public void setTimeNanos(long timeNanos) {
+        mTimeNanos = timeNanos;
     }
 
     /**
-     * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
+     * Returns true if {@link #getTimeUncertaintyNanos()} is available, false otherwise.
      */
-    public boolean hasTimeUncertaintyInNs() {
+    public boolean hasTimeUncertaintyNanos() {
         return isFlagSet(HAS_TIME_UNCERTAINTY);
     }
 
@@ -145,189 +145,189 @@
      * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
      * The uncertainty is represented as an absolute (single sided) value.
      *
-     * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
+     * The value is only available if {@link #hasTimeUncertaintyNanos()} is true.
      */
-    public double getTimeUncertaintyInNs() {
-        return mTimeUncertaintyInNs;
+    public double getTimeUncertaintyNanos() {
+        return mTimeUncertaintyNanos;
     }
 
     /**
      * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
      */
-    public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
+    public void setTimeUncertaintyNanos(double timeUncertaintyNanos) {
         setFlag(HAS_TIME_UNCERTAINTY);
-        mTimeUncertaintyInNs = timeUncertaintyInNs;
+        mTimeUncertaintyNanos = timeUncertaintyNanos;
     }
 
     /**
      * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
      */
-    public void resetTimeUncertaintyInNs() {
+    public void resetTimeUncertaintyNanos() {
         resetFlag(HAS_TIME_UNCERTAINTY);
-        mTimeUncertaintyInNs = Double.NaN;
+        mTimeUncertaintyNanos = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getFullBiasInNs()} is available, false otherwise.
+     * Returns true if {@link #getFullBiasNanos()} is available, false otherwise.
      */
-    public boolean hasFullBiasInNs() {
+    public boolean hasFullBiasNanos() {
         return isFlagSet(HAS_FULL_BIAS);
     }
 
     /**
-     * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
+     * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and
      * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
      *
      * This value is available if the receiver has estimated GPS time. If the computed time is for a
      * non-GPS constellation, the time offset of that constellation to GPS has to be applied to fill
-     * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyInNs()} in
+     * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyNanos()} in
      * it, and it should be used for quality check. The value is only available if
-     * {@link #hasFullBiasInNs()} is true.
+     * {@link #hasFullBiasNanos()} is true.
      *
      * The sign of the value is defined by the following equation:
      *      local estimate of GPS time = time_ns + (full_bias_ns + bias_ns)
      */
-    public long getFullBiasInNs() {
-        return mFullBiasInNs;
+    public long getFullBiasNanos() {
+        return mFullBiasNanos;
     }
 
     /**
      * Sets the full bias in nanoseconds.
      */
-    public void setFullBiasInNs(long value) {
+    public void setFullBiasNanos(long value) {
         setFlag(HAS_FULL_BIAS);
-        mFullBiasInNs = value;
+        mFullBiasNanos = value;
     }
 
     /**
      * Resets the full bias in nanoseconds.
      */
-    public void resetFullBiasInNs() {
+    public void resetFullBiasNanos() {
         resetFlag(HAS_FULL_BIAS);
-        mFullBiasInNs = Long.MIN_VALUE;
+        mFullBiasNanos = Long.MIN_VALUE;
     }
 
     /**
-     * Returns true if {@link #getBiasInNs()} is available, false otherwise.
+     * Returns true if {@link #getBiasNanos()} is available, false otherwise.
      */
-    public boolean hasBiasInNs() {
+    public boolean hasBiasNanos() {
         return isFlagSet(HAS_BIAS);
     }
 
     /**
      * Gets the clock's sub-nanosecond bias.
-     * The reported bias includes {@link #getBiasUncertaintyInNs()}.
+     * The reported bias includes {@link #getBiasUncertaintyNanos()}.
      *
-     * The value is only available if {@link #hasBiasInNs()} is true.
+     * The value is only available if {@link #hasBiasNanos()} is true.
      */
-    public double getBiasInNs() {
-        return mBiasInNs;
+    public double getBiasNanos() {
+        return mBiasNanos;
     }
 
     /**
      * Sets the sub-nanosecond bias.
      */
-    public void setBiasInNs(double biasInNs) {
+    public void setBiasNanos(double biasNanos) {
         setFlag(HAS_BIAS);
-        mBiasInNs = biasInNs;
+        mBiasNanos = biasNanos;
     }
 
     /**
      * Resets the clock's Bias in nanoseconds.
      */
-    public void resetBiasInNs() {
+    public void resetBiasNanos() {
         resetFlag(HAS_BIAS);
-        mBiasInNs = Double.NaN;
+        mBiasNanos = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
+     * Returns true if {@link #getBiasUncertaintyNanos()} is available, false otherwise.
      */
-    public boolean hasBiasUncertaintyInNs() {
+    public boolean hasBiasUncertaintyNanos() {
         return isFlagSet(HAS_BIAS_UNCERTAINTY);
     }
 
     /**
      * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
      *
-     * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
+     * The value is only available if {@link #hasBiasUncertaintyNanos()} is true.
      */
-    public double getBiasUncertaintyInNs() {
-        return mBiasUncertaintyInNs;
+    public double getBiasUncertaintyNanos() {
+        return mBiasUncertaintyNanos;
     }
 
     /**
      * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
      */
-    public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
+    public void setBiasUncertaintyNanos(double biasUncertaintyNanos) {
         setFlag(HAS_BIAS_UNCERTAINTY);
-        mBiasUncertaintyInNs = biasUncertaintyInNs;
+        mBiasUncertaintyNanos = biasUncertaintyNanos;
     }
 
     /**
      * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
      */
-    public void resetBiasUncertaintyInNs() {
+    public void resetBiasUncertaintyNanos() {
         resetFlag(HAS_BIAS_UNCERTAINTY);
-        mBiasUncertaintyInNs = Double.NaN;
+        mBiasUncertaintyNanos = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
+     * Returns true if {@link #getDriftNanosPerSecond()} is available, false otherwise.
      */
-    public boolean hasDriftInNsPerSec() {
+    public boolean hasDriftNanosPerSecond() {
         return isFlagSet(HAS_DRIFT);
     }
 
     /**
      * Gets the clock's Drift in nanoseconds per second.
      * A positive value indicates that the frequency is higher than the nominal frequency.
-     * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
+     * The reported drift includes {@link #getDriftUncertaintyNanosPerSecond()}.
      *
-     * The value is only available if {@link #hasDriftInNsPerSec()} is true.
+     * The value is only available if {@link #hasDriftNanosPerSecond()} is true.
      */
-    public double getDriftInNsPerSec() {
-        return mDriftInNsPerSec;
+    public double getDriftNanosPerSecond() {
+        return mDriftNanosPerSecond;
     }
 
     /**
      * Sets the clock's Drift in nanoseconds per second.
      */
-    public void setDriftInNsPerSec(double driftInNsPerSec) {
+    public void setDriftNanosPerSecond(double driftNanosPerSecond) {
         setFlag(HAS_DRIFT);
-        mDriftInNsPerSec = driftInNsPerSec;
+        mDriftNanosPerSecond = driftNanosPerSecond;
     }
 
     /**
      * Resets the clock's Drift in nanoseconds per second.
      */
-    public void resetDriftInNsPerSec() {
+    public void resetDriftNanosPerSecond() {
         resetFlag(HAS_DRIFT);
-        mDriftInNsPerSec = Double.NaN;
+        mDriftNanosPerSecond = Double.NaN;
     }
 
     /**
-     * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
+     * Returns true if {@link #getDriftUncertaintyNanosPerSecond()} is available, false otherwise.
      */
-    public boolean hasDriftUncertaintyInNsPerSec() {
+    public boolean hasDriftUncertaintyNanosPerSecond() {
         return isFlagSet(HAS_DRIFT_UNCERTAINTY);
     }
 
     /**
      * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
      *
-     * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
+     * The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is true.
      */
-    public double getDriftUncertaintyInNsPerSec() {
-        return mDriftUncertaintyInNsPerSec;
+    public double getDriftUncertaintyNanosPerSecond() {
+        return mDriftUncertaintyNanosPerSecond;
     }
 
     /**
      * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
      */
-    public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
+    public void setDriftUncertaintyNanosPerSecond(double driftUncertaintyNanosPerSecond) {
         setFlag(HAS_DRIFT_UNCERTAINTY);
-        mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
+        mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
     }
 
     /**
@@ -347,9 +347,9 @@
     /**
      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
      */
-    public void resetDriftUncertaintyInNsPerSec() {
+    public void resetDriftUncertaintyNanosPerSecond() {
         resetFlag(HAS_DRIFT_UNCERTAINTY);
-        mDriftUncertaintyInNsPerSec = Double.NaN;
+        mDriftUncertaintyNanosPerSecond = Double.NaN;
     }
 
     public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
@@ -357,15 +357,15 @@
         public GnssClock createFromParcel(Parcel parcel) {
             GnssClock gpsClock = new GnssClock();
 
-            gpsClock.mFlags = (short) parcel.readInt();
-            gpsClock.mLeapSecond = (short) parcel.readInt();
-            gpsClock.mTimeInNs = parcel.readLong();
-            gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
-            gpsClock.mFullBiasInNs = parcel.readLong();
-            gpsClock.mBiasInNs = parcel.readDouble();
-            gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
-            gpsClock.mDriftInNsPerSec = parcel.readDouble();
-            gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
+            gpsClock.mFlags = parcel.readInt();
+            gpsClock.mLeapSecond = parcel.readInt();
+            gpsClock.mTimeNanos = parcel.readLong();
+            gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
+            gpsClock.mFullBiasNanos = parcel.readLong();
+            gpsClock.mBiasNanos = parcel.readDouble();
+            gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
+            gpsClock.mDriftNanosPerSecond = parcel.readDouble();
+            gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
             gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
 
             return gpsClock;
@@ -381,13 +381,13 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mFlags);
         parcel.writeInt(mLeapSecond);
-        parcel.writeLong(mTimeInNs);
-        parcel.writeDouble(mTimeUncertaintyInNs);
-        parcel.writeLong(mFullBiasInNs);
-        parcel.writeDouble(mBiasInNs);
-        parcel.writeDouble(mBiasUncertaintyInNs);
-        parcel.writeDouble(mDriftInNsPerSec);
-        parcel.writeDouble(mDriftUncertaintyInNsPerSec);
+        parcel.writeLong(mTimeNanos);
+        parcel.writeDouble(mTimeUncertaintyNanos);
+        parcel.writeLong(mFullBiasNanos);
+        parcel.writeDouble(mBiasNanos);
+        parcel.writeDouble(mBiasUncertaintyNanos);
+        parcel.writeDouble(mDriftNanosPerSecond);
+        parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
         parcel.writeInt(mHardwareClockDiscontinuityCount);
     }
 
@@ -406,29 +406,29 @@
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "TimeInNs",
-                mTimeInNs,
-                "TimeUncertaintyInNs",
-                hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));
+                "TimeNanos",
+                mTimeNanos,
+                "TimeUncertaintyNanos",
+                hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
 
         builder.append(String.format(
                 format,
-                "FullBiasInNs",
-                hasFullBiasInNs() ? mFullBiasInNs : null));
+                "FullBiasNanos",
+                hasFullBiasNanos() ? mFullBiasNanos : null));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "BiasInNs",
-                hasBiasInNs() ? mBiasInNs : null,
-                "BiasUncertaintyInNs",
-                hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));
+                "BiasNanos",
+                hasBiasNanos() ? mBiasNanos : null,
+                "BiasUncertaintyNanos",
+                hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "DriftInNsPerSec",
-                hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
-                "DriftUncertaintyInNsPerSec",
-                hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
+                "DriftNanosPerSecond",
+                hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
+                "DriftUncertaintyNanosPerSecond",
+                hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
 
         return builder.toString();
     }
@@ -436,25 +436,25 @@
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
         resetLeapSecond();
-        setTimeInNs(Long.MIN_VALUE);
-        resetTimeUncertaintyInNs();
-        resetFullBiasInNs();
-        resetBiasInNs();
-        resetBiasUncertaintyInNs();
-        resetDriftInNsPerSec();
-        resetDriftUncertaintyInNsPerSec();
+        setTimeNanos(Long.MIN_VALUE);
+        resetTimeUncertaintyNanos();
+        resetFullBiasNanos();
+        resetBiasNanos();
+        resetBiasUncertaintyNanos();
+        resetDriftNanosPerSecond();
+        resetDriftUncertaintyNanosPerSecond();
         setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
     }
 
-    private void setFlag(short flag) {
+    private void setFlag(int flag) {
         mFlags |= flag;
     }
 
-    private void resetFlag(short flag) {
+    private void resetFlag(int flag) {
         mFlags &= ~flag;
     }
 
-    private boolean isFlagSet(short flag) {
+    private boolean isFlagSet(int flag) {
         return (mFlags & flag) == flag;
     }
 }
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index abdc13c..367c52f 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -28,82 +28,35 @@
  */
 public final class GnssMeasurement implements Parcelable {
     private int mFlags;
-    private short mSvid;
-    private byte mConstellationType;
-    private double mTimeOffsetInNs;
-    private short mState;
-    private long mReceivedSvTimeInNs;
-    private long mReceivedSvTimeUncertaintyInNs;
-    private double mCn0InDbHz;
-    private double mPseudorangeRateInMetersPerSec;
-    private double mPseudorangeRateUncertaintyInMetersPerSec;
-    private short mAccumulatedDeltaRangeState;
-    private double mAccumulatedDeltaRangeInMeters;
-    private double mAccumulatedDeltaRangeUncertaintyInMeters;
-    private double mPseudorangeInMeters;
-    private double mPseudorangeUncertaintyInMeters;
-    private double mCodePhaseInChips;
-    private double mCodePhaseUncertaintyInChips;
-    private float mCarrierFrequencyInHz;
+    private int mSvid;
+    private int mConstellationType;
+    private double mTimeOffsetNanos;
+    private int mState;
+    private long mReceivedSvTimeNanos;
+    private long mReceivedSvTimeUncertaintyNanos;
+    private double mCn0DbHz;
+    private double mPseudorangeRateMetersPerSecond;
+    private double mPseudorangeRateUncertaintyMetersPerSecond;
+    private int mAccumulatedDeltaRangeState;
+    private double mAccumulatedDeltaRangeMeters;
+    private double mAccumulatedDeltaRangeUncertaintyMeters;
+    private float mCarrierFrequencyHz;
     private long mCarrierCycles;
     private double mCarrierPhase;
     private double mCarrierPhaseUncertainty;
-    private byte mLossOfLock;
-    private int mBitNumber;
-    private short mTimeFromLastBitInMs;
-    private double mDopplerShiftInHz;
-    private double mDopplerShiftUncertaintyInHz;
-    private byte mMultipathIndicator;
+    private int mMultipathIndicator;
     private double mSnrInDb;
-    private double mElevationInDeg;
-    private double mElevationUncertaintyInDeg;
-    private double mAzimuthInDeg;
-    private double mAzimuthUncertaintyInDeg;
-    private boolean mUsedInFix;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
     private static final int HAS_NO_FLAGS = 0;
     private static final int HAS_SNR = (1<<0);
-    private static final int HAS_ELEVATION = (1<<1);
-    private static final int HAS_ELEVATION_UNCERTAINTY = (1<<2);
-    private static final int HAS_AZIMUTH = (1<<3);
-    private static final int HAS_AZIMUTH_UNCERTAINTY = (1<<4);
-    private static final int HAS_PSEUDORANGE = (1<<5);
-    private static final int HAS_PSEUDORANGE_UNCERTAINTY = (1<<6);
-    private static final int HAS_CODE_PHASE = (1<<7);
-    private static final int HAS_CODE_PHASE_UNCERTAINTY = (1<<8);
     private static final int HAS_CARRIER_FREQUENCY = (1<<9);
     private static final int HAS_CARRIER_CYCLES = (1<<10);
     private static final int HAS_CARRIER_PHASE = (1<<11);
     private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
-    private static final int HAS_BIT_NUMBER = (1<<13);
-    private static final int HAS_TIME_FROM_LAST_BIT = (1<<14);
-    private static final int HAS_DOPPLER_SHIFT = (1<<15);
-    private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16);
-    // private static final int HAS_USED_IN_FIX = (1<<17);
     private static final int 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.
-     */
-    public static final byte LOSS_OF_LOCK_UNKNOWN = 0;
-
-    /**
-     * The measurement does not present any indication of 'loss of lock'.
-     */
-    public static final byte LOSS_OF_LOCK_OK = 1;
-
-    /**
-     * 'Loss of lock' detected between the previous and current observation: cycle slip possible.
-     */
-    public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
-
     /** The status of multipath. */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED,
@@ -113,78 +66,78 @@
     /**
      * The indicator is not available or it is unknown.
      */
-    public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0;
+    public static final int MULTIPATH_INDICATOR_UNKNOWN = 0;
 
     /**
      * The measurement has been indicated to use multi-path.
      */
-    public static final byte MULTIPATH_INDICATOR_DETECTED = 1;
+    public static final int MULTIPATH_INDICATOR_DETECTED = 1;
 
     /**
      * The measurement has been indicated not tu use multi-path.
      */
-    public static final byte MULTIPATH_INDICATOR_NOT_USED = 2;
+    public static final int MULTIPATH_INDICATOR_NOT_USED = 2;
 
     /**
      * The state of GNSS receiver the measurement is invalid or unknown.
      */
-    public static final short STATE_UNKNOWN = 0;
+    public static final int STATE_UNKNOWN = 0;
 
     /**
      * The state of the GNSS receiver is ranging code lock.
      */
-    public static final short STATE_CODE_LOCK = (1<<0);
+    public static final int STATE_CODE_LOCK = (1<<0);
 
     /**
      * The state of the GNSS receiver is in bit sync.
      */
-    public static final short STATE_BIT_SYNC = (1<<1);
+    public static final int STATE_BIT_SYNC = (1<<1);
 
     /**
      *The state of the GNSS receiver is in sub-frame sync.
      */
-    public static final short STATE_SUBFRAME_SYNC = (1<<2);
+    public static final int STATE_SUBFRAME_SYNC = (1<<2);
 
     /**
      * The state of the GNSS receiver has TOW decoded.
      */
-    public static final short STATE_TOW_DECODED = (1<<3);
+    public static final int STATE_TOW_DECODED = (1<<3);
 
     /**
      * The state of the GNSS receiver contains millisecond ambiguity.
      */
-    public static final short STATE_MSEC_AMBIGUOUS = (1<<4);
+    public static final int STATE_MSEC_AMBIGUOUS = (1<<4);
 
     /**
      * All the GNSS receiver state flags.
      */
-    private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
+    private static final int STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
             | STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS;
 
     /**
      * The state of the 'Accumulated Delta Range' is invalid or unknown.
      */
-    public static final short ADR_STATE_UNKNOWN = 0;
+    public static final int ADR_STATE_UNKNOWN = 0;
 
     /**
      * The state of the 'Accumulated Delta Range' is valid.
      */
-    public static final short ADR_STATE_VALID = (1<<0);
+    public static final int ADR_STATE_VALID = (1<<0);
 
     /**
      * The state of the 'Accumulated Delta Range' has detected a reset.
      */
-    public static final short ADR_STATE_RESET = (1<<1);
+    public static final int ADR_STATE_RESET = (1<<1);
 
     /**
      * The state of the 'Accumulated Delta Range' has a cycle slip detected.
      */
-    public static final short ADR_STATE_CYCLE_SLIP = (1<<2);
+    public static final int ADR_STATE_CYCLE_SLIP = (1<<2);
 
     /**
      * All the 'Accumulated Delta Range' flags.
      */
-    private static final short ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
+    private static final int ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
 
     // End enumerations in sync with gps.h
 
@@ -199,38 +152,24 @@
         mFlags = measurement.mFlags;
         mSvid = measurement.mSvid;
         mConstellationType = measurement.mConstellationType;
-        mTimeOffsetInNs = measurement.mTimeOffsetInNs;
+        mTimeOffsetNanos = measurement.mTimeOffsetNanos;
         mState = measurement.mState;
-        mReceivedSvTimeInNs = measurement.mReceivedSvTimeInNs;
-        mReceivedSvTimeUncertaintyInNs = measurement.mReceivedSvTimeUncertaintyInNs;
-        mCn0InDbHz = measurement.mCn0InDbHz;
-        mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec;
-        mPseudorangeRateUncertaintyInMetersPerSec =
-                measurement.mPseudorangeRateUncertaintyInMetersPerSec;
+        mReceivedSvTimeNanos = measurement.mReceivedSvTimeNanos;
+        mReceivedSvTimeUncertaintyNanos = measurement.mReceivedSvTimeUncertaintyNanos;
+        mCn0DbHz = measurement.mCn0DbHz;
+        mPseudorangeRateMetersPerSecond = measurement.mPseudorangeRateMetersPerSecond;
+        mPseudorangeRateUncertaintyMetersPerSecond =
+                measurement.mPseudorangeRateUncertaintyMetersPerSecond;
         mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState;
-        mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters;
-        mAccumulatedDeltaRangeUncertaintyInMeters =
-                measurement.mAccumulatedDeltaRangeUncertaintyInMeters;
-        mPseudorangeInMeters = measurement.mPseudorangeInMeters;
-        mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters;
-        mCodePhaseInChips = measurement.mCodePhaseInChips;
-        mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips;
-        mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz;
+        mAccumulatedDeltaRangeMeters = measurement.mAccumulatedDeltaRangeMeters;
+        mAccumulatedDeltaRangeUncertaintyMeters =
+                measurement.mAccumulatedDeltaRangeUncertaintyMeters;
+        mCarrierFrequencyHz = measurement.mCarrierFrequencyHz;
         mCarrierCycles = measurement.mCarrierCycles;
         mCarrierPhase = measurement.mCarrierPhase;
         mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty;
-        mLossOfLock = measurement.mLossOfLock;
-        mBitNumber = measurement.mBitNumber;
-        mTimeFromLastBitInMs = measurement.mTimeFromLastBitInMs;
-        mDopplerShiftInHz = measurement.mDopplerShiftInHz;
-        mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz;
         mMultipathIndicator = measurement.mMultipathIndicator;
         mSnrInDb = measurement.mSnrInDb;
-        mElevationInDeg = measurement.mElevationInDeg;
-        mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg;
-        mAzimuthInDeg = measurement.mAzimuthInDeg;
-        mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
-        mUsedInFix = measurement.mUsedInFix;
     }
 
     /**
@@ -244,14 +183,14 @@
      * Gets the Pseudo-random number (PRN).
      * Range: [1, 32]
      */
-    public short getSvid() {
+    public int getSvid() {
         return mSvid;
     }
 
     /**
      * Sets the Pseud-random number (PRN).
      */
-    public void setSvid(short value) {
+    public void setSvid(int value) {
         mSvid = value;
     }
 
@@ -259,14 +198,14 @@
      * Getst the constellation type.
      */
     @GnssStatus.ConstellationType
-    public byte getConstellationType() {
+    public int getConstellationType() {
         return mConstellationType;
     }
 
     /**
      * Sets the constellation type.
      */
-    public void setConstellationType(@GnssStatus.ConstellationType byte value) {
+    public void setConstellationType(@GnssStatus.ConstellationType int value) {
         mConstellationType = value;
     }
 
@@ -274,7 +213,7 @@
      * Gets the time offset at which the measurement was taken in nanoseconds.
      *
      * The reference receiver's time from which this is offset is specified by
-     * {@link GnssClock#getTimeInNs()}.
+     * {@link GnssClock#getTimeNanos()}.
      *
      * The sign of this value is given by the following equation:
      *      measurement time = time_ns + time_offset_ns
@@ -282,31 +221,31 @@
      * The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
      * accuracy.
      */
-    public double getTimeOffsetInNs() {
-        return mTimeOffsetInNs;
+    public double getTimeOffsetNanos() {
+        return mTimeOffsetNanos;
     }
 
     /**
      * Sets the time offset at which the measurement was taken in nanoseconds.
      */
-    public void setTimeOffsetInNs(double value) {
-        mTimeOffsetInNs = value;
+    public void setTimeOffsetNanos(double value) {
+        mTimeOffsetNanos = value;
     }
 
     /**
      * Gets per-satellite sync state.
      * It represents the current sync state for the associated satellite.
      *
-     * This value helps interpret {@link #getReceivedSvTimeInNs()}.
+     * This value helps interpret {@link #getReceivedSvTimeNanos()}.
      */
-    public short getState() {
+    public int getState() {
         return mState;
     }
 
     /**
      * Sets the sync state.
      */
-    public void setState(short value) {
+    public void setState(int value) {
         mState = value;
     }
 
@@ -408,29 +347,29 @@
      *     Symbol sync     : [ 0   2ms ]   : STATE_SYMBOL_SYNC is set
      *     Message         : [ 0    1s ]   : STATE_SBAS_SYNC is set
      */
-    public long getReceivedSvTimeInNs() {
-        return mReceivedSvTimeInNs;
+    public long getReceivedSvTimeNanos() {
+        return mReceivedSvTimeNanos;
     }
 
     /**
      * Sets the received GNSS time in nanoseconds.
      */
-    public void setReceivedSvTimeInNs(long value) {
-        mReceivedSvTimeInNs = value;
+    public void setReceivedSvTimeNanos(long value) {
+        mReceivedSvTimeNanos = value;
     }
 
     /**
      * Gets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
      */
-    public long getReceivedSvTimeUncertaintyInNs() {
-        return mReceivedSvTimeUncertaintyInNs;
+    public long getReceivedSvTimeUncertaintyNanos() {
+        return mReceivedSvTimeUncertaintyNanos;
     }
 
     /**
      * Sets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
      */
-    public void setReceivedSvTimeUncertaintyInNs(long value) {
-        mReceivedSvTimeUncertaintyInNs = value;
+    public void setReceivedSvTimeUncertaintyNanos(long value) {
+        mReceivedSvTimeUncertaintyNanos = value;
     }
 
     /**
@@ -439,45 +378,46 @@
      *
      * The value contains the measured C/N0 for the signal at the antenna input.
      */
-    public double getCn0InDbHz() {
-        return mCn0InDbHz;
+    public double getCn0DbHz() {
+        return mCn0DbHz;
     }
 
     /**
      * Sets the carrier-to-noise density in dB-Hz.
      */
-    public void setCn0InDbHz(double value) {
-        mCn0InDbHz = value;
+    public void setCn0DbHz(double value) {
+        mCn0DbHz = value;
     }
 
     /**
      * Gets the Pseudorange rate at the timestamp in m/s.
-     * The reported value includes {@link #getPseudorangeRateUncertaintyInMetersPerSec()}.
      *
-     * The correction of a given Pseudorange Rate value includes corrections from receiver and
-     * satellite clock frequency errors.
-     * {@link #isPseudorangeRateCorrected()} identifies the type of value reported.
+     * The reported value includes {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
      *
-     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
-     * The sign of the 'uncorrected' Pseudorange Rate and its relation to the sign of
-     * {@link #getDopplerShiftInHz()} is given by the equation:
+     * The value is uncorrected, hence corrections for receiver and satellite clock frequency errors
+     * should not be included.
+     *
+     * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. The
+     * sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler shift'
+     * is given by the equation:
+     *
      *      pseudorange rate = -k * doppler shift   (where k is a constant)
      */
-    public double getPseudorangeRateInMetersPerSec() {
-        return mPseudorangeRateInMetersPerSec;
+    public double getPseudorangeRateMetersPerSecond() {
+        return mPseudorangeRateMetersPerSecond;
     }
 
     /**
      * Sets the pseudorange rate at the timestamp in m/s.
      */
-    public void setPseudorangeRateInMetersPerSec(double value) {
-        mPseudorangeRateInMetersPerSec = value;
+    public void setPseudorangeRateMetersPerSecond(double value) {
+        mPseudorangeRateMetersPerSecond = value;
     }
 
     /**
-     * See {@link #getPseudorangeRateInMetersPerSec()} for more details.
+     * See {@link #getPseudorangeRateMetersPerSecond()} for more details.
      *
-     * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected
+     * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected
      *         value, {@code false} if it contains an uncorrected value.
      */
     public boolean isPseudorangeRateCorrected() {
@@ -488,30 +428,30 @@
      * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
      * The uncertainty is represented as an absolute (single sided) value.
      */
-    public double getPseudorangeRateUncertaintyInMetersPerSec() {
-        return mPseudorangeRateUncertaintyInMetersPerSec;
+    public double getPseudorangeRateUncertaintyMetersPerSecond() {
+        return mPseudorangeRateUncertaintyMetersPerSecond;
     }
 
     /**
      * Sets the pseudorange's rate uncertainty (1-Sigma) in m/s.
      */
-    public void setPseudorangeRateUncertaintyInMetersPerSec(double value) {
-        mPseudorangeRateUncertaintyInMetersPerSec = value;
+    public void setPseudorangeRateUncertaintyMetersPerSecond(double value) {
+        mPseudorangeRateUncertaintyMetersPerSecond = value;
     }
 
     /**
      * Gets 'Accumulated Delta Range' state.
-     * It indicates whether {@link #getAccumulatedDeltaRangeInMeters()} is reset or there is a
+     * It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
      * cycle slip (indicating 'loss of lock').
      */
-    public short getAccumulatedDeltaRangeState() {
+    public int getAccumulatedDeltaRangeState() {
         return mAccumulatedDeltaRangeState;
     }
 
     /**
      * Sets the 'Accumulated Delta Range' state.
      */
-    public void setAccumulatedDeltaRangeState(short value) {
+    public void setAccumulatedDeltaRangeState(int value) {
         mAccumulatedDeltaRangeState = value;
     }
 
@@ -545,24 +485,24 @@
 
     /**
      * Gets the accumulated delta range since the last channel reset, in meters.
-     * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}.
+     * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
      *
      * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
      *
      * A positive value indicates that the SV is moving away from the receiver.
-     * The sign of {@link #getAccumulatedDeltaRangeInMeters()} and its relation to the sign of
+     * The sign of {@link #getAccumulatedDeltaRangeMeters()} and its relation to the sign of
      * {@link #getCarrierPhase()} is given by the equation:
      *          accumulated delta range = -k * carrier phase    (where k is a constant)
      */
-    public double getAccumulatedDeltaRangeInMeters() {
-        return mAccumulatedDeltaRangeInMeters;
+    public double getAccumulatedDeltaRangeMeters() {
+        return mAccumulatedDeltaRangeMeters;
     }
 
     /**
      * Sets the accumulated delta range in meters.
      */
-    public void setAccumulatedDeltaRangeInMeters(double value) {
-        mAccumulatedDeltaRangeInMeters = value;
+    public void setAccumulatedDeltaRangeMeters(double value) {
+        mAccumulatedDeltaRangeMeters = value;
     }
 
     /**
@@ -571,8 +511,8 @@
      *
      * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
      */
-    public double getAccumulatedDeltaRangeUncertaintyInMeters() {
-        return mAccumulatedDeltaRangeUncertaintyInMeters;
+    public double getAccumulatedDeltaRangeUncertaintyMeters() {
+        return mAccumulatedDeltaRangeUncertaintyMeters;
     }
 
     /**
@@ -580,149 +520,14 @@
      *
      * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
      */
-    public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) {
-        mAccumulatedDeltaRangeUncertaintyInMeters = value;
+    public void setAccumulatedDeltaRangeUncertaintyMeters(double value) {
+        mAccumulatedDeltaRangeUncertaintyMeters = value;
     }
 
     /**
-     * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise.
+     * Returns true if {@link #getCarrierFrequencyHz()} is available, false otherwise.
      */
-    public boolean hasPseudorangeInMeters() {
-        return isFlagSet(HAS_PSEUDORANGE);
-    }
-
-    /**
-     * Gets the best derived pseudorange by the chipset, in meters.
-     * The reported pseudorange includes {@link #getPseudorangeUncertaintyInMeters()}.
-     *
-     * The value is only available if {@link #hasPseudorangeInMeters()} is true.
-     */
-    public double getPseudorangeInMeters() {
-        return mPseudorangeInMeters;
-    }
-
-    /**
-     * Sets the Pseudo-range in meters.
-     */
-    public void setPseudorangeInMeters(double value) {
-        setFlag(HAS_PSEUDORANGE);
-        mPseudorangeInMeters = value;
-    }
-
-    /**
-     * Resets the Pseudo-range in meters.
-     */
-    public void resetPseudorangeInMeters() {
-        resetFlag(HAS_PSEUDORANGE);
-        mPseudorangeInMeters = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise.
-     */
-    public boolean hasPseudorangeUncertaintyInMeters() {
-        return isFlagSet(HAS_PSEUDORANGE_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the pseudorange's uncertainty (1-Sigma) in meters.
-     * The value contains the 'pseudorange' and 'clock' uncertainty in it.
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasPseudorangeUncertaintyInMeters()} is true.
-     */
-    public double getPseudorangeUncertaintyInMeters() {
-        return mPseudorangeUncertaintyInMeters;
-    }
-
-    /**
-     * Sets the pseudo-range's uncertainty (1-Sigma) in meters.
-     */
-    public void setPseudorangeUncertaintyInMeters(double value) {
-        setFlag(HAS_PSEUDORANGE_UNCERTAINTY);
-        mPseudorangeUncertaintyInMeters = value;
-    }
-
-    /**
-     * Resets the pseudo-range's uncertainty (1-Sigma) in meters.
-     */
-    public void resetPseudorangeUncertaintyInMeters() {
-        resetFlag(HAS_PSEUDORANGE_UNCERTAINTY);
-        mPseudorangeUncertaintyInMeters = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise.
-     */
-    public boolean hasCodePhaseInChips() {
-        return isFlagSet(HAS_CODE_PHASE);
-    }
-
-    /**
-     * Gets the fraction of the current C/A code cycle.
-     * Range: [0, 1023]
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
-     * The reported code-phase includes {@link #getCodePhaseUncertaintyInChips()}.
-     *
-     * The value is only available if {@link #hasCodePhaseInChips()} is true.
-     */
-    public double getCodePhaseInChips() {
-        return mCodePhaseInChips;
-    }
-
-    /**
-     * Sets the Code-phase in chips.
-     */
-    public void setCodePhaseInChips(double value) {
-        setFlag(HAS_CODE_PHASE);
-        mCodePhaseInChips = value;
-    }
-
-    /**
-     * Resets the Code-phase in chips.
-     */
-    public void resetCodePhaseInChips() {
-        resetFlag(HAS_CODE_PHASE);
-        mCodePhaseInChips = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise.
-     */
-    public boolean hasCodePhaseUncertaintyInChips() {
-        return isFlagSet(HAS_CODE_PHASE_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the code-phase's uncertainty (1-Sigma) as a fraction of chips.
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasCodePhaseUncertaintyInChips()} is true.
-     */
-    public double getCodePhaseUncertaintyInChips() {
-        return mCodePhaseUncertaintyInChips;
-    }
-
-    /**
-     * Sets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
-     */
-    public void setCodePhaseUncertaintyInChips(double value) {
-        setFlag(HAS_CODE_PHASE_UNCERTAINTY);
-        mCodePhaseUncertaintyInChips = value;
-    }
-
-    /**
-     * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
-     */
-    public void resetCodePhaseUncertaintyInChips() {
-        resetFlag(HAS_CODE_PHASE_UNCERTAINTY);
-        mCodePhaseUncertaintyInChips = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise.
-     */
-    public boolean hasCarrierFrequencyInHz() {
+    public boolean hasCarrierFrequencyHz() {
         return isFlagSet(HAS_CARRIER_FREQUENCY);
     }
 
@@ -730,26 +535,26 @@
      * Gets the carrier frequency at which codes and messages are modulated, it can be L1 or L2.
      * If the field is not set, the carrier frequency corresponds to L1.
      *
-     * The value is only available if {@link #hasCarrierFrequencyInHz()} is true.
+     * The value is only available if {@link #hasCarrierFrequencyHz()} is true.
      */
-    public float getCarrierFrequencyInHz() {
-        return mCarrierFrequencyInHz;
+    public float getCarrierFrequencyHz() {
+        return mCarrierFrequencyHz;
     }
 
     /**
      * Sets the Carrier frequency (L1 or L2) in Hz.
      */
-    public void setCarrierFrequencyInHz(float carrierFrequencyInHz) {
+    public void setCarrierFrequencyHz(float carrierFrequencyHz) {
         setFlag(HAS_CARRIER_FREQUENCY);
-        mCarrierFrequencyInHz = carrierFrequencyInHz;
+        mCarrierFrequencyHz = carrierFrequencyHz;
     }
 
     /**
      * Resets the Carrier frequency (L1 or L2) in Hz.
      */
-    public void resetCarrierFrequencyInHz() {
+    public void resetCarrierFrequencyHz() {
         resetFlag(HAS_CARRIER_FREQUENCY);
-        mCarrierFrequencyInHz = Float.NaN;
+        mCarrierFrequencyHz = Float.NaN;
     }
 
     /**
@@ -761,7 +566,7 @@
 
     /**
      * The number of full carrier cycles between the satellite and the receiver.
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+     * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
      *
      * The value is only available if {@link #hasCarrierCycles()} is true.
      */
@@ -797,7 +602,7 @@
      * Range: [0.0, 1.0].
      * This is usually the fractional part of the complete carrier phase measurement.
      *
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+     * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
      * The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
      *
      * The value is only available if {@link #hasCarrierPhase()} is true.
@@ -856,183 +661,17 @@
     }
 
     /**
-     * Gets a value indicating the 'loss of lock' state of the event.
-     */
-    @LossOfLockStatus
-    public byte getLossOfLock() {
-        return mLossOfLock;
-    }
-
-    /**
-     * Sets the 'loss of lock' status.
-     */
-    public void setLossOfLock(@LossOfLockStatus byte value) {
-        mLossOfLock = value;
-    }
-
-    /**
-     * Gets a string representation of the 'loss of lock'.
-     * For internal and logging use only.
-     */
-    private String getLossOfLockString() {
-        switch (mLossOfLock) {
-            case LOSS_OF_LOCK_UNKNOWN:
-                return "Unknown";
-            case LOSS_OF_LOCK_OK:
-                return "Ok";
-            case LOSS_OF_LOCK_CYCLE_SLIP:
-                return "CycleSlip";
-            default:
-                return "<Invalid:" + mLossOfLock + ">";
-        }
-    }
-
-    /**
-     * Returns true if {@link #getBitNumber()} is available, false otherwise.
-     */
-    public boolean hasBitNumber() {
-        return isFlagSet(HAS_BIT_NUMBER);
-    }
-
-    /**
-     * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week).
-     *
-     * The value is only available if {@link #hasBitNumber()} is true.
-     */
-    public int getBitNumber() {
-        return mBitNumber;
-    }
-
-    /**
-     * Sets the bit number within the broadcast frame.
-     */
-    public void setBitNumber(int bitNumber) {
-        setFlag(HAS_BIT_NUMBER);
-        mBitNumber = bitNumber;
-    }
-
-    /**
-     * Resets the bit number within the broadcast frame.
-     */
-    public void resetBitNumber() {
-        resetFlag(HAS_BIT_NUMBER);
-        mBitNumber = Integer.MIN_VALUE;
-    }
-
-    /**
-     * Returns true if {@link #getTimeFromLastBitInMs()} is available, false otherwise.
-     */
-    public boolean hasTimeFromLastBitInMs() {
-        return isFlagSet(HAS_TIME_FROM_LAST_BIT);
-    }
-
-    /**
-     * Gets the elapsed time since the last received bit in milliseconds.
-     * Range: [0, 20].
-     *
-     * The value is only available if {@link #hasTimeFromLastBitInMs()} is true.
-     */
-    public short getTimeFromLastBitInMs() {
-        return mTimeFromLastBitInMs;
-    }
-
-    /**
-     * Sets the elapsed time since the last received bit in milliseconds.
-     */
-    public void setTimeFromLastBitInMs(short value) {
-        setFlag(HAS_TIME_FROM_LAST_BIT);
-        mTimeFromLastBitInMs = value;
-    }
-
-    /**
-     * Resets the elapsed time since the last received bit in milliseconds.
-     */
-    public void resetTimeFromLastBitInMs() {
-        resetFlag(HAS_TIME_FROM_LAST_BIT);
-        mTimeFromLastBitInMs = Short.MIN_VALUE;
-    }
-
-    /**
-     * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise.
-     */
-    public boolean hasDopplerShiftInHz() {
-        return isFlagSet(HAS_DOPPLER_SHIFT);
-    }
-
-    /**
-     * Gets the Doppler Shift in Hz.
-     * A positive value indicates that the SV is moving toward the receiver.
-     *
-     * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
-     * The reported doppler shift includes {@link #getDopplerShiftUncertaintyInHz()}.
-     *
-     * The value is only available if {@link #hasDopplerShiftInHz()} is true.
-     */
-    public double getDopplerShiftInHz() {
-        return mDopplerShiftInHz;
-    }
-
-    /**
-     * Sets the Doppler shift in Hz.
-     */
-    public void setDopplerShiftInHz(double value) {
-        setFlag(HAS_DOPPLER_SHIFT);
-        mDopplerShiftInHz = value;
-    }
-
-    /**
-     * Resets the Doppler shift in Hz.
-     */
-    public void resetDopplerShiftInHz() {
-        resetFlag(HAS_DOPPLER_SHIFT);
-        mDopplerShiftInHz = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise.
-     */
-    public boolean hasDopplerShiftUncertaintyInHz() {
-        return isFlagSet(HAS_DOPPLER_SHIFT_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the Doppler's Shift uncertainty (1-Sigma) in Hz.
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasDopplerShiftUncertaintyInHz()} is true.
-     */
-    public double getDopplerShiftUncertaintyInHz() {
-        return mDopplerShiftUncertaintyInHz;
-    }
-
-    /**
-     * Sets the Doppler's shift uncertainty (1-Sigma) in Hz.
-     */
-    public void setDopplerShiftUncertaintyInHz(double value) {
-        setFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
-        mDopplerShiftUncertaintyInHz = value;
-    }
-
-    /**
-     * Resets the Doppler's shift uncertainty (1-Sigma) in Hz.
-     */
-    public void resetDopplerShiftUncertaintyInHz() {
-        resetFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
-        mDopplerShiftUncertaintyInHz = Double.NaN;
-    }
-
-    /**
      * Gets a value indicating the 'multipath' state of the event.
      */
     @MultipathIndicator
-    public byte getMultipathIndicator() {
+    public int getMultipathIndicator() {
         return mMultipathIndicator;
     }
 
     /**
      * Sets the 'multi-path' indicator.
      */
-    public void setMultipathIndicator(@MultipathIndicator byte value) {
+    public void setMultipathIndicator(@MultipathIndicator int value) {
         mMultipathIndicator = value;
     }
 
@@ -1085,200 +724,30 @@
         mSnrInDb = Double.NaN;
     }
 
-    /**
-     * Returns true if {@link #getElevationInDeg()} is available, false otherwise.
-     */
-    public boolean hasElevationInDeg() {
-        return isFlagSet(HAS_ELEVATION);
-    }
-
-    /**
-     * Gets the Elevation in degrees.
-     * Range: [-90, 90]
-     * The reported elevation includes {@link #getElevationUncertaintyInDeg()}.
-     *
-     * The value is only available if {@link #hasElevationInDeg()} is true.
-     */
-    public double getElevationInDeg() {
-        return mElevationInDeg;
-    }
-
-    /**
-     * Sets the Elevation in degrees.
-     */
-    public void setElevationInDeg(double elevationInDeg) {
-        setFlag(HAS_ELEVATION);
-        mElevationInDeg = elevationInDeg;
-    }
-
-    /**
-     * Resets the Elevation in degrees.
-     */
-    public void resetElevationInDeg() {
-        resetFlag(HAS_ELEVATION);
-        mElevationInDeg = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise.
-     */
-    public boolean hasElevationUncertaintyInDeg() {
-        return isFlagSet(HAS_ELEVATION_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the elevation's uncertainty (1-Sigma) in degrees.
-     * Range: [0, 90]
-     *
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasElevationUncertaintyInDeg()} is true.
-     */
-    public double getElevationUncertaintyInDeg() {
-        return mElevationUncertaintyInDeg;
-    }
-
-    /**
-     * Sets the elevation's uncertainty (1-Sigma) in degrees.
-     */
-    public void setElevationUncertaintyInDeg(double value) {
-        setFlag(HAS_ELEVATION_UNCERTAINTY);
-        mElevationUncertaintyInDeg = value;
-    }
-
-    /**
-     * Resets the elevation's uncertainty (1-Sigma) in degrees.
-     */
-    public void resetElevationUncertaintyInDeg() {
-        resetFlag(HAS_ELEVATION_UNCERTAINTY);
-        mElevationUncertaintyInDeg = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise.
-     */
-    public boolean hasAzimuthInDeg() {
-        return isFlagSet(HAS_AZIMUTH);
-    }
-
-    /**
-     * Gets the azimuth in degrees.
-     * Range: [0, 360).
-     *
-     * The reported azimuth includes {@link #getAzimuthUncertaintyInDeg()}.
-     *
-     * The value is only available if {@link #hasAzimuthInDeg()} is true.
-     */
-    public double getAzimuthInDeg() {
-        return mAzimuthInDeg;
-    }
-
-    /**
-     * Sets the Azimuth in degrees.
-     */
-    public void setAzimuthInDeg(double value) {
-        setFlag(HAS_AZIMUTH);
-        mAzimuthInDeg = value;
-    }
-
-    /**
-     * Resets the Azimuth in degrees.
-     */
-    public void resetAzimuthInDeg() {
-        resetFlag(HAS_AZIMUTH);
-        mAzimuthInDeg = Double.NaN;
-    }
-
-    /**
-     * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise.
-     */
-    public boolean hasAzimuthUncertaintyInDeg() {
-        return isFlagSet(HAS_AZIMUTH_UNCERTAINTY);
-    }
-
-    /**
-     * Gets the azimuth's uncertainty (1-Sigma) in degrees.
-     * Range: [0, 180].
-     *
-     * The uncertainty is represented as an absolute (single sided) value.
-     *
-     * The value is only available if {@link #hasAzimuthUncertaintyInDeg()} is true.
-     */
-    public double getAzimuthUncertaintyInDeg() {
-        return mAzimuthUncertaintyInDeg;
-    }
-
-    /**
-     * Sets the Azimuth's uncertainty (1-Sigma) in degrees.
-     */
-    public void setAzimuthUncertaintyInDeg(double value) {
-        setFlag(HAS_AZIMUTH_UNCERTAINTY);
-        mAzimuthUncertaintyInDeg = value;
-    }
-
-    /**
-     * Resets the Azimuth's uncertainty (1-Sigma) in degrees.
-     */
-    public void resetAzimuthUncertaintyInDeg() {
-        resetFlag(HAS_AZIMUTH_UNCERTAINTY);
-        mAzimuthUncertaintyInDeg = Double.NaN;
-    }
-
-    /**
-     * Gets a flag indicating whether the GNSS represented by the measurement was used for computing
-     * the most recent fix.
-     *
-     * @return A non-null value if the data is available, null otherwise.
-     */
-    public boolean isUsedInFix() {
-        return mUsedInFix;
-    }
-
-    /**
-     * Sets the Used-in-Fix flag.
-     */
-    public void setUsedInFix(boolean value) {
-        mUsedInFix = value;
-    }
-
     public static final Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
         @Override
         public GnssMeasurement createFromParcel(Parcel parcel) {
             GnssMeasurement gnssMeasurement = new GnssMeasurement();
 
             gnssMeasurement.mFlags = parcel.readInt();
-            gnssMeasurement.mSvid = (short) parcel.readInt();
-            gnssMeasurement.mConstellationType = parcel.readByte();
-            gnssMeasurement.mTimeOffsetInNs = parcel.readDouble();
-            gnssMeasurement.mState = (short) parcel.readInt();
-            gnssMeasurement.mReceivedSvTimeInNs = parcel.readLong();
-            gnssMeasurement.mReceivedSvTimeUncertaintyInNs = parcel.readLong();
-            gnssMeasurement.mCn0InDbHz = parcel.readDouble();
-            gnssMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble();
-            gnssMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble();
-            gnssMeasurement.mAccumulatedDeltaRangeState = (short) parcel.readInt();
-            gnssMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble();
-            gnssMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble();
-            gnssMeasurement.mPseudorangeInMeters = parcel.readDouble();
-            gnssMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble();
-            gnssMeasurement.mCodePhaseInChips = parcel.readDouble();
-            gnssMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble();
-            gnssMeasurement.mCarrierFrequencyInHz = parcel.readFloat();
+            gnssMeasurement.mSvid = parcel.readInt();
+            gnssMeasurement.mConstellationType = parcel.readInt();
+            gnssMeasurement.mTimeOffsetNanos = parcel.readDouble();
+            gnssMeasurement.mState = parcel.readInt();
+            gnssMeasurement.mReceivedSvTimeNanos = parcel.readLong();
+            gnssMeasurement.mReceivedSvTimeUncertaintyNanos = parcel.readLong();
+            gnssMeasurement.mCn0DbHz = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateMetersPerSecond = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateUncertaintyMetersPerSecond = parcel.readDouble();
+            gnssMeasurement.mAccumulatedDeltaRangeState = parcel.readInt();
+            gnssMeasurement.mAccumulatedDeltaRangeMeters = parcel.readDouble();
+            gnssMeasurement.mAccumulatedDeltaRangeUncertaintyMeters = parcel.readDouble();
+            gnssMeasurement.mCarrierFrequencyHz = parcel.readFloat();
             gnssMeasurement.mCarrierCycles = parcel.readLong();
             gnssMeasurement.mCarrierPhase = parcel.readDouble();
             gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
-            gnssMeasurement.mLossOfLock = parcel.readByte();
-            gnssMeasurement.mBitNumber = parcel.readInt();
-            gnssMeasurement.mTimeFromLastBitInMs = (short) parcel.readInt();
-            gnssMeasurement.mDopplerShiftInHz = parcel.readDouble();
-            gnssMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble();
-            gnssMeasurement.mMultipathIndicator = parcel.readByte();
+            gnssMeasurement.mMultipathIndicator = parcel.readInt();
             gnssMeasurement.mSnrInDb = parcel.readDouble();
-            gnssMeasurement.mElevationInDeg = parcel.readDouble();
-            gnssMeasurement.mElevationUncertaintyInDeg = parcel.readDouble();
-            gnssMeasurement.mAzimuthInDeg = parcel.readDouble();
-            gnssMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
-            gnssMeasurement.mUsedInFix = parcel.readInt() != 0;
 
             return gnssMeasurement;
         }
@@ -1293,37 +762,23 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mFlags);
         parcel.writeInt(mSvid);
-        parcel.writeByte(mConstellationType);
-        parcel.writeDouble(mTimeOffsetInNs);
+        parcel.writeInt(mConstellationType);
+        parcel.writeDouble(mTimeOffsetNanos);
         parcel.writeInt(mState);
-        parcel.writeLong(mReceivedSvTimeInNs);
-        parcel.writeLong(mReceivedSvTimeUncertaintyInNs);
-        parcel.writeDouble(mCn0InDbHz);
-        parcel.writeDouble(mPseudorangeRateInMetersPerSec);
-        parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec);
+        parcel.writeLong(mReceivedSvTimeNanos);
+        parcel.writeLong(mReceivedSvTimeUncertaintyNanos);
+        parcel.writeDouble(mCn0DbHz);
+        parcel.writeDouble(mPseudorangeRateMetersPerSecond);
+        parcel.writeDouble(mPseudorangeRateUncertaintyMetersPerSecond);
         parcel.writeInt(mAccumulatedDeltaRangeState);
-        parcel.writeDouble(mAccumulatedDeltaRangeInMeters);
-        parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters);
-        parcel.writeDouble(mPseudorangeInMeters);
-        parcel.writeDouble(mPseudorangeUncertaintyInMeters);
-        parcel.writeDouble(mCodePhaseInChips);
-        parcel.writeDouble(mCodePhaseUncertaintyInChips);
-        parcel.writeFloat(mCarrierFrequencyInHz);
+        parcel.writeDouble(mAccumulatedDeltaRangeMeters);
+        parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyMeters);
+        parcel.writeFloat(mCarrierFrequencyHz);
         parcel.writeLong(mCarrierCycles);
         parcel.writeDouble(mCarrierPhase);
         parcel.writeDouble(mCarrierPhaseUncertainty);
-        parcel.writeByte(mLossOfLock);
-        parcel.writeInt(mBitNumber);
-        parcel.writeInt(mTimeFromLastBitInMs);
-        parcel.writeDouble(mDopplerShiftInHz);
-        parcel.writeDouble(mDopplerShiftUncertaintyInHz);
-        parcel.writeByte(mMultipathIndicator);
+        parcel.writeInt(mMultipathIndicator);
         parcel.writeDouble(mSnrInDb);
-        parcel.writeDouble(mElevationInDeg);
-        parcel.writeDouble(mElevationUncertaintyInDeg);
-        parcel.writeDouble(mAzimuthInDeg);
-        parcel.writeDouble(mAzimuthUncertaintyInDeg);
-        parcel.writeInt(mUsedInFix ? 1 : 0);
     }
 
     @Override
@@ -1339,25 +794,25 @@
 
         builder.append(String.format(format, "Svid", mSvid));
         builder.append(String.format(format, "ConstellationType", mConstellationType));
-        builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
+        builder.append(String.format(format, "TimeOffsetNanos", mTimeOffsetNanos));
 
         builder.append(String.format(format, "State", getStateString()));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "ReceivedSvTimeInNs",
-                mReceivedSvTimeInNs,
-                "ReceivedSvTimeUncertaintyInNs",
-                mReceivedSvTimeUncertaintyInNs));
+                "ReceivedSvTimeNanos",
+                mReceivedSvTimeNanos,
+                "ReceivedSvTimeUncertaintyNanos",
+                mReceivedSvTimeUncertaintyNanos));
 
-        builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz));
+        builder.append(String.format(format, "Cn0DbHz", mCn0DbHz));
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "PseudorangeRateInMetersPerSec",
-                mPseudorangeRateInMetersPerSec,
-                "PseudorangeRateUncertaintyInMetersPerSec",
-                mPseudorangeRateUncertaintyInMetersPerSec));
+                "PseudorangeRateMetersPerSecond",
+                mPseudorangeRateMetersPerSecond,
+                "PseudorangeRateUncertaintyMetersPerSecond",
+                mPseudorangeRateUncertaintyMetersPerSecond));
         builder.append(String.format(
                 format,
                 "PseudorangeRateIsCorrected",
@@ -1370,29 +825,15 @@
 
         builder.append(String.format(
                 formatWithUncertainty,
-                "AccumulatedDeltaRangeInMeters",
-                mAccumulatedDeltaRangeInMeters,
-                "AccumulatedDeltaRangeUncertaintyInMeters",
-                mAccumulatedDeltaRangeUncertaintyInMeters));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "PseudorangeInMeters",
-                hasPseudorangeInMeters() ? mPseudorangeInMeters : null,
-                "PseudorangeUncertaintyInMeters",
-                hasPseudorangeUncertaintyInMeters() ? mPseudorangeUncertaintyInMeters : null));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "CodePhaseInChips",
-                hasCodePhaseInChips() ? mCodePhaseInChips : null,
-                "CodePhaseUncertaintyInChips",
-                hasCodePhaseUncertaintyInChips() ? mCodePhaseUncertaintyInChips : null));
+                "AccumulatedDeltaRangeMeters",
+                mAccumulatedDeltaRangeMeters,
+                "AccumulatedDeltaRangeUncertaintyMeters",
+                mAccumulatedDeltaRangeUncertaintyMeters));
 
         builder.append(String.format(
                 format,
-                "CarrierFrequencyInHz",
-                hasCarrierFrequencyInHz() ? mCarrierFrequencyInHz : null));
+                "CarrierFrequencyHz",
+                hasCarrierFrequencyHz() ? mCarrierFrequencyHz : null));
 
         builder.append(String.format(
                 format,
@@ -1406,25 +847,6 @@
                 "CarrierPhaseUncertainty",
                 hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
 
-        builder.append(String.format(format, "LossOfLock", getLossOfLockString()));
-
-        builder.append(String.format(
-                format,
-                "BitNumber",
-                hasBitNumber() ? mBitNumber : null));
-
-        builder.append(String.format(
-                format,
-                "TimeFromLastBitInMs",
-                hasTimeFromLastBitInMs() ? mTimeFromLastBitInMs : null));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "DopplerShiftInHz",
-                hasDopplerShiftInHz() ? mDopplerShiftInHz : null,
-                "DopplerShiftUncertaintyInHz",
-                hasDopplerShiftUncertaintyInHz() ? mDopplerShiftUncertaintyInHz : null));
-
         builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString()));
 
         builder.append(String.format(
@@ -1432,58 +854,28 @@
                 "SnrInDb",
                 hasSnrInDb() ? mSnrInDb : null));
 
-        builder.append(String.format(
-                formatWithUncertainty,
-                "ElevationInDeg",
-                hasElevationInDeg() ? mElevationInDeg : null,
-                "ElevationUncertaintyInDeg",
-                hasElevationUncertaintyInDeg() ? mElevationUncertaintyInDeg : null));
-
-        builder.append(String.format(
-                formatWithUncertainty,
-                "AzimuthInDeg",
-                hasAzimuthInDeg() ? mAzimuthInDeg : null,
-                "AzimuthUncertaintyInDeg",
-                hasAzimuthUncertaintyInDeg() ? mAzimuthUncertaintyInDeg : null));
-
-        builder.append(String.format(format, "UsedInFix", mUsedInFix));
-
         return builder.toString();
     }
 
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
-        setSvid((short) 0);
-        setTimeOffsetInNs(Long.MIN_VALUE);
+        setSvid(0);
+        setTimeOffsetNanos(Long.MIN_VALUE);
         setState(STATE_UNKNOWN);
-        setReceivedSvTimeInNs(Long.MIN_VALUE);
-        setReceivedSvTimeUncertaintyInNs(Long.MAX_VALUE);
-        setCn0InDbHz(Double.MIN_VALUE);
-        setPseudorangeRateInMetersPerSec(Double.MIN_VALUE);
-        setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE);
+        setReceivedSvTimeNanos(Long.MIN_VALUE);
+        setReceivedSvTimeUncertaintyNanos(Long.MAX_VALUE);
+        setCn0DbHz(Double.MIN_VALUE);
+        setPseudorangeRateMetersPerSecond(Double.MIN_VALUE);
+        setPseudorangeRateUncertaintyMetersPerSecond(Double.MIN_VALUE);
         setAccumulatedDeltaRangeState(ADR_STATE_UNKNOWN);
-        setAccumulatedDeltaRangeInMeters(Double.MIN_VALUE);
-        setAccumulatedDeltaRangeUncertaintyInMeters(Double.MIN_VALUE);
-        resetPseudorangeInMeters();
-        resetPseudorangeUncertaintyInMeters();
-        resetCodePhaseInChips();
-        resetCodePhaseUncertaintyInChips();
-        resetCarrierFrequencyInHz();
+        setAccumulatedDeltaRangeMeters(Double.MIN_VALUE);
+        setAccumulatedDeltaRangeUncertaintyMeters(Double.MIN_VALUE);
+        resetCarrierFrequencyHz();
         resetCarrierCycles();
         resetCarrierPhase();
         resetCarrierPhaseUncertainty();
-        setLossOfLock(LOSS_OF_LOCK_UNKNOWN);
-        resetBitNumber();
-        resetTimeFromLastBitInMs();
-        resetDopplerShiftInHz();
-        resetDopplerShiftUncertaintyInHz();
         setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
         resetSnrInDb();
-        resetElevationInDeg();
-        resetElevationUncertaintyInDeg();
-        resetAzimuthInDeg();
-        resetAzimuthUncertaintyInDeg();
-        setUsedInFix(false);
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index b744a03..86841ff 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -33,46 +33,46 @@
  * Events are delivered to registered instances of {@link Callback}.
  */
 public final class GnssMeasurementsEvent implements Parcelable {
-    /** The status of GPS measurements event. */
+    /** The status of GNSS measurements event. */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
     public @interface GnssMeasurementsStatus {}
 
     /**
-     * The system does not support tracking of GPS Measurements. This status will not change in the
+     * The system does not support tracking of GNSS Measurements. This status will not change in the
      * future.
      */
     public static final int STATUS_NOT_SUPPORTED = 0;
 
     /**
-     * GPS Measurements are successfully being tracked, it will receive updates once they are
+     * GNSS Measurements are successfully being tracked, it will receive updates once they are
      * available.
      */
     public static final int STATUS_READY = 1;
 
     /**
-     * GPS provider or Location is disabled, updates will not be received until they are enabled.
+     * GNSS provider or Location is disabled, updates will not be received until they are enabled.
      */
-    public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+    public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
 
     private final GnssClock mClock;
     private final Collection<GnssMeasurement> mReadOnlyMeasurements;
 
     /**
-     * Used for receiving GPS satellite measurements from the GPS engine.
+     * Used for receiving GNSS satellite measurements from the GNSS engine.
      * Each measurement contains raw and computed data identifying a satellite.
      * You can implement this interface and call
-     * {@link LocationManager#registerGnssMeasurementCallback}.
+     * {@link LocationManager#registerGnssMeasurementsCallback}.
      */
     public static abstract class Callback {
 
         /**
-         * Returns the latest collected GPS Measurements.
+         * Reports the latest collected GNSS Measurements.
          */
         public void onGnssMeasurementsReceived(GnssMeasurementsEvent eventArgs) {}
 
         /**
-         * Returns the latest status of the GPS Measurements sub-system.
+         * Reports the latest status of the GNSS Measurements sub-system.
          */
         public void onStatusChanged(@GnssMeasurementsStatus int status) {}
     }
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index faefd0bb..c0608e0 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -34,58 +34,57 @@
 
     /** The type of the GPS Clock. */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_GPS_L1CA, MESSAGE_TYPE_GPS_L2CNAV,
-        MESSAGE_TYPE_GPS_L5CNAV, MESSAGE_TYPE_GPS_CNAV2, MESSAGE_TYPE_GLO_L1CA, MESSAGE_TYPE_BDS_D1,
-        MESSAGE_TYPE_BDS_D2, MESSAGE_TYPE_GAL_I, MESSAGE_TYPE_GAL_F})
+    @IntDef({TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2,
+        TYPE_GLO_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_GAL_I, TYPE_GAL_F})
     public @interface GnssNavigationMessageType {}
 
     // The following enumerations must be in sync with the values declared in gps.h
 
     /** Message type unknown */
-    public static final short MESSAGE_TYPE_UNKNOWN = 0;
+    public static final int TYPE_UNKNOWN = 0;
     /** GPS L1 C/A message contained in the structure.  */
-    public static final short MESSAGE_TYPE_GPS_L1CA = 0x0101;
+    public static final int TYPE_GPS_L1CA = 0x0101;
     /** GPS L2-CNAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GPS_L2CNAV = 0x0102;
+    public static final int TYPE_GPS_L2CNAV = 0x0102;
     /** GPS L5-CNAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GPS_L5CNAV = 0x0103;
+    public static final int TYPE_GPS_L5CNAV = 0x0103;
     /** GPS CNAV-2 message contained in the structure. */
-    public static final short MESSAGE_TYPE_GPS_CNAV2 = 0x0104;
+    public static final int TYPE_GPS_CNAV2 = 0x0104;
     /** Glonass L1 CA message contained in the structure. */
-    public static final short MESSAGE_TYPE_GLO_L1CA = 0x0301;
+    public static final int TYPE_GLO_L1CA = 0x0301;
     /** Beidou D1 message contained in the structure. */
-    public static final short MESSAGE_TYPE_BDS_D1 = 0x0501;
+    public static final int TYPE_BDS_D1 = 0x0501;
     /** Beidou D2 message contained in the structure. */
-    public static final short MESSAGE_TYPE_BDS_D2 = 0x0502;
+    public static final int TYPE_BDS_D2 = 0x0502;
     /** Galileo I/NAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GAL_I = 0x0601;
+    public static final int TYPE_GAL_I = 0x0601;
     /** Galileo F/NAV message contained in the structure. */
-    public static final short MESSAGE_TYPE_GAL_F = 0x0602;
+    public static final int TYPE_GAL_F = 0x0602;
 
     /**
      * The Navigation Message Status is 'unknown'.
      */
-    public static final short STATUS_UNKNOWN = 0;
+    public static final int STATUS_UNKNOWN = 0;
 
     /**
      * The Navigation Message was received without any parity error in its navigation words.
      */
-    public static final short STATUS_PARITY_PASSED = (1<<0);
+    public static final int STATUS_PARITY_PASSED = (1<<0);
 
     /**
      * The Navigation Message was received with words that failed parity check, but the receiver was
      * able to correct those words.
      */
-    public static final short STATUS_PARITY_REBUILT = (1<<1);
+    public static final int STATUS_PARITY_REBUILT = (1<<1);
 
     // End enumerations in sync with gps.h
 
-    private short mType;
-    private short mSvid;
-    private short mMessageId;
-    private short mSubmessageId;
+    private int mType;
+    private int mSvid;
+    private int mMessageId;
+    private int mSubmessageId;
     private byte[] mData;
-    private short mStatus;
+    private int mStatus;
 
     GnssNavigationMessage() {
         initialize();
@@ -114,14 +113,14 @@
      * Gets the type of the navigation message contained in the object.
      */
     @GnssNavigationMessageType
-    public short getType() {
+    public int getType() {
         return mType;
     }
 
     /**
      * Sets the type of the navigation message.
      */
-    public void setType(@GnssNavigationMessageType short value) {
+    public void setType(@GnssNavigationMessageType int value) {
         mType = value;
     }
 
@@ -131,25 +130,25 @@
      */
     private String getTypeString() {
         switch (mType) {
-            case MESSAGE_TYPE_UNKNOWN:
+            case TYPE_UNKNOWN:
                 return "Unknown";
-            case MESSAGE_TYPE_GPS_L1CA:
+            case TYPE_GPS_L1CA:
                 return "GPS L1 C/A";
-            case MESSAGE_TYPE_GPS_L2CNAV:
+            case TYPE_GPS_L2CNAV:
                 return "GPS L2-CNAV";
-            case MESSAGE_TYPE_GPS_L5CNAV:
+            case TYPE_GPS_L5CNAV:
                 return "GPS L5-CNAV";
-            case MESSAGE_TYPE_GPS_CNAV2:
+            case TYPE_GPS_CNAV2:
                 return "GPS CNAV2";
-            case MESSAGE_TYPE_GLO_L1CA:
+            case TYPE_GLO_L1CA:
                 return "Glonass L1 C/A";
-            case MESSAGE_TYPE_BDS_D1:
+            case TYPE_BDS_D1:
                 return "Beidou D1";
-            case MESSAGE_TYPE_BDS_D2:
+            case TYPE_BDS_D2:
                 return "Beidou D2";
-            case MESSAGE_TYPE_GAL_I:
+            case TYPE_GAL_I:
                 return "Galileo I";
-            case MESSAGE_TYPE_GAL_F:
+            case TYPE_GAL_F:
                 return "Galileo F";
             default:
                 return "<Invalid:" + mType + ">";
@@ -160,14 +159,14 @@
      * Gets the Pseudo-random number.
      * Range: [1, 32].
      */
-    public short getSvid() {
+    public int getSvid() {
         return mSvid;
     }
 
     /**
      * Sets the Pseud-random number.
      */
-    public void setSvid(short value) {
+    public void setSvid(int value) {
         mSvid = value;
     }
 
@@ -177,14 +176,14 @@
      * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
      * Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1.
      */
-    public short getMessageId() {
+    public int getMessageId() {
         return mMessageId;
     }
 
     /**
      * Sets the Message Identifier.
      */
-    public void setMessageId(short value) {
+    public void setMessageId(int value) {
         mMessageId = value;
     }
 
@@ -194,14 +193,14 @@
      * (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds
      * to the sub-frame Id of the navigation message.
      */
-    public short getSubmessageId() {
+    public int getSubmessageId() {
         return mSubmessageId;
     }
 
     /**
      * Sets the Sub-message identifier.
      */
-    public void setSubmessageId(short value) {
+    public void setSubmessageId(int value) {
         mSubmessageId = value;
     }
 
@@ -228,14 +227,14 @@
     /**
      * Gets the Status of the navigation message contained in the object.
      */
-    public short getStatus() {
+    public int getStatus() {
         return mStatus;
     }
 
     /**
      * Sets the status of the navigation message.
      */
-    public void setStatus(short value) {
+    public void setStatus(int value) {
         mStatus = value;
     }
 
@@ -262,10 +261,10 @@
         public GnssNavigationMessage createFromParcel(Parcel parcel) {
             GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
 
-            navigationMessage.setType((short) parcel.readInt());
-            navigationMessage.setSvid((short) parcel.readInt());
-            navigationMessage.setMessageId((short) parcel.readInt());
-            navigationMessage.setSubmessageId((short) parcel.readInt());
+            navigationMessage.setType(parcel.readInt());
+            navigationMessage.setSvid(parcel.readInt());
+            navigationMessage.setMessageId(parcel.readInt());
+            navigationMessage.setSubmessageId(parcel.readInt());
 
             int dataLength = parcel.readInt();
             byte[] data = new byte[dataLength];
@@ -274,7 +273,7 @@
 
             if (parcel.dataAvail() >= Integer.SIZE) {
                 int status = parcel.readInt();
-                navigationMessage.setStatus((short) status);
+                navigationMessage.setStatus(status);
             } else {
                 navigationMessage.setStatus(STATUS_UNKNOWN);
             }
@@ -328,7 +327,7 @@
     }
 
     private void initialize() {
-        mType = MESSAGE_TYPE_UNKNOWN;
+        mType = TYPE_UNKNOWN;
         mSvid = 0;
         mMessageId = -1;
         mSubmessageId = -1;
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
index 19c82e9..0df730d 100644
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -32,7 +32,7 @@
 public final class GnssNavigationMessageEvent implements Parcelable {
     /** The status of GPS measurements event. */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+    @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
     public @interface GnssNavigationMessageStatus {}
 
     /**
@@ -50,7 +50,7 @@
     /**
      * GPS provider or Location is disabled, updated will not be received until they are enabled.
      */
-    public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+    public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
 
     private final GnssNavigationMessage mNavigationMessage;
 
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 06ce30c..2a42fc6 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -27,19 +27,19 @@
  */
 public final class GnssStatus {
     /** Unknown constellation type. */
-    public static final byte CONSTELLATION_UNKNOWN = 0;
+    public static final int CONSTELLATION_UNKNOWN = 0;
     /** Constellation type constant for GPS. */
-    public static final byte CONSTELLATION_GPS = 1;
+    public static final int CONSTELLATION_GPS = 1;
     /** Constellation type constant for SBAS. */
-    public static final byte CONSTELLATION_SBAS = 2;
+    public static final int CONSTELLATION_SBAS = 2;
     /** Constellation type constant for Glonass. */
-    public static final byte CONSTELLATION_GLONASS = 3;
+    public static final int CONSTELLATION_GLONASS = 3;
     /** Constellation type constant for QZSS. */
-    public static final byte CONSTELLATION_QZSS = 4;
+    public static final int CONSTELLATION_QZSS = 4;
     /** Constellation type constant for Beidou. */
-    public static final byte CONSTELLATION_BEIDOU = 5;
+    public static final int CONSTELLATION_BEIDOU = 5;
     /** Constellation type constant for Galileo. */
-    public static final byte CONSTELLATION_GALILEO = 6;
+    public static final int CONSTELLATION_GALILEO = 6;
 
     /** Constellation type. */
     @Retention(RetentionPolicy.SOURCE)
@@ -66,16 +66,16 @@
 
     /* These package private values are modified by the LocationManager class */
     /* package */ int[] mSvidWithFlags;
-    /* package */ float[] mSnrs;
+    /* package */ float[] mCn0DbHz;
     /* package */ float[] mElevations;
     /* package */ float[] mAzimuths;
     /* package */ int mSvCount;
 
-    GnssStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+    GnssStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
             float[] azimuths) {
         mSvCount = svCount;
         mSvidWithFlags = svidWithFlags;
-        mSnrs = snrs;
+        mCn0DbHz = cn0s;
         mElevations = elevations;
         mAzimuths = azimuths;
     }
@@ -92,8 +92,8 @@
      * @param satIndex the index of the satellite in the list.
      */
     @ConstellationType
-    public byte getConstellationType(int satIndex) {
-        return (byte) ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
+    public int getConstellationType(int satIndex) {
+        return ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
                 & CONSTELLATION_TYPE_MASK);
     }
 
@@ -109,15 +109,15 @@
      * 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];
+    public float getCn0DbHz(int satIndex) {
+        return mCn0DbHz[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) {
+    public float getElevationDegrees(int satIndex) {
         return 0f;
     }
 
@@ -125,7 +125,7 @@
      * Retrieves the azimuth the satellite at the specified position.
      * @param satIndex the index of the satellite in the list.
      */
-    public float getAzimuth(int satIndex) {
+    public float getAzimuthDegrees(int satIndex) {
         return mAzimuths[satIndex];
     }
 
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
index b86171b..0d2955a 100644
--- a/location/java/android/location/GnssStatusCallback.java
+++ b/location/java/android/location/GnssStatusCallback.java
@@ -32,13 +32,13 @@
 
     /**
      * Called when the GNSS system has received its first fix since starting.
-     * @param ttff the time from start to first fix.
+     * @param ttffMillis the time from start to first fix in milliseconds.
      */
-    public void onFirstFix(int ttff) {}
+    public void onFirstFix(int ttffMillis) {}
 
     /**
      * 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/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 7b3dd7d..bc518f9 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -138,7 +138,7 @@
     // For API-compat a public ctor() is not available
     GpsStatus() {}
 
-    private void setStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+    private void setStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
             float[] azimuths) {
         clearSatellites();
         for (int i = 0; i < svCount; i++) {
@@ -158,7 +158,7 @@
                 }
 
                 satellite.mValid = true;
-                satellite.mSnr = snrs[i];
+                satellite.mSnr = cn0s[i];
                 satellite.mElevation = elevations[i];
                 satellite.mAzimuth = azimuths[i];
                 satellite.mHasEphemeris =
@@ -179,7 +179,7 @@
      */
     void setStatus(GnssStatus status, int timeToFirstFix) {
         mTimeToFirstFix = timeToFirstFix;
-        setStatus(status.mSvCount, status.mSvidWithFlags, status.mSnrs, status.mElevations,
+        setStatus(status.mSvCount, status.mSvidWithFlags, status.mCn0DbHz, status.mElevations,
                 status.mAzimuths);
     }
 
diff --git a/location/java/android/location/IGnssStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl
index 8c7d06e..d84614f 100644
--- a/location/java/android/location/IGnssStatusListener.aidl
+++ b/location/java/android/location/IGnssStatusListener.aidl
@@ -26,7 +26,7 @@
     void onGnssStarted();
     void onGnssStopped();
     void onFirstFix(int ttff);
-    void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] snrs,
+    void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] cn0s,
             in float[] elevations, in float[] azimuths);
     void onNmeaReceived(long timestamp, String nmea);
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 3cd47e7..28db099 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1554,9 +1554,9 @@
 
         @Override
         public void onSvStatusChanged(int svCount, int[] prnWithFlags,
-                float[] snrs, float[] elevations, float[] azimuths) {
+                float[] cn0s, float[] elevations, float[] azimuths) {
             if (mGnssCallback != null) {
-                mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths);
+                mGnssStatus = new GnssStatus(svCount, prnWithFlags, cn0s, elevations, azimuths);
 
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
@@ -1805,7 +1805,7 @@
 
     /**
      * No-op method to keep backward-compatibility.
-     * Don't use it. Use {@link #registerGnssMeasurementCallback} instead.
+     * Don't use it. Use {@link #registerGnssMeasurementsCallback} instead.
      * @hide
      * @deprecated
      */
@@ -1822,8 +1822,8 @@
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
-        return registerGnssMeasurementCallback(callback, null);
+    public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
+        return registerGnssMeasurementsCallback(callback, null);
     }
 
     /**
@@ -1834,14 +1834,14 @@
      * @return {@code true} if the callback was added successfully, {@code false} otherwise.
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback,
+    public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback,
             Handler handler) {
         return mGnssMeasurementCallbackTransport.add(callback, handler);
     }
 
     /**
      * No-op method to keep backward-compatibility.
-     * Don't use it. Use {@link #unregisterGnssMeasurementCallback} instead.
+     * Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead.
      * @hide
      * @deprecated
      */
@@ -1855,7 +1855,7 @@
      *
      * @param callback a {@link GnssMeasurementsEvent.Callback} object to remove.
      */
-    public void unregisterGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
+    public void unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
         mGnssMeasurementCallbackTransport.remove(callback);
     }
 
diff --git a/location/tests/locationtests/src/android/location/GpsStatusTest.java b/location/tests/locationtests/src/android/location/GpsStatusTest.java
index 4808faf..316e88d 100644
--- a/location/tests/locationtests/src/android/location/GpsStatusTest.java
+++ b/location/tests/locationtests/src/android/location/GpsStatusTest.java
@@ -40,7 +40,7 @@
     private GpsStatus mStatus;
     private int mCount;
     private int[] mPrns;
-    private float[] mSnrs;
+    private float[] mCn0s;
     private float[] mElevations;
     private float[] mAzimuth;
     private int mEphemerisMask;
@@ -179,7 +179,7 @@
 
     private void verifySatellites(GpsStatus status) {
         verifySatelliteCount(status, mCount);
-        verifySatellites(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask,
+        verifySatellites(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask,
                 mAlmanacMask, mUsedInFixMask);
     }
 
@@ -187,7 +187,7 @@
             GpsStatus status,
             int count,
             int[] prns,
-            float[] snrs,
+            float[] cn0s,
             float[] elevations,
             float[] azimuth,
             int ephemerisMask,
@@ -197,7 +197,7 @@
             int prn = prns[i];
             GpsSatellite satellite = getSatellite(status, prn);
             assertNotNull(getSatelliteAssertInfo(i, prn, "non-null"), satellite);
-            assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), snrs[i], satellite.getSnr());
+            assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), cn0s[i], satellite.getSnr());
             assertEquals(
                     getSatelliteAssertInfo(i, prn, "Elevation"),
                     elevations[i],
@@ -247,7 +247,7 @@
     }
 
     private void setSatellites(GpsStatus status) throws Exception {
-        set(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
+        set(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
                 mUsedInFixMask);
     }
 
@@ -255,7 +255,7 @@
             GpsStatus status,
             int count,
             int[] prns,
-            float[] snrs,
+            float[] cn0s,
             float[] elevations,
             float[] azimuth,
             int ephemerisMask,
@@ -279,7 +279,7 @@
                 status,
                 count,
                 prns,
-                snrs,
+                cn0s,
                 elevations,
                 azimuth,
                 ephemerisMask,
@@ -333,7 +333,7 @@
         if (!reusePrns) {
             mPrns = generateIntArray(count);
         }
-        mSnrs = generateFloatArray(count);
+        mCn0s = generateFloatArray(count);
         mElevations = generateFloatArray(count);
         mAzimuth = generateFloatArray(count);
         mEphemerisMask = generateMask(mPrns);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 646ab4e..a0e2481 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -644,6 +644,21 @@
     /** 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;
 
+    /**
+     * A key describing a unique ID for the content of a media track.
+     *
+     * <p>This key is used by {@link MediaExtractor}. Some extractors provide multiple encodings
+     * of the same track (e.g. float audio tracks for FLAC and WAV may be expressed as two
+     * tracks via MediaExtractor: a normal PCM track for backward compatibility, and a float PCM
+     * track for added fidelity. Similarly, Dolby Vision extractor may provide a baseline SDR
+     * version of a DV track.) This key can be used to identify which MediaExtractor tracks refer
+     * to the same underlying content.
+     * </p>
+     *
+     * The associated value is an integer.
+     */
+    public static final String KEY_TRACK_ID = "track-id";
+
     /* package private */ MediaFormat(Map<String, Object> map) {
         mMap = map;
     }
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index 3b892cb..537b56d 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -116,7 +116,8 @@
         return UNKNOWN_ERROR;
     }
     if (mSizeIsCached) {
-        return mCachedSize;
+        *size = mCachedSize;
+        return OK;
     }
 
     JNIEnv* env = AndroidRuntime::getJNIEnv();
diff --git a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
index b0f3cc3..5aeebbb 100644
--- a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
+++ b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
+        android:width="24dp"
+        android:height="24dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
diff --git a/packages/DocumentsUI/res/drawable/ic_usb_storage.xml b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
new file mode 100644
index 0000000..2a8d024
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M15 7v4h1v2h-3V5h2l-3,-4,-3 4h2v8H8v-2.07c.7,-.37 1.2,-1.08 1.2,-1.93 0,-1.21,-.99,-2.2,-2.2,-2.2,-1.21 0,-2.2.99,-2.2 2.2 0 .85.5 1.56 1.2 1.93V13c0 1.11.89 2 2 2h3v3.05c-.71.37,-1.2 1.1,-1.2 1.95 0 1.22.99 2.2 2.2 2.2 1.21 0 2.2,-.98 2.2,-2.2 0,-.85,-.49,-1.58,-1.2,-1.95V15h3c1.11 0 2,-.89 2,-2v-2h1V7h-4z"/>
+</vector>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 40bd754..ebc9082 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -82,6 +82,9 @@
         builder.setNegativeButton(android.R.string.cancel, null);
         final AlertDialog dialog = builder.create();
 
+        // Workaround for the problem - virtual keyboard doesn't show on the phone.
+        Shared.ensureKeyboardPresent(context, dialog);
+
         editText.setOnEditorActionListener(
                 new OnEditorActionListener() {
                     @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 99c2d80..26900a7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -17,9 +17,12 @@
 package com.android.documentsui;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.text.format.Time;
+import android.view.WindowManager;
+import android.app.AlertDialog;
 
 import java.text.Collator;
 import java.util.ArrayList;
@@ -155,4 +158,15 @@
 
         return sCollator.compare(lhs, rhs);
     }
+
+    public static boolean isHardwareKeyboardAvailable(Context context) {
+        return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
+    }
+
+    public static void ensureKeyboardPresent(Context context, AlertDialog dialog) {
+        if (!isHardwareKeyboardAvailable(context)) {
+            dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+        }
+    }
+
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index 11f9aa71..8b619b6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -123,20 +123,20 @@
                 mSummary.setVisibility(View.INVISIBLE);
             }
 
-            if (docLastModified == -1) {
+            if (docLastModified > 0) {
                 hasDetails = true;
-                mDate.setText(null);
-            } else {
                 mDate.setText(Shared.formatTime(mContext, docLastModified));
+            } else {
+                mDate.setText(null);
             }
 
-            if (!state.showSize || docSize == -1) {
+            if (state.showSize && docSize > -1) {
                 hasDetails = true;
-                mSize.setVisibility(View.GONE);
-                mDetails.setVisibility(View.GONE);
-            } else {
                 mSize.setVisibility(View.VISIBLE);
                 mSize.setText(Formatter.formatFileSize(mContext, docSize));
+            } else {
+                mSize.setVisibility(View.GONE);
+                mDetails.setVisibility(View.GONE);
             }
             mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE);
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index 0018d01..884abbb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -92,6 +92,9 @@
 
         final AlertDialog dialog = builder.create();
 
+        // Workaround for the problem - virtual keyboard doesn't show on the phone.
+        Shared.ensureKeyboardPresent(context, dialog);
+
         mEditText.setOnEditorActionListener(
                 new OnEditorActionListener() {
                     @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 29273a3..3eaf10a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.documentsui.model;
 
+import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.Shared.compareToIgnoreCaseNullable;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
@@ -31,6 +32,7 @@
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.documentsui.IconUtils;
 import com.android.documentsui.R;
@@ -47,6 +49,8 @@
  * Representation of a {@link Root}.
  */
 public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
+
+    private static final String TAG = "RootInfo";
     private static final int VERSION_INIT = 1;
     private static final int VERSION_DROP_TYPE = 2;
 
@@ -59,6 +63,8 @@
             TYPE_DOWNLOADS,
             TYPE_LOCAL,
             TYPE_MTP,
+            TYPE_SD,
+            TYPE_USB,
             TYPE_OTHER
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -70,7 +76,9 @@
     public static final int TYPE_DOWNLOADS = 5;
     public static final int TYPE_LOCAL = 6;
     public static final int TYPE_MTP = 7;
-    public static final int TYPE_OTHER = 8;
+    public static final int TYPE_SD = 8;
+    public static final int TYPE_USB = 9;
+    public static final int TYPE_OTHER = 10;
 
     public String authority;
     public String rootId;
@@ -185,33 +193,40 @@
     private void deriveFields() {
         derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
 
-        // TODO: remove these special case icons
         if (isHome()) {
+            derivedType = TYPE_LOCAL;
             derivedIcon = R.drawable.ic_root_documents;
-            derivedType = TYPE_LOCAL;
-        } else if (isExternalStorage()) {
-            derivedIcon = R.drawable.ic_root_smartphone;
-            derivedType = TYPE_LOCAL;
-            // TODO: Apply SD card icon to SD devices.
-        } else if (isDownloads()) {
-            derivedIcon = R.drawable.ic_root_download;
-            derivedType = TYPE_DOWNLOADS;
-        } else if (isImages()) {
-            derivedIcon = R.drawable.ic_doc_image;
-            derivedType = TYPE_IMAGES;
-        } else if (isVideos()) {
-            derivedIcon = R.drawable.ic_doc_video;
-            derivedType = TYPE_VIDEO;
-        } else if (isAudio()) {
-            derivedIcon = R.drawable.ic_doc_audio;
-            derivedType = TYPE_AUDIO;
-        } else if (isRecents()) {
-            derivedType = TYPE_RECENTS;
         } else if (isMtp()) {
             derivedType = TYPE_MTP;
+            derivedIcon = R.drawable.ic_usb_storage;
+        } else if (isUsb()) {
+            derivedType = TYPE_USB;
+            derivedIcon = R.drawable.ic_usb_storage;
+        } else if (isSd()) {
+            derivedType = TYPE_SD;
+            derivedIcon = R.drawable.ic_sd_storage;
+        } else if (isExternalStorage()) {
+            derivedType = TYPE_LOCAL;
+            derivedIcon = R.drawable.ic_root_smartphone;
+        } else if (isDownloads()) {
+            derivedType = TYPE_DOWNLOADS;
+            derivedIcon = R.drawable.ic_root_download;
+        } else if (isImages()) {
+            derivedType = TYPE_IMAGES;
+            derivedIcon = R.drawable.ic_doc_image;
+        } else if (isVideos()) {
+            derivedType = TYPE_VIDEO;
+            derivedIcon = R.drawable.ic_doc_video;
+        } else if (isAudio()) {
+            derivedType = TYPE_AUDIO;
+            derivedIcon = R.drawable.ic_doc_audio;
+        } else if (isRecents()) {
+            derivedType = TYPE_RECENTS;
         } else {
             derivedType = TYPE_OTHER;
         }
+
+        if (DEBUG) Log.d(TAG, "Finished deriving fields: " + this);
     }
 
     public Uri getUri() {
@@ -291,6 +306,14 @@
         return (flags & Root.FLAG_EMPTY) != 0;
     }
 
+    public boolean isSd() {
+        return (flags & Root.FLAG_REMOVABLE_SD) != 0;
+    }
+
+    public boolean isUsb() {
+        return (flags & Root.FLAG_REMOVABLE_USB) != 0;
+    }
+
     public Drawable loadIcon(Context context) {
         if (derivedIcon != 0) {
             return context.getDrawable(derivedIcon);
@@ -358,7 +381,14 @@
 
     @Override
     public String toString() {
-        return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
+        return "Root{"
+                + "authority=" + authority
+                + ", rootId=" + rootId
+                + ", title=" + title
+                + ", isUsb=" + isUsb()
+                + ", isSd=" + isSd()
+                + ", isMtp=" + isMtp()
+                + "}";
     }
 
     public String getDirectoryString() {
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 3eda8ec..9a51b05 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -34,6 +34,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.OnCloseListener;
 import android.os.UserHandle;
+import android.os.storage.DiskInfo;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.provider.DocumentsContract;
@@ -184,6 +185,14 @@
             root.flags = Root.FLAG_LOCAL_ONLY
                     | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
 
+            final DiskInfo disk = volume.getDisk();
+            if (DEBUG) Log.d(TAG, "Disk for root " + rootId + " is " + disk);
+            if (disk != null && disk.isSd()) {
+                root.flags |= Root.FLAG_REMOVABLE_SD;
+            } else if (disk != null && disk.isUsb()) {
+                root.flags |= Root.FLAG_REMOVABLE_USB;
+            }
+
             if (volume.isPrimary()) {
                 // save off the primary volume for subsequent "Home" dir initialization.
                 primaryVolume = volume;
diff --git a/packages/SettingsLib/res/drawable/ic_info.xml b/packages/SettingsLib/res/drawable/ic_info.xml
new file mode 100644
index 0000000..afe7e6b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_info.xml
@@ -0,0 +1,25 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?android:attr/colorAccent">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml b/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
deleted file mode 100644
index b3d7cf9..0000000
--- a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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="21dp"
-        android:height="21dp"
-        android:viewportWidth="21.0"
-        android:viewportHeight="21.0"
-        android:tint="?android:attr/colorAccent">
-    <path
-            android:fillColor="@android:color/white"
-            android:pathData="M8,16c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S6.9,16,8,16zM14,7h-1V5c0-2.8-2.2-5-5-5S3,2.2,3,5v2H2C0.9,7,0,7.9,0,9v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V9C16,7.9,15.1,7,14,7z M4.9,5c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H4.9V5z M14,19H2V9h12V19z" />
-</vector>
diff --git a/packages/SettingsLib/res/layout/restricted_icon.xml b/packages/SettingsLib/res/layout/restricted_icon.xml
new file mode 100644
index 0000000..d57fb80
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_icon.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/restricted_icon"
+    android:layout_width="@dimen/restricted_icon_size"
+    android:layout_height="@dimen/restricted_icon_size"
+    android:src="@drawable/ic_info"
+    android:gravity="end|center_vertical" />
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
new file mode 100644
index 0000000..6183812
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/restricted_icon"
+        android:layout_width="@dimen/restricted_icon_size"
+        android:layout_height="@dimen/restricted_icon_size"
+        android:src="@drawable/ic_info"
+        android:gravity="end|center_vertical" />
+    <!-- Based off frameworks/base/core/res/res/layout/preference_widget_switch.xml -->
+    <Switch xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+android:id/switch_widget"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        android:clickable="false"
+        android:background="@null" />
+</merge>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 9f78e87..c3b3cfc 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -33,8 +33,8 @@
     <dimen name="user_spinner_item_height">56dp</dimen>
 
     <!-- Lock icon for preferences locked by admin -->
-    <dimen name="restricted_lock_icon_size">16dp</dimen>
-    <dimen name="restricted_lock_icon_padding">4dp</dimen>
+    <dimen name="restricted_icon_size">16dp</dimen>
+    <dimen name="restricted_icon_padding">4dp</dimen>
 
     <dimen name="wifi_preference_badge_padding">8dip</dimen>
 
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 72fa939..ae2c6e7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -773,6 +773,11 @@
     <!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] -->
     <string name="disabled_by_admin_summary_text">Controlled by admin</string>
 
+    <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+    <string name="enabled_by_admin">Enabled by administrator</string>
+    <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+    <string name="disabled_by_admin">Disabled by administrator</string>
+
     <!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
     <string name="home">Home</string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
index c2f885d..4c0450e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
@@ -49,7 +49,7 @@
 
         mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(context);
         mRestrictedPadlockPadding = context.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_padding);
+                R.dimen.restricted_icon_padding);
     }
 
     private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
index e63130d..360a34c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
@@ -36,7 +36,7 @@
 
         mContext = context;
         mExtraPadding = mContext.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_padding);
+                R.dimen.restricted_icon_padding);
         mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
     }
 
@@ -53,7 +53,7 @@
 
         // Add extra padding before the padlock.
         float transX = x + mExtraPadding;
-        float transY = bottom - drawable.getBounds().bottom - paint.getFontMetricsInt().descent;
+        float transY = (bottom - drawable.getBounds().bottom) / 2.0f;
 
         canvas.translate(transX, transY);
         drawable.draw(canvas);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 6d29c5f..d0c249f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -49,9 +49,9 @@
      * @return drawables for displaying with settings that are locked by a device admin.
      */
     public static Drawable getRestrictedPadlock(Context context) {
-        Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
+        Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_info);
         final int iconSize = context.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_size);
+                R.dimen.restricted_icon_size);
         restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
         return restrictedPadlock;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
index 810f6eb..e69497a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
@@ -23,6 +23,7 @@
 import android.support.v7.preference.PreferenceManager;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
+import android.view.View;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
@@ -36,6 +37,7 @@
     public RestrictedPreference(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        setWidgetLayoutResource(R.layout.restricted_icon);
         mHelper = new RestrictedPreferenceHelper(context, this, attrs);
     }
 
@@ -56,6 +58,10 @@
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
         mHelper.onBindViewHolder(holder);
+        final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+        if (restrictedIcon != null) {
+            restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+        }
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 227b1e8..0c0af24 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -54,7 +54,7 @@
 
         mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
         mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
-                R.dimen.restricted_lock_icon_padding);
+                R.dimen.restricted_icon_padding);
 
         if (attrs != null) {
             final TypedArray attributes = context.obtainStyledAttributes(attrs,
@@ -91,12 +91,8 @@
      * Modify PreferenceViewHolder to add padlock if restriction is disabled.
      */
     public void onBindViewHolder(PreferenceViewHolder holder) {
-        final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
-        if (titleView != null) {
-            RestrictedLockUtils.setTextViewPadlock(mContext, titleView, mDisabledByAdmin);
-            if (mDisabledByAdmin) {
-                holder.itemView.setEnabled(true);
-            }
+        if (mDisabledByAdmin) {
+            holder.itemView.setEnabled(true);
         }
         if (mUseAdminDisabledSummary) {
             final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index 6cae8aa..f381286 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -23,6 +23,8 @@
 import android.support.v7.preference.PreferenceViewHolder;
 import android.support.v14.preference.SwitchPreference;
 import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
@@ -36,6 +38,7 @@
     public RestrictedSwitchPreference(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        setWidgetLayoutResource(R.layout.restricted_switch_widget);
         mHelper = new RestrictedPreferenceHelper(context, this, attrs);
     }
 
@@ -56,6 +59,20 @@
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
         mHelper.onBindViewHolder(holder);
+        final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+        final View switchWidget = holder.findViewById(android.R.id.switch_widget);
+        if (restrictedIcon != null) {
+            restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+        }
+        if (switchWidget != null) {
+            switchWidget.setVisibility(isDisabledByAdmin() ? View.GONE : View.VISIBLE);
+        }
+        final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
+        if (summaryView != null && isDisabledByAdmin()) {
+            summaryView.setText(
+                    isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+            summaryView.setVisibility(View.VISIBLE);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/res/drawable/ic_info.xml b/packages/SystemUI/res/drawable/ic_info.xml
deleted file mode 100644
index 65e7bf5..0000000
--- a/packages/SystemUI/res/drawable/ic_info.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 603ebbf..b0dca9a 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -20,22 +20,22 @@
         android:layout_height="wrap_content"
         android:orientation="horizontal">
      <TextView android:id="@+id/tile_label"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:textColor="@color/qs_tile_text"
-             android:gravity="center_horizontal"
-             android:minLines="2"
-             android:padding="0dp"
-             android:fontFamily="sans-serif-condensed"
-             android:textStyle="normal"
-             android:textSize="@dimen/qs_tile_text_size"
-             android:clickable="false" />
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@color/qs_tile_text"
+            android:gravity="center_horizontal"
+            android:minLines="2"
+            android:padding="0dp"
+            android:fontFamily="sans-serif-condensed"
+            android:textStyle="normal"
+            android:textSize="@dimen/qs_tile_text_size"
+            android:clickable="false" />
      <ImageView android:id="@+id/restricted_padlock"
-             android:layout_width="@dimen/qs_tile_text_size"
-             android:layout_height="@dimen/qs_tile_text_size"
-             android:src="@drawable/ic_settings_lock_outline"
-             android:layout_marginLeft="@dimen/restricted_padlock_pading"
-             android:baselineAlignBottom="true"
-             android:scaleType="centerInside"
-             android:visibility="gone" />
+            android:layout_width="@dimen/qs_tile_text_size"
+            android:layout_height="match_parent"
+            android:paddingBottom="@dimen/qs_tile_text_size"
+            android:src="@drawable/ic_info"
+            android:layout_marginLeft="@dimen/restricted_padlock_pading"
+            android:scaleType="centerInside"
+            android:visibility="gone" />
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index a22c360..661d74a 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -53,10 +53,10 @@
         <ImageView
                 android:id="@+id/restricted_padlock"
                 android:layout_width="@dimen/qs_detail_item_secondary_text_size"
-                android:layout_height="@dimen/qs_detail_item_secondary_text_size"
-                android:src="@drawable/ic_settings_lock_outline"
+                android:layout_height="match_parent"
+                android:gravity="center_vertical"
+                android:src="@drawable/ic_info"
                 android:layout_marginLeft="@dimen/restricted_padlock_pading"
-                android:baselineAlignBottom="true"
                 android:scaleType="centerInside"
                 android:visibility="gone" />
     </LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 33f3c30..f6dcc11 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -144,7 +144,9 @@
     protected Animator getViewTranslationAnimator(View v, float target,
             AnimatorUpdateListener listener) {
         ObjectAnimator anim = createTranslationAnimation(v, target);
-        anim.addUpdateListener(listener);
+        if (listener != null) {
+            anim.addUpdateListener(listener);
+        }
         return anim;
     }
 
@@ -370,6 +372,9 @@
         };
 
         Animator anim = getViewTranslationAnimator(animView, newPos, updateListener);
+        if (anim == null) {
+            return;
+        }
         if (useAccelerateInterpolator) {
             anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
         } else {
@@ -411,6 +416,9 @@
         };
 
         Animator anim = getViewTranslationAnimator(animView, targetLeft, updateListener);
+        if (anim == null) {
+            return;
+        }
         int duration = SNAP_ANIM_LEN;
         anim.setDuration(duration);
         anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f63e97a..469a1fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1090,6 +1090,8 @@
 
     @Override
     public void onGearDisplayed(ExpandableNotificationRow row) {
+        MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+                row.getStatusBarNotification().getPackageName());
         mNotificationGearDisplayed = row;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f446593..84b84e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -684,7 +684,7 @@
         mTranslateableViews.remove(mGutsStub);
     }
 
-    public void setTranslationForOutline(float translationX) {
+    private void setTranslationForOutline(float translationX) {
         setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
     }
 
@@ -704,6 +704,46 @@
         if (mTranslateAnim != null) {
             mTranslateAnim.cancel();
         }
+        mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
+                null /* updateListener */);
+        if (mTranslateAnim != null) {
+            mTranslateAnim.start();
+        }
+    }
+
+    @Override
+    public void setTranslation(float translationX) {
+        if (areGutsExposed()) {
+            // Don't translate if guts are showing.
+            return;
+        }
+        // Translate the group of views
+        for (int i = 0; i < mTranslateableViews.size(); i++) {
+            if (mTranslateableViews.get(i) != null) {
+                mTranslateableViews.get(i).setTranslationX(translationX);
+            }
+        }
+        setTranslationForOutline(translationX);
+        if (mSettingsIconRow != null) {
+            mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
+        }
+    }
+
+    @Override
+    public float getTranslation() {
+        if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
+            // All of the views in the list should have same translation, just use first one.
+            return mTranslateableViews.get(0).getTranslationX();
+        }
+        return 0;
+    }
+
+    public Animator getTranslateViewAnimator(final float leftTarget,
+            AnimatorUpdateListener listener) {
+        if (areGutsExposed()) {
+            // No translation if guts are exposed.
+            return null;
+        }
         AnimatorSet set = new AnimatorSet();
         if (mTranslateableViews != null) {
             for (int i = 0; i < mTranslateableViews.size(); i++) {
@@ -715,8 +755,15 @@
                         @Override
                         public void onAnimationUpdate(ValueAnimator animation) {
                             setTranslationForOutline((float) animation.getAnimatedValue());
+                            if (mSettingsIconRow != null) {
+                                mSettingsIconRow.updateSettingsIcons(
+                                        (float) animation.getAnimatedValue(), getMeasuredWidth());
+                            }
                         }
                     });
+                    if (listener != null) {
+                        translateAnim.addUpdateListener(listener);
+                    }
                 }
                 translateAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
@@ -730,8 +777,7 @@
                 set.play(translateAnim);
             }
         }
-        mTranslateAnim = set;
-        set.start();
+        return set;
     }
 
     public float getSpaceForGear() {
@@ -748,10 +794,6 @@
         return mSettingsIconRow;
     }
 
-    public ArrayList<View> getContentViews() {
-        return mTranslateableViews;
-    }
-
     public void inflateGuts() {
         if (mGuts == null) {
             mGutsStub.inflate();
@@ -1169,6 +1211,10 @@
         return mMaxExpandHeight;
     }
 
+    public boolean areGutsExposed() {
+        return (mGuts != null && mGuts.areGutsExposed());
+    }
+
     @Override
     public boolean isContentExpandable() {
         NotificationContentView showingLayout = getShowingLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 1ff87f5..b2c632b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -283,6 +283,20 @@
     public void setBelowSpeedBump(boolean below) {
     }
 
+    /**
+     * Sets the translation of the view.
+     */
+    public void setTranslation(float translation) {
+        setTranslationX(translation);
+    }
+
+    /**
+     * Gets the translation of the view.
+     */
+    public float getTranslation() {
+        return getTranslationX();
+    }
+
     public void onHeightReset() {
         if (mOnHeightChangedListener != null) {
             mOnHeightChangedListener.onReset(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 1c16bdc0..45a24a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -130,7 +130,12 @@
             importanceSlider.setVisibility(View.VISIBLE);
             importanceButtons.setVisibility(View.GONE);
         } else {
-            bindToggles(importanceButtons, sbn, systemApp);
+            int userImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+            try {
+                userImportance =
+                        mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
+            } catch (RemoteException e) {}
+            bindToggles(importanceButtons, userImportance, systemApp);
             importanceButtons.setVisibility(View.VISIBLE);
             importanceSlider.setVisibility(View.GONE);
         }
@@ -144,7 +149,7 @@
             if (mBlock.isChecked()) {
                 progress = NotificationListenerService.Ranking.IMPORTANCE_NONE;
             } else if (mSilent.isChecked()) {
-                progress = NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
+                progress = NotificationListenerService.Ranking.IMPORTANCE_LOW;
             } else {
                 progress = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
             }
@@ -158,7 +163,7 @@
         }
     }
 
-    private void bindToggles(final View importanceButtons, final StatusBarNotification sbn,
+    private void bindToggles(final View importanceButtons, final int importance,
             final boolean systemApp) {
         mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
         mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
@@ -169,7 +174,11 @@
         } else {
             mReset.setText(mContext.getString(R.string.do_not_silence_block));
         }
-        mReset.setChecked(true);
+        if (importance == NotificationListenerService.Ranking.IMPORTANCE_LOW) {
+            mSilent.setChecked(true);
+        } else {
+            mReset.setChecked(true);
+        }
     }
 
     private void bindSlider(final View importanceSlider, final StatusBarNotification sbn,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 960e4cf..988d537 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -221,6 +221,7 @@
 
         apply();
         applyIconTint();
+        mNC.addSignalCallback(this);
     }
 
     @Override
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 c152171..ef16388 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -995,7 +995,6 @@
         SignalClusterView signalCluster =
                 (SignalClusterView) containerView.findViewById(R.id.signal_cluster);
         if (signalCluster != null) {
-            mNetworkController.addSignalCallback(signalCluster);
             signalCluster.setSecurityController(mSecurityController);
             signalCluster.setNetworkController(mNetworkController);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
index bd36462..159bd41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
@@ -19,6 +19,7 @@
 import android.net.NetworkCapabilities;
 
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.util.BitSet;
 
@@ -46,12 +47,12 @@
     }
 
     @Override
-    public void notifyListeners() {
+    public void notifyListeners(SignalCallback callback) {
         boolean ethernetVisible = mCurrentState.connected;
         String contentDescription = getStringIfExists(getContentDescription());
 
         // TODO: wire up data transfer using WifiSignalPoller.
-        mCallbackHandler.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
+        callback.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
                 contentDescription));
     }
 
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 8fd4d9c..80dcfb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -34,6 +34,7 @@
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
 
@@ -198,7 +199,7 @@
     }
 
     @Override
-    public void notifyListeners() {
+    public void notifyListeners(SignalCallback callback) {
         MobileIconGroup icons = getIcons();
 
         String contentDescription = getStringIfExists(getContentDescription());
@@ -231,7 +232,7 @@
                 || mCurrentState.iconGroup == TelephonyIcons.ROAMING
                 || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
-        mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+        callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
                 mSubscriptionInfo.getSubscriptionId());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 8193b52..40eb71d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -322,16 +322,16 @@
     }
 
     public void addSignalCallback(SignalCallback cb) {
-        mCallbackHandler.setListening(cb, true);
-        mCallbackHandler.setSubs(mCurrentSubscriptions);
-        mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
+        cb.setSubs(mCurrentSubscriptions);
+        cb.setIsAirplaneMode(new IconState(mAirplaneMode,
                 TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
-        mCallbackHandler.setNoSims(mHasNoSims);
-        mWifiSignalController.notifyListeners();
-        mEthernetSignalController.notifyListeners();
+        cb.setNoSims(mHasNoSims);
+        mWifiSignalController.notifyListeners(cb);
+        mEthernetSignalController.notifyListeners(cb);
         for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
-            mobileSignalController.notifyListeners();
+            mobileSignalController.notifyListeners(cb);
         }
+        mCallbackHandler.setListening(cb, true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index c954d08..4cfd1c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.text.format.DateFormat;
 import android.util.Log;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
@@ -48,7 +49,7 @@
     // is aware of current state.
     protected final NetworkControllerImpl mNetworkController;
 
-    protected final CallbackHandler mCallbackHandler;
+    private final CallbackHandler mCallbackHandler;
 
     // Save the previous HISTORY_SIZE states for logging.
     private final State[] mHistory;
@@ -198,12 +199,16 @@
         }
     }
 
+    public final void notifyListeners() {
+        notifyListeners(mCallbackHandler);
+    }
+
     /**
      * Trigger callbacks based on current state.  The callbacks should be completely
      * based on current state, and only need to be called in the scenario where
      * mCurrentState != mLastState.
      */
-    public abstract void notifyListeners();
+    public abstract void notifyListeners(SignalCallback callback);
 
     /**
      * Generate a blank T.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index cc98eb6..a6ed04f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -28,6 +28,7 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.util.Objects;
 
@@ -72,7 +73,7 @@
     }
 
     @Override
-    public void notifyListeners() {
+    public void notifyListeners(SignalCallback callback) {
         // only show wifi in the cluster if connected or if wifi-only
         boolean wifiVisible = mCurrentState.enabled
                 && (mCurrentState.connected || !mHasMobileData);
@@ -83,7 +84,7 @@
         IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
         IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
                 contentDescription);
-        mCallbackHandler.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+        callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
                 ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
                 wifiDesc);
     }
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 e8dad92..aa444f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -48,6 +48,8 @@
 import android.view.animation.Interpolator;
 import android.widget.OverScroller;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -363,6 +365,8 @@
     @Override
     public void onGearTouched(ExpandableNotificationRow row, int x, int y) {
         if (mLongPressListener != null) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
+                    row.getStatusBarNotification().getPackageName());
             mLongPressListener.onLongPress(row, x, y);
         }
     }
@@ -710,6 +714,7 @@
 
         if (targetLeft == 0 && mCurrIconRow != null) {
             mCurrIconRow.resetState();
+            mCurrIconRow = null;
             if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
                 mGearExposedView = null;
             }
@@ -3363,7 +3368,6 @@
 
         private static final long GEAR_SHOW_DELAY = 60;
 
-        private ArrayList<View> mTranslatingViews = new ArrayList<>();
         private CheckForDrag mCheckForDrag;
         private Handler mHandler;
         private int mMoveState = MOVE_STATE_UNDEFINED;
@@ -3380,6 +3384,7 @@
 
             // Reset check for drag gesture
             mCheckForDrag = null;
+            mCurrIconRow = null;
 
             // Slide back any notifications that might be showing a gear
             resetExposedGearView();
@@ -3388,9 +3393,6 @@
                 // Set the listener for the current row's gear
                 mCurrIconRow = ((ExpandableNotificationRow) currView).getSettingsRow();
                 mCurrIconRow.setGearListener(NotificationStackScrollLayout.this);
-
-                // And the translating children
-                mTranslatingViews = ((ExpandableNotificationRow) currView).getContentViews();
             }
             mMoveState = MOVE_STATE_UNDEFINED;
         }
@@ -3404,15 +3406,12 @@
             }
             mMoveState = newMoveState;
 
-            if (view instanceof ExpandableNotificationRow) {
-                ((ExpandableNotificationRow) view).setTranslationForOutline(translation);
-                if (!isPinnedHeadsUp(view)) {
-                    // Only show the gear if we're not a heads up view.
-                    checkForDrag();
-                    if (mCurrIconRow != null) {
-                        mCurrIconRow.updateSettingsIcons(translation, getSize(view));
-                    }
-                }
+            final boolean gutsExposed = (view instanceof ExpandableNotificationRow)
+                    && ((ExpandableNotificationRow) view).areGutsExposed();
+
+            if (!isPinnedHeadsUp(view) && !gutsExposed) {
+                // Only show the gear if we're not a heads up view and guts aren't exposed.
+                checkForDrag();
             }
         }
 
@@ -3435,12 +3434,12 @@
                     (!fromLeft && absTrans >= snapBackThreshold * 0.4f
                             && absTrans <= notiThreshold);
 
-            if (pastGear && !isPinnedHeadsUp(animView)) {
+            if (pastGear && !isPinnedHeadsUp(animView)
+                    && (animView instanceof ExpandableNotificationRow)) {
                 // bouncity
                 final float target = fromLeft ? snapBackThreshold : -snapBackThreshold;
                 mGearExposedView = mTranslatingParentView;
-                if (mGearDisplayedListener != null
-                        && (animView instanceof ExpandableNotificationRow)) {
+                if (mGearDisplayedListener != null) {
                     mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
                 }
                 super.snapChild(animView, target, velocity);
@@ -3450,38 +3449,16 @@
         }
 
         @Override
-        public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) {
-            if (mDismissAllInProgress) {
-                // When dismissing all, we translate the entire view instead.
-                super.onTranslationUpdate(animView, value, canBeDismissed);
-                return;
-            }
-            if (animView instanceof ExpandableNotificationRow) {
-                ((ExpandableNotificationRow) animView).setTranslationForOutline(value);
-            }
-            if (mCurrIconRow != null) {
-                mCurrIconRow.updateSettingsIcons(value, getSize(animView));
-            }
-        }
-
-        @Override
         public Animator getViewTranslationAnimator(View v, float target,
                 AnimatorUpdateListener listener) {
             if (mDismissAllInProgress) {
                 // When dismissing all, we translate the entire view instead.
                 return super.getViewTranslationAnimator(v, target, listener);
+            } else if (v instanceof ExpandableNotificationRow) {
+                return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+            } else {
+                return super.getViewTranslationAnimator(v, target, listener);
             }
-            ArrayList<Animator> animators = new ArrayList<Animator>();
-            for (int i = 0; i < mTranslatingViews.size(); i++) {
-                ObjectAnimator anim = createTranslationAnimation(mTranslatingViews.get(i), target);
-                animators.add(anim);
-                if (i == 0 && listener != null) {
-                    anim.addUpdateListener(listener);
-                }
-            }
-            AnimatorSet set = new AnimatorSet();
-            set.playTogether(animators);
-            return set;
         }
 
         @Override
@@ -3489,13 +3466,8 @@
             if (mDismissAllInProgress) {
                 // When dismissing all, we translate the entire view instead.
                 super.setTranslation(v, translate);
-                return;
-            }
-            // Translate the group of views
-            for (int i = 0; i < mTranslatingViews.size(); i++) {
-                if (mTranslatingViews.get(i) != null) {
-                    super.setTranslation(mTranslatingViews.get(i), translate);
-                }
+            } else {
+                ((ExpandableView) v).setTranslation(translate);
             }
         }
 
@@ -3504,15 +3476,11 @@
             if (mDismissAllInProgress) {
                 // When dismissing all, we translate the entire view instead.
                 return super.getTranslation(v);
+            } else {
+                return ((ExpandableView) v).getTranslation();
             }
-            // All of the views in the list should have same translation, just use first one.
-            if (mTranslatingViews.size() > 0) {
-                return super.getTranslation(mTranslatingViews.get(0));
-            }
-            return 0;
         }
 
-
         /**
          * Returns the horizontal space in pixels required to display the gear behind a
          * notification.
@@ -3567,26 +3535,11 @@
             final View prevGearExposedView = mGearExposedView;
             mGearExposedView = null;
 
-            AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
-                public void onAnimationEnd(Animator animator) {
-                    if (prevGearExposedView instanceof ExpandableNotificationRow) {
-                        ((ExpandableNotificationRow) prevGearExposedView).getSettingsRow()
-                                .resetState();
-                    }
-                }
-            };
-            AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
-                @Override
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    if (prevGearExposedView instanceof ExpandableNotificationRow) {
-                        ((ExpandableNotificationRow) prevGearExposedView)
-                                .setTranslationForOutline((float) animation.getAnimatedValue());
-                    }
-                }
-            };
-            Animator set = getViewTranslationAnimator(prevGearExposedView, 0, updateListener);
-            set.addListener(listener);
-            set.start();
+            Animator anim = getViewTranslationAnimator(prevGearExposedView,
+                    0 /* leftTarget */, null /* updateListener */);
+            if (anim != null) {
+                anim.start();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index fd753e9..fb425ab 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -50,6 +50,7 @@
     private TextView mPlayPauseDescriptionTextView;
     private View mCloseButtonView;
     private View mCloseDescriptionView;
+    private boolean mMovePipToFullscreen;
 
     private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
         @Override
@@ -69,6 +70,7 @@
             @Override
             public void onClick(View v) {
                 mPipManager.movePipToFullscreen();
+                mMovePipToFullscreen = true;
                 finish();
             }
         });
@@ -167,7 +169,9 @@
     }
 
     private void restorePipAndFinish() {
-        mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+        if (!mMovePipToFullscreen) {
+            mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+        }
         finish();
     }
 
@@ -221,7 +225,7 @@
     @Override
     public void finish() {
         super.finish();
-        if (mPipManager.isRecentsShown()) {
+        if (mPipManager.isRecentsShown() && !mMovePipToFullscreen) {
             SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
             for (int i = services.length - 1; i >= 0; i--) {
                 if (services[i] instanceof Recents) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index ebd5384..60d33fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -32,6 +32,7 @@
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
 import org.mockito.ArgumentCaptor;
@@ -100,7 +101,7 @@
 
         // Trigger blank callbacks to always get the current state (some tests don't trigger
         // changes from default state).
-        mNetworkController.addSignalCallback(null);
+        mNetworkController.addSignalCallback(mock(SignalCallback.class));
         mNetworkController.addEmergencyListener(null);
     }
 
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 5d693c9..8171b49 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -1927,6 +1927,14 @@
     // access before; action pass package name of calling package.
     ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331;
 
+    // Logged when the user slides a notification and
+    // reveals the gear beneath it.
+    ACTION_REVEAL_GEAR = 332;
+
+    // Logged when the user taps on the gear beneath
+    // a notification.
+    ACTION_TOUCH_GEAR = 333;
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
 
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 3bef19e..316e530 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1061,7 +1061,7 @@
               type, kind, norm, size);
     }
     return (jlong)(uintptr_t)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind,
-                                             norm, size);
+                                             norm, size, true);
 }
 
 static jlong
@@ -1100,7 +1100,7 @@
     jlong id = (jlong)(uintptr_t)rsElementCreate2((RsContext)con,
                                      (const RsElement *)ids, fieldCount,
                                      nameArray, fieldCount * sizeof(size_t),  sizeArray,
-                                     (const uint32_t *)arraySizes, fieldCount);
+                                     (const uint32_t *)arraySizes, fieldCount, true);
 
     free(ids);
     free(arraySizes);
@@ -1174,7 +1174,7 @@
     }
 
     return (jlong)(uintptr_t)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips,
-                                          faces, yuv);
+                                          faces, yuv, true);
 }
 
 static void
@@ -1210,7 +1210,7 @@
     }
     return (jlong)(uintptr_t) rsAllocationCreateTyped((RsContext)con, (RsType)type,
                                                       (RsAllocationMipmapControl)mips,
-                                                      (uint32_t)usage, (uintptr_t)pointer);
+                                                      (uint32_t)usage, (uintptr_t)pointer, true);
 }
 
 static void
@@ -1315,7 +1315,7 @@
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con,
                                                   (RsType)type, (RsAllocationMipmapControl)mip,
-                                                  ptr, bitmap.getSize(), usage);
+                                                  ptr, bitmap.getSize(), usage, true);
     bitmap.unlockPixels();
     return id;
 }
@@ -1331,7 +1331,7 @@
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con,
                                             (RsType)type, (RsAllocationMipmapControl)mip,
-                                            (uint32_t)usage, (uintptr_t)ptr);
+                                            (uint32_t)usage, (uintptr_t)ptr, true);
     bitmap.unlockPixels();
     return id;
 }
@@ -1347,7 +1347,7 @@
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con,
                                                       (RsType)type, (RsAllocationMipmapControl)mip,
-                                                      ptr, bitmap.getSize(), usage);
+                                                      ptr, bitmap.getSize(), usage, true);
     bitmap.unlockPixels();
     return id;
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index acd57b17..9e6c21c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -655,10 +655,9 @@
             userState.mUiAutomationServiceOwner = owner;
             userState.mUiAutomationServiceClient = serviceClient;
             userState.mUiAutomationFlags = flags;
-            userState.mIsAccessibilityEnabled = true;
             userState.mInstalledServices.add(accessibilityServiceInfo);
             if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) {
-                // Set the temporary state.
+                // Set the temporary state, and use it instead of settings
                 userState.mIsTouchExplorationEnabled = false;
                 userState.mIsEnhancedWebAccessibilityEnabled = false;
                 userState.mIsDisplayMagnificationEnabled = false;
@@ -709,7 +708,6 @@
                 return;
             }
 
-            userState.mIsAccessibilityEnabled = true;
             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
             userState.mIsEnhancedWebAccessibilityEnabled = false;
             userState.mIsDisplayMagnificationEnabled = false;
@@ -1245,17 +1243,17 @@
         }
     }
 
-    private void manageServicesLocked(UserState userState) {
+    private void updateServicesLocked(UserState userState) {
         Map<ComponentName, Service> componentNameToServiceMap =
                 userState.mComponentNameToServiceMap;
         boolean isUnlocked = mContext.getSystemService(UserManager.class)
                 .isUserUnlocked(userState.mUserId);
-        boolean isEnabled = userState.mIsAccessibilityEnabled;
 
         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
             ComponentName componentName = ComponentName.unflattenFromString(
                     installedService.getId());
+
             Service service = componentNameToServiceMap.get(componentName);
 
             // Ignore non-encryption-aware services until user is unlocked
@@ -1264,45 +1262,25 @@
                 continue;
             }
 
-            if (isEnabled) {
-                // Wait for the binding if it is in process.
-                if (userState.mBindingServices.contains(componentName)) {
+            // Wait for the binding if it is in process.
+            if (userState.mBindingServices.contains(componentName)) {
+                continue;
+            }
+            if (userState.mEnabledServices.contains(componentName)) {
+                if (service == null) {
+                    service = new Service(userState.mUserId, componentName, installedService);
+                } else if (userState.mBoundServices.contains(service)) {
                     continue;
                 }
-                if (userState.mEnabledServices.contains(componentName)) {
-                    if (service == null) {
-                        service = new Service(userState.mUserId, componentName, installedService);
-                    } else if (userState.mBoundServices.contains(service)) {
-                        continue;
-                    }
-                    service.bindLocked();
-                } else {
-                    if (service != null) {
-                        service.unbindLocked();
-                    }
-                }
+                service.bindLocked();
             } else {
                 if (service != null) {
                     service.unbindLocked();
-                } else {
-                    userState.mBindingServices.remove(componentName);
                 }
             }
         }
 
-        // No enabled installed services => disable accessibility to avoid
-        // sending accessibility events with no recipient across processes.
-        if (isEnabled && isUnlocked && userState.mBoundServices.isEmpty()
-                && userState.mBindingServices.isEmpty()) {
-            userState.mIsAccessibilityEnabled = false;
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
+        updateAccessibilityEnabledSetting(userState);
     }
 
     private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
@@ -1329,7 +1307,8 @@
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
             }
             // Touch exploration without accessibility makes no sense.
-            if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
+            if (userState.isHandlingAccessibilityEvents()
+                    && userState.mIsTouchExplorationEnabled) {
                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
             }
             if (userState.mIsFilterKeyEventsEnabled) {
@@ -1468,25 +1447,17 @@
     }
 
     private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
-        if (userState.mIsAccessibilityEnabled) {
-            // We observe windows for accessibility only if there is at least
-            // one bound service that can retrieve window content that specified
-            // it is interested in accessing such windows. For services that are
-            // binding we do an update pass after each bind event, so we run this
-            // code and register the callback if needed.
-            boolean boundServiceCanRetrieveInteractiveWindows = false;
+        // We observe windows for accessibility only if there is at least
+        // one bound service that can retrieve window content that specified
+        // it is interested in accessing such windows. For services that are
+        // binding we do an update pass after each bind event, so we run this
+        // code and register the callback if needed.
 
-            List<Service> boundServices = userState.mBoundServices;
-            final int boundServiceCount = boundServices.size();
-            for (int i = 0; i < boundServiceCount; i++) {
-                Service boundService = boundServices.get(i);
-                if (boundService.canRetrieveInteractiveWindowsLocked()) {
-                    boundServiceCanRetrieveInteractiveWindows = true;
-                    break;
-                }
-            }
-
-            if (boundServiceCanRetrieveInteractiveWindows) {
+        List<Service> boundServices = userState.mBoundServices;
+        final int boundServiceCount = boundServices.size();
+        for (int i = 0; i < boundServiceCount; i++) {
+            Service boundService = boundServices.get(i);
+            if (boundService.canRetrieveInteractiveWindowsLocked()) {
                 if (mWindowsForAccessibilityCallback == null) {
                     mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback();
                     mWindowManagerService.setWindowsForAccessibilityCallback(
@@ -1554,37 +1525,30 @@
         userState.mIsFilterKeyEventsEnabled = false;
     }
 
-    private void updateServicesLocked(UserState userState) {
-        if (userState.mIsAccessibilityEnabled) {
-            manageServicesLocked(userState);
-        } else {
-            unbindAllServicesLocked(userState);
-        }
-    }
-
     private boolean readConfigurationForUserStateLocked(UserState userState) {
-        boolean somthingChanged = readAccessibilityEnabledSettingLocked(userState);
-        somthingChanged |= readInstalledAccessibilityServiceLocked(userState);
-        somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
-        somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
-        somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
-        somthingChanged |= readHighTextContrastEnabledSettingLocked(userState);
-        somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
-        somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
-        somthingChanged |= readAutoclickEnabledSettingLocked(userState);
-        somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
-        return somthingChanged;
+        boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
+        somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
+        somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
+        somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
+        somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
+        somethingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
+        somethingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
+        somethingChanged |= readAutoclickEnabledSettingLocked(userState);
+        somethingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
+
+        return somethingChanged;
     }
 
-    private boolean readAccessibilityEnabledSettingLocked(UserState userState) {
-        final boolean accessibilityEnabled = Settings.Secure.getIntForUser(
-               mContext.getContentResolver(),
-               Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
-        if (accessibilityEnabled != userState.mIsAccessibilityEnabled) {
-            userState.mIsAccessibilityEnabled = accessibilityEnabled;
-            return true;
+    private void updateAccessibilityEnabledSetting(UserState userState) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.ACCESSIBILITY_ENABLED,
+                    userState.isHandlingAccessibilityEvents() ? 0 : 1,
+                    userState.mUserId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
-        return false;
     }
 
     private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
@@ -1809,7 +1773,7 @@
             // Check whether any Accessibility Services are still enabled and, if not, remove flag
             // requesting no soft keyboard
             final boolean accessibilityRequestingNoIme = userState.mSoftKeyboardShowMode == 1;
-            if (accessibilityRequestingNoIme && !userState.mIsAccessibilityEnabled) {
+            if (accessibilityRequestingNoIme && !userState.isHandlingAccessibilityEvents()) {
                 // No active Accessibility Services can be requesting the soft keyboard to be hidden
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
                         Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
@@ -1853,7 +1817,6 @@
                 UserState userState = mUserStates.valueAt(i);
                 pw.append("User state[attributes:{id=" + userState.mUserId);
                 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
-                pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
                 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
                 pw.append(", displayMagnificationEnabled="
                         + userState.mIsDisplayMagnificationEnabled);
@@ -2003,7 +1966,7 @@
         private void announceNewUserIfNeeded() {
             synchronized (mLock) {
                 UserState userState = getCurrentUserStateLocked();
-                if (userState.mIsAccessibilityEnabled) {
+                if (userState.isHandlingAccessibilityEvents()) {
                     UserManager userManager = (UserManager) mContext.getSystemService(
                             Context.USER_SERVICE);
                     String message = mContext.getString(R.string.user_switched,
@@ -4061,7 +4024,6 @@
 
         public int mSoftKeyboardShowMode = 0;
 
-        public boolean mIsAccessibilityEnabled;
         public boolean mIsTouchExplorationEnabled;
         public boolean mIsTextHighContrastEnabled;
         public boolean mIsEnhancedWebAccessibilityEnabled;
@@ -4096,11 +4058,11 @@
 
         public int getClientState() {
             int clientState = 0;
-            if (mIsAccessibilityEnabled) {
+            if (isHandlingAccessibilityEvents()) {
                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
             }
             // Touch exploration relies on enabled accessibility.
-            if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+            if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) {
                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
             }
             if (mIsTextHighContrastEnabled) {
@@ -4109,6 +4071,10 @@
             return clientState;
         }
 
+        public boolean isHandlingAccessibilityEvents() {
+            return !mBoundServices.isEmpty() || !mBoundServices.isEmpty();
+        }
+
         public void onSwitchToAnotherUser() {
             // Clear UI test automation state.
             if (mUiAutomationService != null) {
@@ -4128,7 +4094,6 @@
             // Clear state persisted in settings.
             mEnabledServices.clear();
             mTouchExplorationGrantedServices.clear();
-            mIsAccessibilityEnabled = false;
             mIsTouchExplorationEnabled = false;
             mIsEnhancedWebAccessibilityEnabled = false;
             mIsDisplayMagnificationEnabled = false;
@@ -4155,9 +4120,6 @@
 
     private final class AccessibilityContentObserver extends ContentObserver {
 
-        private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
-                Settings.Secure.ACCESSIBILITY_ENABLED);
-
         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
 
@@ -4199,8 +4161,6 @@
         }
 
         public void register(ContentResolver contentResolver) {
-            contentResolver.registerContentObserver(mAccessibilityEnabledUri,
-                    false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
                     false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
@@ -4240,11 +4200,7 @@
                     return;
                 }
 
-                if (mAccessibilityEnabledUri.equals(uri)) {
-                    if (readAccessibilityEnabledSettingLocked(userState)) {
-                        onUserStateChangedLocked(userState);
-                    }
-                } else if (mTouchExplorationEnabledUri.equals(uri)) {
+                if (mTouchExplorationEnabledUri.equals(uri)) {
                     if (readTouchExplorationEnabledSettingLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 25b6fdd..079b2f2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -125,6 +125,7 @@
 import com.android.server.connectivity.NetworkMonitor;
 import com.android.server.connectivity.PacManager;
 import com.android.server.connectivity.PermissionMonitor;
+import com.android.server.connectivity.ApfFilter;
 import com.android.server.connectivity.Tethering;
 import com.android.server.connectivity.Vpn;
 import com.android.server.net.BaseNetworkObserver;
@@ -353,6 +354,13 @@
      */
     private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
 
+    /**
+     * used to push APF program to NetworkAgent
+     * replyTo = NetworkAgent message handler
+     * obj = byte[] of APF program
+     */
+    private static final int EVENT_PUSH_APF_PROGRAM_TO_NETWORK = 32;
+
     /** Handler thread used for both of the handlers below. */
     @VisibleForTesting
     protected final HandlerThread mHandlerThread;
@@ -2190,6 +2198,7 @@
             mKeepaliveTracker.handleStopAllKeepalives(nai,
                     ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
+            if (nai.apfFilter != null) nai.apfFilter.shutdown();
             mNetworkAgentInfos.remove(msg.replyTo);
             updateClat(null, nai.linkProperties, nai);
             synchronized (mNetworkForNetId) {
@@ -2404,6 +2413,13 @@
                 accept ? 1 : 0, always ? 1: 0, network));
     }
 
+    public void pushApfProgramToNetwork(NetworkAgentInfo nai, byte[] program) {
+        enforceConnectivityInternalPermission();
+        Message msg = mHandler.obtainMessage(EVENT_PUSH_APF_PROGRAM_TO_NETWORK, program);
+        msg.replyTo = nai.messenger;
+        mHandler.sendMessage(msg);
+    }
+
     private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
         if (DBG) log("handleSetAcceptUnvalidated network=" + network +
                 " accept=" + accept + " always=" + always);
@@ -2553,6 +2569,16 @@
                     handleMobileDataAlwaysOn();
                     break;
                 }
+                case EVENT_PUSH_APF_PROGRAM_TO_NETWORK: {
+                    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
+                    if (nai == null) {
+                        loge("EVENT_PUSH_APF_PROGRAM_TO_NETWORK from unknown NetworkAgent");
+                    } else {
+                         nai.asyncChannel.sendMessage(NetworkAgent.CMD_PUSH_APF_PROGRAM,
+                                 (byte[]) msg.obj);
+                    }
+                    break;
+                }
                 // Sent by KeepaliveTracker to process an app request on the state machine thread.
                 case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
                     mKeepaliveTracker.handleStartKeepalive(msg);
@@ -4068,6 +4094,9 @@
         if (networkAgent.clatd != null) {
             networkAgent.clatd.fixupLinkProperties(oldLp);
         }
+        if (networkAgent.apfFilter != null) {
+            networkAgent.apfFilter.updateFilter();
+        }
 
         updateInterfaces(newLp, oldLp, netId);
         updateMtu(newLp, oldLp);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5a3639a..f2a9c2c 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -849,7 +849,7 @@
             AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
                     mDockAudioMediaEnabled ?
                             AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
-            readEncodedSurroundMode(mContentResolver);
+            sendEncodedSurroundMode(mContentResolver);
         }
         if (mHdmiManager != null) {
             synchronized (mHdmiManager) {
@@ -1023,7 +1023,7 @@
         AudioSystem.setMasterMono(masterMono);
     }
 
-    private void readEncodedSurroundMode(ContentResolver cr)
+    private void sendEncodedSurroundMode(ContentResolver cr)
     {
         int encodedSurroundMode = Settings.Global.getInt(
                 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
@@ -1102,7 +1102,7 @@
 
             updateRingerModeAffectedStreams();
             readDockAudioSettings(cr);
-            readEncodedSurroundMode(cr);
+            sendEncodedSurroundMode(cr);
         }
 
         mMuteAffectedStreams = System.getIntForUser(cr,
@@ -4642,6 +4642,8 @@
 
     private class SettingsObserver extends ContentObserver {
 
+        private int mEncodedSurroundMode;
+
         SettingsObserver() {
             super(new Handler());
             mContentResolver.registerContentObserver(Settings.System.getUriFor(
@@ -4650,6 +4652,12 @@
                 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
             mContentResolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.MASTER_MONO), false, this);
+
+            mEncodedSurroundMode = Settings.Global.getInt(
+                    mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+                    Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+            mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
         }
 
         @Override
@@ -4669,7 +4677,33 @@
                 }
                 readDockAudioSettings(mContentResolver);
                 updateMasterMono(mContentResolver);
-                readEncodedSurroundMode(mContentResolver);
+                updateEncodedSurroundOutput();
+            }
+        }
+
+        private void updateEncodedSurroundOutput() {
+            int newSurroundMode = Settings.Global.getInt(
+                mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+                Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+            // Did it change?
+            if (mEncodedSurroundMode != newSurroundMode) {
+                // Send to AudioPolicyManager
+                sendEncodedSurroundMode(newSurroundMode);
+                synchronized(mConnectedDevices) {
+                    // Is HDMI connected?
+                    String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
+                    DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+                    if (deviceSpec != null) {
+                        // Toggle HDMI to retrigger broadcast with proper formats.
+                        setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+                                AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
+                                "android"); // disconnect
+                        setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+                                AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
+                                "android"); // reconnect
+                    }
+                }
+                mEncodedSurroundMode = newSurroundMode;
             }
         }
     }
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
new file mode 100644
index 0000000..25c84e1
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -0,0 +1,499 @@
+/*
+ * 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.connectivity;
+
+import static android.system.OsConstants.*;
+
+import android.net.NetworkUtils;
+import android.net.apf.ApfGenerator;
+import android.net.apf.ApfGenerator.IllegalInstructionException;
+import android.net.apf.ApfGenerator.Register;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.PacketSocketAddress;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.util.HexDump;
+import com.android.server.ConnectivityService;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.Thread;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import libcore.io.IoBridge;
+
+/**
+ * For networks that support packet filtering via APF programs, {@code ApfFilter}
+ * listens for IPv6 ICMPv6 router advertisements (RAs) and generates APF programs to
+ * filter out redundant duplicate ones.
+ *
+ * @hide
+ */
+public class ApfFilter {
+    // Thread to listen for RAs.
+    private class ReceiveThread extends Thread {
+        private final byte[] mPacket = new byte[1514];
+        private final FileDescriptor mSocket;
+        private volatile boolean mStopped;
+
+        public ReceiveThread(FileDescriptor socket) {
+            mSocket = socket;
+        }
+
+        public void halt() {
+            mStopped = true;
+            try {
+                // Interrupts the read() call the thread is blocked in.
+                IoBridge.closeAndSignalBlockedThreads(mSocket);
+            } catch (IOException ignored) {}
+        }
+
+        @Override
+        public void run() {
+            log("begin monitoring");
+            while (!mStopped) {
+                try {
+                    int length = Os.read(mSocket, mPacket, 0, mPacket.length);
+                    processRa(mPacket, length);
+                } catch (IOException|ErrnoException e) {
+                    if (!mStopped) {
+                        Log.e(TAG, "Read error", e);
+                    }
+                }
+            }
+        }
+    }
+
+    private static final String TAG = "ApfFilter";
+
+    private final ConnectivityService mConnectivityService;
+    private final NetworkAgentInfo mNai;
+    private ReceiveThread mReceiveThread;
+    private String mIfaceName;
+    private long mUniqueCounter;
+
+    private ApfFilter(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+        mConnectivityService = connectivityService;
+        mNai = nai;
+        maybeStartFilter();
+    }
+
+    private void log(String s) {
+        Log.d(TAG, "(" + mNai.network.netId + "): " + s);
+    }
+
+    private long getUniqueNumber() {
+        return mUniqueCounter++;
+    }
+
+    /**
+     * Attempt to start listening for RAs and, if RAs are received, generating and installing
+     * filters to ignore useless RAs.
+     */
+    private void maybeStartFilter() {
+        mIfaceName = mNai.linkProperties.getInterfaceName();
+        if (mIfaceName == null) return;
+        FileDescriptor socket;
+        try {
+            socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
+            PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
+                    NetworkInterface.getByName(mIfaceName).getIndex());
+            Os.bind(socket, addr);
+            NetworkUtils.attachRaFilter(socket, mNai.networkMisc.apfPacketFormat);
+        } catch(SocketException|ErrnoException e) {
+            Log.e(TAG, "Error filtering raw socket", e);
+            return;
+        }
+        mReceiveThread = new ReceiveThread(socket);
+        mReceiveThread.start();
+    }
+
+    /**
+     * mNai's LinkProperties may have changed, take appropriate action.
+     */
+    public void updateFilter() {
+        // If we're not listening for RAs, try starting.
+        if (mReceiveThread == null) {
+            maybeStartFilter();
+        // If interface name has changed, restart.
+        } else if (!mIfaceName.equals(mNai.linkProperties.getInterfaceName())) {
+            shutdown();
+            maybeStartFilter();
+        }
+    }
+
+    // Returns seconds since Unix Epoch.
+    private static long curTime() {
+        return System.currentTimeMillis() / 1000L;
+    }
+
+    // A class to hold information about an RA.
+    private class Ra {
+        private static final int ETH_HEADER_LEN = 14;
+
+        private static final int IPV6_HEADER_LEN = 40;
+
+        // From RFC4861:
+        private static final int ICMP6_RA_HEADER_LEN = 16;
+        private static final int ICMP6_RA_OPTION_OFFSET =
+                ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
+        private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
+                ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
+        private static final int ICMP6_RA_ROUTER_LIFETIME_LEN = 2;
+        // Prefix information option.
+        private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
+        private static final int ICMP6_PREFIX_OPTION_LEN = 32;
+        private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
+        private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN = 4;
+        private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
+        private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN = 4;
+
+        // From RFC6106: Recursive DNS Server option
+        private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
+        // From RFC6106: DNS Search List option
+        private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
+
+        // From RFC4191: Route Information option
+        private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
+        // Above three options all have the same format:
+        private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
+        private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
+
+        private final ByteBuffer mPacket;
+        // List of binary ranges that include the whole packet except the lifetimes.
+        // Pairs consist of offset and length.
+        private final ArrayList<Pair<Integer, Integer>> mNonLifetimes =
+                new ArrayList<Pair<Integer, Integer>>();
+        // Minimum lifetime in packet
+        long mMinLifetime;
+        // When the packet was last captured, in seconds since Unix Epoch
+        long mLastSeen;
+
+        /**
+         * Add a binary range of the packet that does not include a lifetime to mNonLifetimes.
+         * Assumes mPacket.position() is as far as we've parsed the packet.
+         * @param lastNonLifetimeStart offset within packet of where the last binary range of
+         *                             data not including a lifetime.
+         * @param lifetimeOffset offset from mPacket.position() to the next lifetime data.
+         * @param lifetimeLength length of the next lifetime data.
+         * @return offset within packet of where the next binary range of data not including
+         *         a lifetime.  This can be passed into the next invocation of this function
+         *         via {@code lastNonLifetimeStart}.
+         */
+        private int addNonLifetime(int lastNonLifetimeStart, int lifetimeOffset,
+                int lifetimeLength) {
+            lifetimeOffset += mPacket.position();
+            mNonLifetimes.add(new Pair<Integer, Integer>(lastNonLifetimeStart,
+                    lifetimeOffset - lastNonLifetimeStart));
+            return lifetimeOffset + lifetimeLength;
+        }
+
+        // Note that this parses RA and may throw IllegalArgumentException (from
+        // Buffer.position(int) ) or IndexOutOfBoundsException (from ByteBuffer.get(int) ) if
+        // parsing encounters something non-compliant with specifications.
+        Ra(byte[] packet, int length) {
+            mPacket = ByteBuffer.allocate(length).put(ByteBuffer.wrap(packet, 0, length));
+            mPacket.clear();
+            mLastSeen = curTime();
+
+            // Parse router lifetime
+            int lastNonLifetimeStart = addNonLifetime(0, ICMP6_RA_ROUTER_LIFETIME_OFFSET,
+                    ICMP6_RA_ROUTER_LIFETIME_LEN);
+            // Parse ICMP6 options
+            mPacket.position(ICMP6_RA_OPTION_OFFSET);
+            while (mPacket.hasRemaining()) {
+                int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
+                int optionLength = (((int)mPacket.get(mPacket.position() + 1)) & 0xff) * 8;
+                switch (optionType) {
+                    case ICMP6_PREFIX_OPTION_TYPE:
+                        // Parse valid lifetime
+                        lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+                                ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
+                                ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN);
+                        // Parse preferred lifetime
+                        lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+                                ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
+                                ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
+                        break;
+                    // These three options have the same lifetime offset and size, so process
+                    // together:
+                    case ICMP6_ROUTE_INFO_OPTION_TYPE:
+                    case ICMP6_RDNSS_OPTION_TYPE:
+                    case ICMP6_DNSSL_OPTION_TYPE:
+                        // Parse lifetime
+                        lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+                                ICMP6_4_BYTE_LIFETIME_OFFSET,
+                                ICMP6_4_BYTE_LIFETIME_LEN);
+                        break;
+                    default:
+                        // RFC4861 section 4.2 dictates we ignore unknown options for fowards
+                        // compatibility.
+                        break;
+                }
+                mPacket.position(mPacket.position() + optionLength);
+            }
+            // Mark non-lifetime bytes since last lifetime.
+            addNonLifetime(lastNonLifetimeStart, 0, 0);
+            mMinLifetime = minLifetime(packet, length);
+        }
+
+        // Ignoring lifetimes (which may change) does {@code packet} match this RA?
+        boolean matches(byte[] packet, int length) {
+            if (length != mPacket.limit()) return false;
+            ByteBuffer a = ByteBuffer.wrap(packet);
+            ByteBuffer b = mPacket;
+            for (Pair<Integer, Integer> nonLifetime : mNonLifetimes) {
+                a.clear();
+                b.clear();
+                a.position(nonLifetime.first);
+                b.position(nonLifetime.first);
+                a.limit(nonLifetime.first + nonLifetime.second);
+                b.limit(nonLifetime.first + nonLifetime.second);
+                if (a.compareTo(b) != 0) return false;
+            }
+            return true;
+        }
+
+        // What is the minimum of all lifetimes within {@code packet} in seconds?
+        // Precondition: matches(packet, length) already returned true.
+        long minLifetime(byte[] packet, int length) {
+            long minLifetime = Long.MAX_VALUE;
+            // Wrap packet in ByteBuffer so we can read big-endian values easily
+            ByteBuffer byteBuffer = ByteBuffer.wrap(packet);
+            for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
+                int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;
+                int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
+                long val;
+                switch (lifetimeLength) {
+                    case 2: val = byteBuffer.getShort(offset); break;
+                    case 4: val = byteBuffer.getInt(offset); break;
+                    default: throw new IllegalStateException("bogus lifetime size " + length);
+                }
+                // Mask to size, converting signed to unsigned
+                val &= (1L << (lifetimeLength * 8)) - 1;
+                minLifetime = Math.min(minLifetime, val);
+            }
+            return minLifetime;
+        }
+
+        // How many seconds does this RA's have to live, taking into account the fact
+        // that we might have seen it a while ago.
+        long currentLifetime() {
+            return mMinLifetime - (curTime() - mLastSeen);
+        }
+
+        boolean isExpired() {
+            return currentLifetime() < 0;
+        }
+
+        // Append a filter for this RA to {@code gen}. Jump to DROP_LABEL if it should be dropped.
+        // Jump to the next filter if packet doesn't match this RA.
+        long generateFilter(ApfGenerator gen) throws IllegalInstructionException {
+            String nextFilterLabel = "Ra" + getUniqueNumber();
+            // Skip if packet is not the right size
+            gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
+            gen.addJumpIfR0NotEquals(mPacket.limit(), nextFilterLabel);
+            int filterLifetime = (int)(currentLifetime() / FRACTION_OF_LIFETIME_TO_FILTER);
+            // Skip filter if expired
+            gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
+            gen.addJumpIfR0GreaterThan(filterLifetime, nextFilterLabel);
+            for (int i = 0; i < mNonLifetimes.size(); i++) {
+                // Generate code to match the packet bytes
+                Pair<Integer, Integer> nonLifetime = mNonLifetimes.get(i);
+                gen.addLoadImmediate(Register.R0, nonLifetime.first);
+                gen.addJumpIfBytesNotEqual(Register.R0,
+                        Arrays.copyOfRange(mPacket.array(), nonLifetime.first,
+                                           nonLifetime.first + nonLifetime.second),
+                        nextFilterLabel);
+                // Generate code to test the lifetimes haven't gone down too far
+                if ((i + 1) < mNonLifetimes.size()) {
+                    Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
+                    int offset = nonLifetime.first + nonLifetime.second;
+                    int length = nextNonLifetime.first - offset;
+                    switch (length) {
+                        case 4: gen.addLoad32(Register.R0, offset); break;
+                        case 2: gen.addLoad16(Register.R0, offset); break;
+                        default: throw new IllegalStateException("bogus lifetime size " + length);
+                    }
+                    gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel);
+                }
+            }
+            gen.addJump(gen.DROP_LABEL);
+            gen.defineLabel(nextFilterLabel);
+            return filterLifetime;
+        }
+    }
+
+    // Maximum number of RAs to filter for.
+    private static final int MAX_RAS = 10;
+    private ArrayList<Ra> mRas = new ArrayList<Ra>();
+
+    // There is always some marginal benefit to updating the installed APF program when an RA is
+    // seen because we can extend the program's lifetime slightly, but there is some cost to
+    // updating the program, so don't bother unless the program is going to expire soon. This
+    // constant defines "soon" in seconds.
+    private static final long MAX_PROGRAM_LIFETIME_WORTH_REFRESHING = 30;
+    // We don't want to filter an RA for it's whole lifetime as it'll be expired by the time we ever
+    // see a refresh.  Using half the lifetime might be a good idea except for the fact that
+    // packets may be dropped, so let's use 6.
+    private static final int FRACTION_OF_LIFETIME_TO_FILTER = 6;
+
+    // When did we last install a filter program? In seconds since Unix Epoch.
+    private long mLastTimeInstalledProgram;
+    // How long should the last installed filter program live for? In seconds.
+    private long mLastInstalledProgramMinLifetime;
+
+    private void installNewProgram() {
+        if (mRas.size() == 0) return;
+        final byte[] program;
+        long programMinLifetime = Long.MAX_VALUE;
+        try {
+            ApfGenerator gen = new ApfGenerator();
+            // This is guaranteed to return true because of the check in maybeInstall.
+            gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+            // Step 1: Determine how many RA filters we can fit in the program.
+            int ras = 0;
+            for (Ra ra : mRas) {
+                if (ra.isExpired()) continue;
+                ra.generateFilter(gen);
+                if (gen.programLengthOverEstimate() > mNai.networkMisc.maximumApfProgramSize) {
+                    // We went too far.  Use prior number of RAs in "ras".
+                    break;
+                } else {
+                    // Yay! this RA filter fits, increment "ras".
+                    ras++;
+                }
+            }
+            // Step 2: Generate RA filters
+            gen = new ApfGenerator();
+            // This is guaranteed to return true because of the check in maybeInstall.
+            gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+            for (Ra ra : mRas) {
+                if (ras-- == 0) break;
+                if (ra.isExpired()) continue;
+                programMinLifetime = Math.min(programMinLifetime, ra.generateFilter(gen));
+            }
+            // Execution will reach the end of the program if no filters match, which will pass the
+            // packet to the AP.
+            program = gen.generate();
+        } catch (IllegalInstructionException e) {
+            Log.e(TAG, "Program failed to generate: ", e);
+            return;
+        }
+        mLastTimeInstalledProgram = curTime();
+        mLastInstalledProgramMinLifetime = programMinLifetime;
+        hexDump("Installing filter: ", program, program.length);
+        mConnectivityService.pushApfProgramToNetwork(mNai, program);
+    }
+
+    // Install a new filter program if the last installed one will die soon.
+    private void maybeInstallNewProgram() {
+        if (mRas.size() == 0) return;
+        // If the current program doesn't expire for a while, don't bother updating.
+        long expiry = mLastTimeInstalledProgram + mLastInstalledProgramMinLifetime;
+        if (expiry < curTime() + MAX_PROGRAM_LIFETIME_WORTH_REFRESHING) {
+            installNewProgram();
+        }
+    }
+
+    private void hexDump(String msg, byte[] packet, int length) {
+        log(msg + HexDump.toHexString(packet, 0, length));
+    }
+
+    private void processRa(byte[] packet, int length) {
+        hexDump("Read packet = ", packet, length);
+
+        // Have we seen this RA before?
+        for (int i = 0; i < mRas.size(); i++) {
+            Ra ra = mRas.get(i);
+            if (ra.matches(packet, length)) {
+                log("matched RA");
+                // Update lifetimes.
+                ra.mLastSeen = curTime();
+                ra.mMinLifetime = ra.minLifetime(packet, length);
+
+                // Keep mRas in LRU order so as to prioritize generating filters for recently seen
+                // RAs. LRU prioritizes this because RA filters are generated in order from mRas
+                // until the filter program exceeds the maximum filter program size allowed by the
+                // chipset, so RAs appearing earlier in mRas are more likely to make it into the
+                // filter program.
+                // TODO: consider sorting the RAs in order of increasing expiry time as well.
+                // Swap to front of array.
+                mRas.add(0, mRas.remove(i));
+
+                maybeInstallNewProgram();
+                return;
+            }
+        }
+        // Purge expired RAs.
+        for (int i = 0; i < mRas.size();) {
+            if (mRas.get(i).isExpired()) {
+                log("expired RA");
+                mRas.remove(i);
+            } else {
+                i++;
+            }
+        }
+        // TODO: figure out how to proceed when we've received more then MAX_RAS RAs.
+        if (mRas.size() >= MAX_RAS) return;
+        try {
+            log("adding RA");
+            mRas.add(new Ra(packet, length));
+        } catch (Exception e) {
+            Log.e(TAG, "Error parsing RA: " + e);
+            return;
+        }
+        installNewProgram();
+    }
+
+    /**
+     * Install an {@link ApfFilter} on {@code nai} if {@code nai} supports packet
+     * filtering using APF programs.
+     */
+    public static void maybeInstall(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+        if (nai.networkMisc == null) return;
+        if (nai.networkMisc.apfVersionSupported == 0) return;
+        if (nai.networkMisc.maximumApfProgramSize < 200) {
+            Log.e(TAG, "Uselessly small APF size limit: " + nai.networkMisc.maximumApfProgramSize);
+            return;
+        }
+        // For now only support generating programs for Ethernet frames. If this restriction is
+        // lifted:
+        //   1. the program generator will need its offsets adjusted.
+        //   2. the packet filter attached to our packet socket will need its offset adjusted.
+        if (nai.networkMisc.apfPacketFormat != ARPHRD_ETHER) return;
+        if (!new ApfGenerator().setApfVersion(nai.networkMisc.apfVersionSupported)) {
+            Log.e(TAG, "Unsupported APF version: " + nai.networkMisc.apfVersionSupported);
+            return;
+        }
+        nai.apfFilter = new ApfFilter(connectivityService, nai);
+    }
+
+    public void shutdown() {
+        if (mReceiveThread != null) {
+            log("shuting down");
+            mReceiveThread.halt();  // Also closes socket.
+            mReceiveThread = null;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index a9eaeee..b390884 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -16,13 +16,11 @@
 
 package com.android.server.connectivity;
 
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-
 import java.net.Inet4Address;
 
 import android.content.Context;
 import android.net.InterfaceConfiguration;
+import android.net.ConnectivityManager;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkAgent;
@@ -34,6 +32,7 @@
 import android.util.Slog;
 
 import com.android.server.net.BaseNetworkObserver;
+import com.android.internal.util.ArrayUtils;
 
 /**
  * @hide
@@ -46,6 +45,13 @@
     // This must match the interface prefix in clatd.c.
     private static final String CLAT_PREFIX = "v4-";
 
+    // The network types we will start clatd on.
+    private static final int[] NETWORK_TYPES = {
+            ConnectivityManager.TYPE_MOBILE,
+            ConnectivityManager.TYPE_WIFI,
+            ConnectivityManager.TYPE_ETHERNET,
+    };
+
     private final INetworkManagementService mNMService;
 
     // ConnectivityService Handler for LinkProperties updates.
@@ -90,7 +96,7 @@
                 (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
         // Only support clat on mobile and wifi for now, because these are the only IPv6-only
         // networks we can connect to.
-        return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
+        return connected && !hasIPv4Address && ArrayUtils.contains(NETWORK_TYPES, netType);
     }
 
     /**
@@ -221,7 +227,7 @@
     }
 
     private void maybeSetIpv6NdOffload(String iface, boolean on) {
-        if (mNetwork.networkInfo.getType() != TYPE_WIFI) {
+        if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
             return;
         }
         try {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index c5d38cb..b4c71c1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -32,6 +32,7 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.server.ConnectivityService;
 import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.connectivity.ApfFilter;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -163,6 +164,8 @@
     // Used by ConnectivityService to keep track of 464xlat.
     public Nat464Xlat clatd;
 
+    public ApfFilter apfFilter;
+
     public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
             LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
             NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService) {
@@ -175,6 +178,7 @@
         currentScore = score;
         networkMonitor = connService.createNetworkMonitor(context, handler, this, defaultRequest);
         networkMisc = misc;
+        apfFilter.maybeInstall(connService, this);
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index ed68abe..e08fad4 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1559,11 +1559,11 @@
      * called from native code to update SV info
      */
     private void reportSvStatus() {
-        int svCount = native_read_sv_status(mSvidWithFlags, mSnrs, mSvElevations, mSvAzimuths);
+        int svCount = native_read_sv_status(mSvidWithFlags, mCn0s, mSvElevations, mSvAzimuths);
         mListenerHelper.onSvStatusChanged(
                 svCount,
                 mSvidWithFlags,
-                mSnrs,
+                mCn0s,
                 mSvElevations,
                 mSvAzimuths);
 
@@ -1578,7 +1578,7 @@
             }
             if (VERBOSE) {
                 Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
-                        " snr: " + mSnrs[i]/10 +
+                        " cn0: " + mCn0s[i]/10 +
                         " elev: " + mSvElevations[i] +
                         " azimuth: " + mSvAzimuths[i] +
                         ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
@@ -2402,7 +2402,7 @@
 
     // preallocated arrays, to avoid memory allocation in reportStatus()
     private int mSvidWithFlags[] = new int[MAX_SVS];
-    private float mSnrs[] = new float[MAX_SVS];
+    private float mCn0s[] = new float[MAX_SVS];
     private float mSvElevations[] = new float[MAX_SVS];
     private float mSvAzimuths[] = new float[MAX_SVS];
     private int mSvCount;
@@ -2424,7 +2424,7 @@
     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[] prnWithFlags, float[] snrs, float[] elevations,
+    private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
             float[] azimuths);
     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/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index d9e8e91..734a8d4 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -72,7 +72,7 @@
                 status = GnssMeasurementsEvent.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GnssMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
+                status = GnssMeasurementsEvent.STATUS_GNSS_LOCATION_DISABLED;
                 break;
             case RESULT_UNKNOWN:
                 return null;
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 57bce4b..fdef31f 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -73,7 +73,8 @@
                 status = GnssNavigationMessageEvent.STATUS_NOT_SUPPORTED;
                 break;
             case RESULT_GPS_LOCATION_DISABLED:
-                status = GnssNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
+                status = GnssNavigationMessageEvent
+                        .STATUS_GNSS_LOCATION_DISABLED;
                 break;
             case RESULT_UNKNOWN:
                 return null;
diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 0b3111c..d471e45 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -75,7 +75,7 @@
     public void onSvStatusChanged(
             final int svCount,
             final int[] prnWithFlags,
-            final float[] snrs,
+            final float[] cn0s,
             final float[] elevations,
             final float[] azimuths) {
         Operation operation = new Operation() {
@@ -84,7 +84,7 @@
                 listener.onSvStatusChanged(
                         svCount,
                         prnWithFlags,
-                        snrs,
+                        cn0s,
                         elevations,
                         azimuths);
             }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e8d27db..3855579 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1320,7 +1320,7 @@
 
         @Override
         public int getImportance(String pkg, int uid) {
-            checkCallerIsSystem();
+            enforceSystemOrSystemUI("Caller not system or systemui");
             return mRankingHelper.getImportance(pkg, uid);
         }
 
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 94b3b2d..3d2a355 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -180,10 +180,5 @@
             return dexoptFlags | DEXOPT_OTA;
         }
 
-        @Override
-        protected void recordSuccessfulDexopt(Package pkg, String instructionSet) {
-            // Never record the dexopt, as it's in the B partition.
-        }
-
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index a084d86..c9613b4 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -113,15 +113,6 @@
     }
 
     /**
-     * Determine whether the package should be skipped for the given instruction set. A return
-     * value of true means the package will be skipped. A return value of false means that the
-     * package will be further investigated, and potentially compiled.
-     */
-    protected boolean shouldSkipBasedOnISA(PackageParser.Package pkg, String instructionSet) {
-        return pkg.mDexOptPerformed.contains(instructionSet);
-    }
-
-    /**
      * Adjust the given dexopt-needed value. Can be overridden to influence the decision to
      * optimize or not (and in what way).
      */
@@ -136,13 +127,6 @@
         return dexoptFlags;
     }
 
-    /**
-     * Update the package status after a successful compilation.
-     */
-    protected void recordSuccessfulDexopt(PackageParser.Package pkg, String instructionSet) {
-        pkg.mDexOptPerformed.add(instructionSet);
-    }
-
     private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
             boolean useProfiles, boolean extractOnly) {
         final String[] instructionSets = targetInstructionSets != null ?
@@ -159,11 +143,6 @@
         boolean performedDexOpt = false;
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
         for (String dexCodeInstructionSet : dexCodeInstructionSets) {
-            if (!useProfiles && shouldSkipBasedOnISA(pkg, dexCodeInstructionSet)) {
-                // Skip only if we do not use profiles since they might trigger a recompilation.
-                continue;
-            }
-
             for (String path : paths) {
                 if (useProfiles && isUsedByOtherApps(path)) {
                     // We cannot use profile guided compilation if the apk was used by another app.
@@ -172,35 +151,44 @@
                 int dexoptNeeded;
 
                 try {
-                    dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
-                            dexCodeInstructionSet, /* defer */false);
+                    int compilationTypeMask = 0;
+                    if (extractOnly) {
+                        // For extract only, any type of compilation is good.
+                        compilationTypeMask = DexFile.COMPILATION_TYPE_FULL
+                            | DexFile.COMPILATION_TYPE_PROFILE_GUIDE
+                            | DexFile.COMPILATION_TYPE_EXTRACT_ONLY;
+                    } else {
+                        // Branch taken for profile guide and full compilation.
+                        // Profile guide compilation should only recompile a previous
+                        // profile compiled/extract only file and should not be attempted if the
+                        // apk is already fully compiled. So test against a full compilation type.
+                        compilationTypeMask = DexFile.COMPILATION_TYPE_FULL;
+                    }
+                    dexoptNeeded = DexFile.getDexOptNeeded(path,
+                            dexCodeInstructionSet, compilationTypeMask);
                 } catch (IOException ioe) {
                     Slog.w(TAG, "IOException reading apk: " + path, ioe);
                     return DEX_OPT_FAILED;
                 }
                 dexoptNeeded = adjustDexoptNeeded(dexoptNeeded);
 
-                if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
-                    if (useProfiles) {
-                        // Profiles may trigger re-compilation. The final decision is taken in
-                        // installd.
-                        dexoptNeeded = DexFile.DEX2OAT_NEEDED;
-                    } else {
-                        // No dexopt needed and we don't use profiles. Nothing to do.
-                        continue;
-                    }
-                }
                 final String dexoptType;
                 String oatDir = null;
-                if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
-                    dexoptType = "dex2oat";
-                    oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
-                } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
-                    dexoptType = "patchoat";
-                } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
-                    dexoptType = "self patchoat";
-                } else {
-                    throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
+                switch (dexoptNeeded) {
+                    case DexFile.NO_DEXOPT_NEEDED:
+                        continue;
+                    case DexFile.DEX2OAT_NEEDED:
+                        dexoptType = "dex2oat";
+                        oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
+                        break;
+                    case DexFile.PATCHOAT_NEEDED:
+                        dexoptType = "patchoat";
+                        break;
+                    case DexFile.SELF_PATCHOAT_NEEDED:
+                        dexoptType = "self patchoat";
+                        break;
+                    default:
+                        throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded);
                 }
 
 
@@ -226,15 +214,6 @@
                     Slog.w(TAG, "Failed to dexopt", e);
                 }
             }
-
-            if (!extractOnly) {
-                // At this point we haven't failed dexopt and we haven't deferred dexopt. We must
-                // either have either succeeded dexopt, or have had getDexOptNeeded tell us
-                // it isn't required. We therefore mark that this package doesn't need dexopt unless
-                // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
-                // it.
-                recordSuccessfulDexopt(pkg, dexCodeInstructionSet);
-            }
         }
 
         // If we've gotten here, we're sure that no error occurred and that we haven't
@@ -317,12 +296,6 @@
         }
 
         @Override
-        protected boolean shouldSkipBasedOnISA(Package pkg, String instructionSet) {
-            // Forced compilation, never skip.
-            return false;
-        }
-
-        @Override
         protected int adjustDexoptNeeded(int dexoptNeeded) {
             // Ensure compilation, no matter the current state.
             // TODO: The return value is wrong when patchoat is needed.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 55be545..86f2f97 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -639,9 +639,6 @@
     // List of packages names to keep cached, even if they are uninstalled for all users
     private List<String> mKeepUninstalledPackages;
 
-    private boolean mUseJitProfiles =
-            SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
-
     private static class IFVerificationParams {
         PackageParser.Package pkg;
         boolean replacing;
@@ -2161,10 +2158,12 @@
                         }
 
                         try {
-                            int dexoptNeeded = DexFile.getDexOptNeeded(lib, null, dexCodeInstructionSet, false);
+                            // Shared libraries do not have profiles so we perform a full
+                            // AOT compilation (if needed).
+                            int dexoptNeeded = DexFile.getDexOptNeeded(
+                                    lib, dexCodeInstructionSet,
+                                    DexFile.COMPILATION_TYPE_FULL);
                             if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                                // Shared libraries do not have profiles so we perform a full
-                                // AOT compilation.
                                 mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
                                         dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
                                         StorageManager.UUID_PRIVATE_INTERNAL,
@@ -6838,7 +6837,7 @@
 
         // Extract pacakges only if profile-guided compilation is enabled because
         // otherwise BackgroundDexOptService will not dexopt them later.
-        if (!mUseJitProfiles || !isUpgrade()) {
+        if (!isUpgrade()) {
             return;
         }
 
@@ -6920,10 +6919,6 @@
 
             targetInstructionSet = instructionSet != null ? instructionSet :
                     getPrimaryInstructionSet(p.applicationInfo);
-            if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
-                // Skip only if we do not use profiles since they might trigger a recompilation.
-                return false;
-            }
         }
         long callingId = Binder.clearCallingIdentity();
         try {
@@ -13853,21 +13848,17 @@
                 return;
             }
 
-            // Extract package to save the VM unzipping the APK in memory during
-            // launch. Only do this if profile-guided compilation is enabled because
-            // otherwise BackgroundDexOptService will not dexopt the package later.
-            if (mUseJitProfiles) {
-                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-                // Do not run PackageDexOptimizer through the local performDexOpt
-                // method because `pkg` is not in `mPackages` yet.
-                int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
-                        false /* useProfiles */, true /* extractOnly */);
-                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-                if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
-                    String msg = "Extracking package failed for " + pkgName;
-                    res.setError(INSTALL_FAILED_DEXOPT, msg);
-                    return;
-                }
+
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+            // Do not run PackageDexOptimizer through the local performDexOpt
+            // method because `pkg` is not in `mPackages` yet.
+            int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
+                    false /* useProfiles */, true /* extractOnly */);
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+                String msg = "Extracking package failed for " + pkgName;
+                res.setError(INSTALL_FAILED_DEXOPT, msg);
+                return;
             }
         }
 
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ba0d340..a0a971a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -882,6 +882,9 @@
             wallpaper = mLockWallpaperMap.get(userId);
             if (wallpaper == null) {
                 // It's already gone; we're done.
+                if (DEBUG) {
+                    Slog.i(TAG, "Lock wallpaper already cleared");
+                }
                 return;
             }
         } else {
@@ -902,14 +905,19 @@
                 wallpaper.wallpaperFile.delete();
                 wallpaper.cropFile.delete();
                 if (which == FLAG_SET_LOCK) {
+                    mLockWallpaperMap.remove(userId);
                     final IWallpaperManagerCallback cb = mKeyguardListener;
                     if (cb != null) {
+                        if (DEBUG) {
+                            Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
+                        }
                         try {
                             cb.onWallpaperChanged();
                         } catch (RemoteException e) {
                             // Oh well it went away; no big deal
                         }
                     }
+                    saveSettingsLocked(userId);
                     return;
                 }
             }
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index c97323c..aa14fff 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -140,7 +140,7 @@
             ALOGD("Unknown constellation type with Svid = %d.", info.svid);
             info.constellation = GNSS_CONSTELLATION_UNKNOWN;
         }
-        info.snr = sv_status->sv_list[i].snr;
+        info.c_n0_dbhz = 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;
@@ -698,12 +698,12 @@
 }
 
 static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
-        jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
+        jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
         jfloatArray azumArray)
 {
     // this should only be called from within a call to reportSvStatus
     jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
-    jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
+    jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
 
@@ -713,13 +713,13 @@
         svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
             (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
             info.flags;
-        snrs[i] = info.snr;
+        cn0s[i] = info.c_n0_dbhz;
         elev[i] = info.elevation;
         azim[i] = info.azimuth;
     }
 
     env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
-    env->ReleaseFloatArrayElements(snrArray, snrs, 0);
+    env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
     env->ReleaseFloatArrayElements(elevArray, elev, 0);
     env->ReleaseFloatArrayElements(azumArray, azim, 0);
     return (jint) sGnssSvListSize;
@@ -1095,7 +1095,9 @@
     JavaObject object(env, "android/location/GnssClock");
     GpsClockFlags flags = clock->flags;
 
-    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
+    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+           LeapSecond,
+           static_cast<int32_t>(clock->leap_second));
 
     // GnssClock only supports the more effective HW_CLOCK type, so type
     // handling and documentation complexity has been removed.  To convert the
@@ -1122,18 +1124,18 @@
         break;
     }
 
-    SET(TimeInNs, clock->time_ns);
+    SET(TimeNanos, clock->time_ns);
     SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyInNs,
+           TimeUncertaintyNanos,
            clock->time_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
     SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyInNs,
+           BiasUncertaintyNanos,
            clock->bias_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
     SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyInNsPerSec,
+           DriftUncertaintyNanosPerSecond,
            clock->drift_uncertainty_nsps);
 
     return object.get();
@@ -1143,20 +1145,21 @@
     JavaObject object(env, "android/location/GnssClock");
     GpsClockFlags flags = clock->flags;
 
-    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
-    SET(Type, static_cast<uint8_t>(GPS_CLOCK_TYPE_LOCAL_HW_TIME));
-    SET(TimeInNs, clock->time_ns);
+    SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+           LeapSecond,
+           static_cast<int32_t>(clock->leap_second));
+    SET(TimeNanos, clock->time_ns);
     SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
-           TimeUncertaintyInNs,
+           TimeUncertaintyNanos,
            clock->time_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
-    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+    SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
     SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
-           BiasUncertaintyInNs,
+           BiasUncertaintyNanos,
            clock->bias_uncertainty_ns);
-    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
     SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
-           DriftUncertaintyInNsPerSec,
+           DriftUncertaintyNanosPerSecond,
            clock->drift_uncertainty_nsps);
 
     SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
@@ -1168,41 +1171,30 @@
                                          GpsMeasurement* measurement) {
     JavaObject object(env, "android/location/GnssMeasurement");
     GpsMeasurementFlags flags = measurement->flags;
-    SET(Svid, static_cast<int16_t>(measurement->prn));
+    SET(Svid, static_cast<int32_t>(measurement->prn));
     if (measurement->prn >= 1 || measurement->prn <= 32) {
-        SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
+        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
     } else {
         ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
         SET(ConstellationType,
-            static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
+            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
     }
-    SET(TimeOffsetInNs, measurement->time_offset_ns);
-    SET(State, measurement->state);
-    SET(ReceivedSvTimeInNs, measurement->received_gps_tow_ns);
-    SET(ReceivedSvTimeUncertaintyInNs,
+    SET(TimeOffsetNanos, measurement->time_offset_ns);
+    SET(State, static_cast<int32_t>(measurement->state));
+    SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
+    SET(ReceivedSvTimeUncertaintyNanos,
         measurement->received_gps_tow_uncertainty_ns);
-    SET(Cn0InDbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
-    SET(PseudorangeRateUncertaintyInMetersPerSec,
+    SET(Cn0DbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyMetersPerSecond,
         measurement->pseudorange_rate_uncertainty_mps);
-    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
-    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
-    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+    SET(AccumulatedDeltaRangeState,
+        static_cast<int32_t>(measurement->accumulated_delta_range_state));
+    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyMeters,
         measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
-           PseudorangeInMeters,
-           measurement->pseudorange_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
-           PseudorangeUncertaintyInMeters,
-           measurement->pseudorange_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
-           CodePhaseInChips,
-           measurement->code_phase_chips);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
-           CodePhaseUncertaintyInChips,
-           measurement->code_phase_uncertainty_chips);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyInHz,
+           CarrierFrequencyHz,
            measurement->carrier_frequency_hz);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
            CarrierCycles,
@@ -1213,33 +1205,8 @@
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
            CarrierPhaseUncertainty,
            measurement->carrier_phase_uncertainty);
-    SET(LossOfLock, measurement->loss_of_lock);
-    SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
-    SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
-           TimeFromLastBitInMs,
-           measurement->time_from_last_bit_ms);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
-           DopplerShiftInHz,
-           measurement->doppler_shift_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
-           DopplerShiftUncertaintyInHz,
-           measurement->doppler_shift_uncertainty_hz);
     SET(MultipathIndicator, measurement->multipath_indicator);
     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
-           ElevationInDeg,
-           measurement->elevation_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
-           ElevationUncertaintyInDeg,
-           measurement->elevation_uncertainty_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
-           AzimuthInDeg,
-           measurement->azimuth_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
-           AzimuthUncertaintyInDeg,
-           measurement->azimuth_uncertainty_deg);
-    SET(UsedInFix,
-        (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
 
     return object.get();
 }
@@ -1250,34 +1217,23 @@
     GpsMeasurementFlags flags = measurement->flags;
 
     SET(Svid, measurement->svid);
-    SET(ConstellationType, measurement->constellation);
-    SET(TimeOffsetInNs, measurement->time_offset_ns);
-    SET(State, measurement->state);
-    SET(ReceivedSvTimeInNs, measurement->received_sv_time_in_ns);
-    SET(ReceivedSvTimeUncertaintyInNs,
+    SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
+    SET(TimeOffsetNanos, measurement->time_offset_ns);
+    SET(State, static_cast<int32_t>(measurement->state));
+    SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+    SET(ReceivedSvTimeUncertaintyNanos,
         measurement->received_sv_time_uncertainty_in_ns);
-    SET(Cn0InDbHz, measurement->c_n0_dbhz);
-    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
-    SET(PseudorangeRateUncertaintyInMetersPerSec,
+    SET(Cn0DbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyMetersPerSecond,
         measurement->pseudorange_rate_uncertainty_mps);
-    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
-    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
-    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+    SET(AccumulatedDeltaRangeState,
+        static_cast<int32_t>(measurement->accumulated_delta_range_state));
+    SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyMeters,
         measurement->accumulated_delta_range_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
-           PseudorangeInMeters,
-           measurement->pseudorange_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
-           PseudorangeUncertaintyInMeters,
-           measurement->pseudorange_uncertainty_m);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
-           CodePhaseInChips,
-           measurement->code_phase_chips);
-    SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
-           CodePhaseUncertaintyInChips,
-           measurement->code_phase_uncertainty_chips);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
-           CarrierFrequencyInHz,
+           CarrierFrequencyHz,
            measurement->carrier_frequency_hz);
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
            CarrierCycles,
@@ -1288,32 +1244,8 @@
     SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
            CarrierPhaseUncertainty,
            measurement->carrier_phase_uncertainty);
-    SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
-    SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
-           TimeFromLastBitInMs,
-           measurement->time_from_last_bit_ms);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
-           DopplerShiftInHz,
-           measurement->doppler_shift_hz);
-    SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
-           DopplerShiftUncertaintyInHz,
-           measurement->doppler_shift_uncertainty_hz);
     SET(MultipathIndicator, measurement->multipath_indicator);
     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
-           ElevationInDeg,
-           measurement->elevation_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
-           ElevationUncertaintyInDeg,
-           measurement->elevation_uncertainty_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
-           AzimuthInDeg,
-           measurement->azimuth_deg);
-    SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
-           AzimuthUncertaintyInDeg,
-           measurement->azimuth_uncertainty_deg);
-    SET(UsedInFix,
-        (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
 
     return object.get();
 }
@@ -1493,21 +1425,22 @@
         return NULL;
     }
     JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Svid, static_cast<int16_t>(message->prn));
+    SET(Svid, static_cast<int32_t>(message->prn));
     if (message->prn >=1 && message->prn <= 32) {
-        SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
+        SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
         // Legacy driver doesn't set the higher byte to constellation type
         // correctly. Set the higher byte to 'GPS'.
-        SET(Type, static_cast<int16_t>(message->type | 0x0100));
+        SET(Type, static_cast<int32_t>(message->type | 0x0100));
     } else {
         ALOGD("Unknown constellation type with Svid = %d.", message->prn);
         SET(ConstellationType,
-            static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
-        SET(Type, static_cast<int16_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
+            static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+        SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
     }
-    SET(MessageId, message->message_id);
-    SET(SubmessageId, message->submessage_id);
+    SET(MessageId, static_cast<int32_t>(message->message_id));
+    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
     object.callSetter("setData", data, dataLength);
+    SET(Status, static_cast<int32_t>(message->status));
     return object.get();
 }
 
@@ -1520,11 +1453,12 @@
         return NULL;
     }
     JavaObject object(env, "android/location/GnssNavigationMessage");
-    SET(Type, message->type);
-    SET(Svid, message->svid);
-    SET(MessageId, message->message_id);
-    SET(SubmessageId, message->submessage_id);
+    SET(Type, static_cast<int32_t>(message->type));
+    SET(Svid, static_cast<int32_t>(message->svid));
+    SET(MessageId, static_cast<int32_t>(message->message_id));
+    SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
     object.callSetter("setData", data, dataLength);
+    SET(Status, static_cast<int32_t>(message->status));
     return object.get();
 }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0252ea4..1490109 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5530,7 +5530,8 @@
         Preconditions.checkNotNull(packageName, "packageName is null");
         final int callingUid = mInjector.binderGetCallingUid();
         try {
-            int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, 0);
+            int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
+                    UserHandle.getUserId(callingUid));
             if (uid != callingUid) {
                 throw new SecurityException("Invalid packageName");
             }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index c34d4a9..e851c8d 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -518,6 +518,14 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+            int badgeDensity) {
+        throw new UnsupportedOperationException();
+    }
+
+
     @Override
     public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
         throw new UnsupportedOperationException();
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index c2ad9ef..663e1e2 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -40,10 +40,8 @@
 built_ext_classes := $(call java-lib-files,ext)
 built_ext_data := $(call intermediates-dir-for, \
 			JAVA_LIBRARIES,ext,,COMMON)/javalib.jar
-built_icudata_dep := $(call java-lib-deps,icu4j-icudata-jarjar)
-built_icudata_data := $(call java-lib-files,icu4j-icudata-jarjar)
-built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-jarjar)
-built_icutzdata_data := $(call java-lib-files,icu4j-icutzdata-jarjar)
+built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
+built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
 
 built_layoutlib_create_jar := $(call intermediates-dir-for, \
 			JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
@@ -77,8 +75,8 @@
 	             $(built_core_classes) \
 	             $(built_framework_classes) \
 	             $(built_ext_classes) \
-		     $(built_icudata_data) \
-		     $(built_icutzdata_data) \
+		     $(built_icudata_dep) \
+		     $(built_icutzdata_dep) \
 	             $(built_ext_data)
 	$(hide) ls -l $(built_framework_classes)
 
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index db4c6dc6..ae42ba6 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -305,6 +305,12 @@
         return defValue;
     }
 
+    @Override
+    public ComplexColor getComplexColor(int index) {
+        // TODO: Support GradientColor
+        return getColorStateList(index);
+    }
+
     /**
      * Retrieve the ColorStateList for the attribute at <var>index</var>.
      * The value may be either a single solid color or a reference to
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index c4fbd56..fa880f0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -142,7 +142,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setBitmap(long canvas, Bitmap bitmap) {
+    public static void native_setBitmap(long canvas, Bitmap bitmap) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
         Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
         if (canvasDelegate == null || bitmapDelegate==null) {
@@ -153,7 +153,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_isOpaque(long nativeCanvas) {
+    public static boolean native_isOpaque(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -164,10 +164,10 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
+    public static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
 
     @LayoutlibDelegate
-    /*package*/ static int native_getWidth(long nativeCanvas) {
+    public static int native_getWidth(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -178,7 +178,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getHeight(long nativeCanvas) {
+    public static int native_getHeight(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -189,7 +189,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_save(long nativeCanvas, int saveFlags) {
+    public static int native_save(long nativeCanvas, int saveFlags) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -200,7 +200,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_saveLayer(long nativeCanvas, float l,
+    public static int native_saveLayer(long nativeCanvas, float l,
                                                float t, float r, float b,
                                                long paint, int layerFlags) {
         // get the delegate from the native int.
@@ -219,7 +219,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
+    public static int native_saveLayerAlpha(long nativeCanvas, float l,
                                                     float t, float r, float b,
                                                     int alpha, int layerFlags) {
         // get the delegate from the native int.
@@ -232,7 +232,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
+    public static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
         // FIXME: implement throwOnUnderflow.
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -244,7 +244,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount,
+    public static void native_restoreToCount(long nativeCanvas, int saveCount,
             boolean throwOnUnderflow) {
         // FIXME: implement throwOnUnderflow.
         // get the delegate from the native int.
@@ -257,7 +257,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int native_getSaveCount(long nativeCanvas) {
+    public static int native_getSaveCount(long nativeCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -268,7 +268,7 @@
     }
 
     @LayoutlibDelegate
-   /*package*/ static void native_translate(long nativeCanvas, float dx, float dy) {
+   public static void native_translate(long nativeCanvas, float dx, float dy) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -279,7 +279,7 @@
     }
 
     @LayoutlibDelegate
-       /*package*/ static void native_scale(long nativeCanvas, float sx, float sy) {
+       public static void native_scale(long nativeCanvas, float sx, float sy) {
             // get the delegate from the native int.
             Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
             if (canvasDelegate == null) {
@@ -290,7 +290,7 @@
         }
 
     @LayoutlibDelegate
-    /*package*/ static void native_rotate(long nativeCanvas, float degrees) {
+    public static void native_rotate(long nativeCanvas, float degrees) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -301,7 +301,7 @@
     }
 
     @LayoutlibDelegate
-   /*package*/ static void native_skew(long nativeCanvas, float kx, float ky) {
+   public static void native_skew(long nativeCanvas, float kx, float ky) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -325,7 +325,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_concat(long nCanvas, long nMatrix) {
+    public static void native_concat(long nCanvas, long nMatrix) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
         if (canvasDelegate == null) {
@@ -353,7 +353,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
+    public static void native_setMatrix(long nCanvas, long nMatrix) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
         if (canvasDelegate == null) {
@@ -383,7 +383,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_clipRect(long nCanvas,
+    public static boolean native_clipRect(long nCanvas,
                                                   float left, float top,
                                                   float right, float bottom,
                                                   int regionOp) {
@@ -397,7 +397,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_clipPath(long nativeCanvas,
+    public static boolean native_clipPath(long nativeCanvas,
                                                   long nativePath,
                                                   int regionOp) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -414,7 +414,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_clipRegion(long nativeCanvas,
+    public static boolean native_clipRegion(long nativeCanvas,
                                                     long nativeRegion,
                                                     int regionOp) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -431,7 +431,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
+    public static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
             return;
@@ -446,7 +446,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_getClipBounds(long nativeCanvas,
+    public static boolean native_getClipBounds(long nativeCanvas,
                                                        Rect bounds) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -467,7 +467,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_getCTM(long canvas, long matrix) {
+    public static void native_getCTM(long canvas, long matrix) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
         if (canvasDelegate == null) {
@@ -484,13 +484,13 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_quickReject(long nativeCanvas, long path) {
+    public static boolean native_quickReject(long nativeCanvas, long path) {
         // FIXME properly implement quickReject
         return false;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_quickReject(long nativeCanvas,
+    public static boolean native_quickReject(long nativeCanvas,
                                                      float left, float top,
                                                      float right, float bottom) {
         // FIXME properly implement quickReject
@@ -498,7 +498,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
+    public static void native_drawColor(long nativeCanvas, final int color, final int mode) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
@@ -529,14 +529,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
+    public static void native_drawPaint(long nativeCanvas, long paint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
                 "Canvas.drawPaint is not supported.", null, null /*data*/);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPoint(long nativeCanvas, float x, float y,
+    public static void native_drawPoint(long nativeCanvas, float x, float y,
             long nativePaint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -544,7 +544,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
+    public static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
             long nativePaint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -552,7 +552,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawLine(long nativeCanvas,
+    public static void native_drawLine(long nativeCanvas,
             final float startX, final float startY, final float stopX, final float stopY,
             long paint) {
         draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -565,7 +565,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawLines(long nativeCanvas,
+    public static void native_drawLines(long nativeCanvas,
             final float[] pts, final int offset, final int count,
             long nativePaint) {
         draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
@@ -581,7 +581,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawRect(long nativeCanvas,
+    public static void native_drawRect(long nativeCanvas,
             final float left, final float top, final float right, final float bottom, long paint) {
 
         draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -607,7 +607,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawOval(long nativeCanvas, final float left,
+    public static void native_drawOval(long nativeCanvas, final float left,
             final float top, final float right, final float bottom, long paint) {
         if (right > left && bottom > top) {
             draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -634,7 +634,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawCircle(long nativeCanvas,
+    public static void native_drawCircle(long nativeCanvas,
             float cx, float cy, float radius, long paint) {
         native_drawOval(nativeCanvas,
                 cx - radius, cy - radius, cx + radius, cy + radius,
@@ -642,7 +642,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawArc(long nativeCanvas,
+    public static void native_drawArc(long nativeCanvas,
             final float left, final float top, final float right, final float bottom,
             final float startAngle, final float sweep,
             final boolean useCenter, long paint) {
@@ -674,7 +674,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawRoundRect(long nativeCanvas,
+    public static void native_drawRoundRect(long nativeCanvas,
             final float left, final float top, final float right, final float bottom,
             final float rx, final float ry, long paint) {
         draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -704,7 +704,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
+    public static void native_drawPath(long nativeCanvas, long path, long paint) {
         final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
         if (pathDelegate == null) {
             return;
@@ -756,7 +756,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawRegion(long nativeCanvas, long nativeRegion,
+    public static void native_drawRegion(long nativeCanvas, long nativeRegion,
             long nativePaint) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -764,7 +764,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
+    public static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
             long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
             final float dstRight, final float dstBottom, long nativePaintOrZero,
             final int screenDensity, final int bitmapDensity) {
@@ -811,7 +811,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+    public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
                                                  float left, float top,
                                                  long nativePaintOrZero,
                                                  int canvasDensity,
@@ -833,7 +833,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+    public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
                                  float srcLeft, float srcTop, float srcRight, float srcBottom,
                                  float dstLeft, float dstTop, float dstRight, float dstBottom,
                                  long nativePaintOrZero, int screenDensity, int bitmapDensity) {
@@ -849,7 +849,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
+    public static void native_drawBitmap(long nativeCanvas, int[] colors,
                                                 int offset, int stride, final float x,
                                                  final float y, int width, int height,
                                                  boolean hasAlpha,
@@ -874,7 +874,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
+    public static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
                                                       long nMatrix, long nPaint) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
@@ -915,7 +915,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
+    public static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
             int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
             int colorOffset, long nPaint) {
         // FIXME
@@ -924,7 +924,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
+    public static void nativeDrawVertices(long nCanvas, int mode, int n,
             float[] verts, int vertOffset,
             float[] texs, int texOffset,
             int[] colors, int colorOffset,
@@ -936,14 +936,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
+    public static void native_drawText(long nativeCanvas, char[] text, int index, int count,
             float startX, float startY, int flags, long paint, long typeface) {
         drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
                 paint, typeface);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawText(long nativeCanvas, String text,
+    public static void native_drawText(long nativeCanvas, String text,
             int start, int end, float x, float y, final int flags, long paint,
             long typeface) {
         int count = end - start;
@@ -954,7 +954,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
+    public static void native_drawTextRun(long nativeCanvas, String text,
             int start, int end, int contextStart, int contextEnd,
             float x, float y, boolean isRtl, long paint, long typeface) {
         int count = end - start;
@@ -965,14 +965,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
+    public static void native_drawTextRun(long nativeCanvas, char[] text,
             int start, int count, int contextStart, int contextCount,
             float x, float y, boolean isRtl, long paint, long typeface) {
         drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+    public static void native_drawTextOnPath(long nativeCanvas,
                                                      char[] text, int index,
                                                      int count, long path,
                                                      float hOffset,
@@ -984,7 +984,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+    public static void native_drawTextOnPath(long nativeCanvas,
                                                      String text, long path,
                                                      float hOffset,
                                                      float vOffset,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 514d785..839c182 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -223,6 +223,10 @@
         return mColorFilter;
     }
 
+    public void setColorFilter(long colorFilterPtr) {
+        mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr);
+    }
+
     /**
      * Returns the {@link Shader} delegate or null if none have been set
      *
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index e1da27b..08f0cb4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -572,7 +572,7 @@
         return null;
     }
 
-    private static void addPath(long destPath, long srcPath, AffineTransform transform) {
+    public static void addPath(long destPath, long srcPath, AffineTransform transform) {
         Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
         if (destPathDelegate == null) {
             return;
@@ -630,7 +630,7 @@
      * Fills the given {@link RectF} with the path bounds.
      * @param bounds the RectF to be filled.
      */
-    private void fillBounds(RectF bounds) {
+    public void fillBounds(RectF bounds) {
         Rectangle2D rect = mPath.getBounds2D();
         bounds.left = (float)rect.getMinX();
         bounds.right = (float)rect.getMaxX();
@@ -644,7 +644,7 @@
      * @param x The x-coordinate of the start of a new contour
      * @param y The y-coordinate of the start of a new contour
      */
-    private void moveTo(float x, float y) {
+    public void moveTo(float x, float y) {
         mPath.moveTo(mLastX = x, mLastY = y);
     }
 
@@ -658,7 +658,7 @@
      * @param dy The amount to add to the y-coordinate of the end of the
      *           previous contour, to specify the start of a new contour
      */
-    private void rMoveTo(float dx, float dy) {
+    public void rMoveTo(float dx, float dy) {
         dx += mLastX;
         dy += mLastY;
         mPath.moveTo(mLastX = dx, mLastY = dy);
@@ -672,7 +672,7 @@
      * @param x The x-coordinate of the end of a line
      * @param y The y-coordinate of the end of a line
      */
-    private void lineTo(float x, float y) {
+    public void lineTo(float x, float y) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
         }
@@ -689,7 +689,7 @@
      * @param dy The amount to add to the y-coordinate of the previous point on
      *           this contour, to specify a line
      */
-    private void rLineTo(float dx, float dy) {
+    public void rLineTo(float dx, float dy) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
         }
@@ -714,7 +714,7 @@
      * @param x2 The x-coordinate of the end point on a quadratic curve
      * @param y2 The y-coordinate of the end point on a quadratic curve
      */
-    private void quadTo(float x1, float y1, float x2, float y2) {
+    public void quadTo(float x1, float y1, float x2, float y2) {
         mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
     }
 
@@ -732,7 +732,7 @@
      * @param dy2 The amount to add to the y-coordinate of the last point on
      *            this contour, for the end point of a quadratic curve
      */
-    private void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
+    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
         }
@@ -755,7 +755,7 @@
      * @param x3 The x-coordinate of the end point on a cubic curve
      * @param y3 The y-coordinate of the end point on a cubic curve
      */
-    private void cubicTo(float x1, float y1, float x2, float y2,
+    public void cubicTo(float x1, float y1, float x2, float y2,
                         float x3, float y3) {
         if (!hasPoints()) {
             mPath.moveTo(0, 0);
@@ -768,7 +768,7 @@
      * current point on this contour. If there is no previous point, then a
      * moveTo(0,0) is inserted automatically.
      */
-    private void rCubicTo(float dx1, float dy1, float dx2, float dy2,
+    public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
                          float dx3, float dy3) {
         if (!hasPoints()) {
             mPath.moveTo(mLastX = 0, mLastY = 0);
@@ -798,7 +798,7 @@
      *                    mod 360.
      * @param forceMoveTo If true, always begin a new contour with the arc
      */
-    private void arcTo(float left, float top, float right, float bottom, float startAngle,
+    public void arcTo(float left, float top, float right, float bottom, float startAngle,
             float sweepAngle,
             boolean forceMoveTo) {
         Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle,
@@ -812,7 +812,7 @@
      * Close the current contour. If the current point is not equal to the
      * first point of the contour, a line segment is automatically added.
      */
-    private void close() {
+    public void close() {
         mPath.closePath();
     }
 
@@ -831,7 +831,7 @@
      * @param bottom The bottom of a rectangle to add to the path
      * @param dir    The direction to wind the rectangle's contour
      */
-    private void addRect(float left, float top, float right, float bottom,
+    public void addRect(float left, float top, float right, float bottom,
                         int dir) {
         moveTo(left, top);
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
new file mode 100644
index 0000000..eef8235
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -0,0 +1,1122 @@
+/*
+ * 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.graphics.drawable;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas_Delegate;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Join;
+import android.graphics.Paint_Delegate;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.Path_Delegate;
+import android.graphics.Rect;
+import android.graphics.Region.Op;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.PathParser_Delegate;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+
+import static android.graphics.Canvas.CLIP_SAVE_FLAG;
+import static android.graphics.Canvas.MATRIX_SAVE_FLAG;
+import static android.graphics.Paint.Cap.BUTT;
+import static android.graphics.Paint.Cap.ROUND;
+import static android.graphics.Paint.Cap.SQUARE;
+import static android.graphics.Paint.Join.BEVEL;
+import static android.graphics.Paint.Join.MITER;
+import static android.graphics.Paint.Style;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link VectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original  methods of VectorDrawable have been replaced by
+ * calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class VectorDrawable_Delegate {
+    private static final String LOGTAG = VectorDrawable_Delegate.class.getSimpleName();
+    private static final boolean DBG_VECTOR_DRAWABLE = false;
+
+    private static final DelegateManager<VNativeObject> sPathManager =
+            new DelegateManager<>(VNativeObject.class);
+
+    private static <T> T getDelegate(long nativePtr) {
+        //noinspection unchecked
+        T object = (T) sPathManager.getDelegate(nativePtr);
+        assert object != null;
+
+        return object;
+    }
+
+    /**
+     * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
+     * null.
+     */
+    private static TypedArray obtainAttributes(
+            Resources res, Theme theme, AttributeSet set, int[] attrs) {
+        if (theme == null) {
+            return res.obtainAttributes(set, attrs);
+        }
+        return theme.obtainStyledAttributes(set, attrs, 0, 0);
+    }
+
+    private static int applyAlpha(int color, float alpha) {
+        int alphaBytes = Color.alpha(color);
+        color &= 0x00FFFFFF;
+        color |= ((int) (alphaBytes * alpha)) << 24;
+        return color;
+    }
+
+    @LayoutlibDelegate
+    static long nCreateRenderer(long rootGroupPtr) {
+        VGroup_Delegate rootGroup = getDelegate(rootGroupPtr);
+        return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
+    }
+
+    @LayoutlibDelegate
+    static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
+            float viewportHeight) {
+        VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+        nativePathRenderer.mViewportWidth = viewportWidth;
+        nativePathRenderer.mViewportHeight = viewportHeight;
+    }
+
+    @LayoutlibDelegate
+    static boolean nSetRootAlpha(long rendererPtr, float alpha) {
+        VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+        nativePathRenderer.setRootAlpha(alpha);
+
+        return true;
+    }
+
+    @LayoutlibDelegate
+    static float nGetRootAlpha(long rendererPtr) {
+        VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+
+        return nativePathRenderer.getRootAlpha();
+    }
+
+    @LayoutlibDelegate
+    static void nSetAllowCaching(long rendererPtr, boolean allowCaching) {
+        // ignored
+    }
+
+    @LayoutlibDelegate
+    static void nDraw(long rendererPtr, long canvasWrapperPtr,
+            long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) {
+        VPathRenderer_Delegate nativePathRenderer =
+                getDelegate(rendererPtr);
+
+        Canvas_Delegate.native_save(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+        Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.left, bounds.top);
+
+        if (needsMirroring) {
+            Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.width(), 0);
+            Canvas_Delegate.native_scale(canvasWrapperPtr, -1.0f, 1.0f);
+        }
+
+        // At this point, canvas has been translated to the right position.
+        // And we use this bound for the destination rect for the drawBitmap, so
+        // we offset to (0, 0);
+        bounds.offsetTo(0, 0);
+        nativePathRenderer.draw(canvasWrapperPtr, colorFilterPtr, bounds.width(), bounds.height());
+
+        Canvas_Delegate.native_restore(canvasWrapperPtr, true);
+    }
+
+    @LayoutlibDelegate
+    static long nCreateFullPath() {
+        return sPathManager.addNewDelegate(new VFullPath_Delegate());
+    }
+
+    @LayoutlibDelegate
+    static long nCreateFullPath(long nativeFullPathPtr) {
+        VFullPath_Delegate original = getDelegate(nativeFullPathPtr);
+
+        return sPathManager.addNewDelegate(new VFullPath_Delegate(original));
+    }
+
+    @LayoutlibDelegate
+    static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData,
+            int length) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+
+        ByteBuffer properties = ByteBuffer.wrap(propertiesData);
+        properties.order(ByteOrder.nativeOrder());
+
+        properties.putFloat(VFullPath_Delegate.STROKE_WIDTH_INDEX * 4, path.getStrokeWidth());
+        properties.putInt(VFullPath_Delegate.STROKE_COLOR_INDEX * 4, path.getStrokeColor());
+        properties.putFloat(VFullPath_Delegate.STROKE_ALPHA_INDEX * 4, path.getStrokeAlpha());
+        properties.putInt(VFullPath_Delegate.FILL_COLOR_INDEX * 4, path.getFillColor());
+        properties.putFloat(VFullPath_Delegate.FILL_ALPHA_INDEX * 4, path.getStrokeAlpha());
+        properties.putFloat(VFullPath_Delegate.TRIM_PATH_START_INDEX * 4, path.getTrimPathStart());
+        properties.putFloat(VFullPath_Delegate.TRIM_PATH_END_INDEX * 4, path.getTrimPathEnd());
+        properties.putFloat(VFullPath_Delegate.TRIM_PATH_OFFSET_INDEX * 4,
+                path.getTrimPathOffset());
+        properties.putInt(VFullPath_Delegate.STROKE_LINE_CAP_INDEX * 4, path.getStrokeLineCap());
+        properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin());
+        properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4,
+                path.getStrokeMiterlimit());
+
+        return true;
+    }
+
+    @LayoutlibDelegate
+    static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
+            int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
+            float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
+            int strokeLineJoin) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+
+        path.setStrokeWidth(strokeWidth);
+        path.setStrokeColor(strokeColor);
+        path.setStrokeAlpha(strokeAlpha);
+        path.setFillColor(fillColor);
+        path.setFillAlpha(fillAlpha);
+        path.setTrimPathStart(trimPathStart);
+        path.setTrimPathEnd(trimPathEnd);
+        path.setTrimPathOffset(trimPathOffset);
+        path.setStrokeMiterlimit(strokeMiterLimit);
+        path.setStrokeLineCap(strokeLineCap);
+        path.setStrokeLineJoin(strokeLineJoin);
+    }
+
+    @LayoutlibDelegate
+    static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) {
+
+    }
+
+    @LayoutlibDelegate
+    static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) {
+
+    }
+
+    @LayoutlibDelegate
+    static long nCreateClipPath() {
+        return sPathManager.addNewDelegate(new VClipPath_Delegate());
+    }
+
+    @LayoutlibDelegate
+    static long nCreateClipPath(long clipPathPtr) {
+        VClipPath_Delegate original = getDelegate(clipPathPtr);
+        return sPathManager.addNewDelegate(new VClipPath_Delegate(original));
+    }
+
+    @LayoutlibDelegate
+    static long nCreateGroup() {
+        return sPathManager.addNewDelegate(new VGroup_Delegate());
+    }
+
+    @LayoutlibDelegate
+    static long nCreateGroup(long groupPtr) {
+        VGroup_Delegate original = getDelegate(groupPtr);
+        return sPathManager.addNewDelegate(
+                new VGroup_Delegate(original, new ArrayMap<String, Object>()));
+    }
+
+    @LayoutlibDelegate
+    static void nSetName(long nodePtr, String name) {
+        VNativeObject group = getDelegate(nodePtr);
+        group.setName(name);
+    }
+
+    @LayoutlibDelegate
+    static boolean nGetGroupProperties(long groupPtr, float[] propertiesData,
+            int length) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+
+        FloatBuffer properties = FloatBuffer.wrap(propertiesData);
+
+        properties.put(VGroup_Delegate.ROTATE_INDEX, group.getRotation());
+        properties.put(VGroup_Delegate.PIVOT_X_INDEX, group.getPivotX());
+        properties.put(VGroup_Delegate.PIVOT_Y_INDEX, group.getPivotY());
+        properties.put(VGroup_Delegate.SCALE_X_INDEX, group.getScaleX());
+        properties.put(VGroup_Delegate.SCALE_Y_INDEX, group.getScaleY());
+        properties.put(VGroup_Delegate.TRANSLATE_X_INDEX, group.getTranslateX());
+        properties.put(VGroup_Delegate.TRANSLATE_Y_INDEX, group.getTranslateY());
+
+        return true;
+    }
+    @LayoutlibDelegate
+    static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
+            float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+
+        group.setRotation(rotate);
+        group.setPivotX(pivotX);
+        group.setPivotY(pivotY);
+        group.setScaleX(scaleX);
+        group.setScaleY(scaleY);
+        group.setTranslateX(translateX);
+        group.setTranslateY(translateY);
+    }
+
+    @LayoutlibDelegate
+    static void nAddChild(long groupPtr, long nodePtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.mChildren.add(getDelegate(nodePtr));
+    }
+
+    @LayoutlibDelegate
+    static void nSetPathString(long pathPtr, String pathString, int length) {
+        VPath_Delegate path = getDelegate(pathPtr);
+        path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString));
+    }
+
+    /**
+     * The setters and getters below for paths and groups are here temporarily, and will be removed
+     * once the animation in AVD is replaced with RenderNodeAnimator, in which case the animation
+     * will modify these properties in native. By then no JNI hopping would be necessary for VD
+     * during animation, and these setters and getters will be obsolete.
+     */
+    // Setters and getters during animation.
+    @LayoutlibDelegate
+    static float nGetRotation(long groupPtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        return group.getRotation();
+    }
+
+    @LayoutlibDelegate
+    static void nSetRotation(long groupPtr, float rotation) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.setRotation(rotation);
+    }
+
+    @LayoutlibDelegate
+    static float nGetPivotX(long groupPtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        return group.getPivotX();
+    }
+
+    @LayoutlibDelegate
+    static void nSetPivotX(long groupPtr, float pivotX) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.setPivotX(pivotX);
+    }
+
+    @LayoutlibDelegate
+    static float nGetPivotY(long groupPtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        return group.getPivotY();
+    }
+
+    @LayoutlibDelegate
+    static void nSetPivotY(long groupPtr, float pivotY) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.setPivotY(pivotY);
+    }
+
+    @LayoutlibDelegate
+    static float nGetScaleX(long groupPtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        return group.getScaleX();
+    }
+
+    @LayoutlibDelegate
+    static void nSetScaleX(long groupPtr, float scaleX) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.setScaleX(scaleX);
+    }
+
+    @LayoutlibDelegate
+    static float nGetScaleY(long groupPtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        return group.getScaleY();
+    }
+
+    @LayoutlibDelegate
+    static void nSetScaleY(long groupPtr, float scaleY) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.setScaleY(scaleY);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTranslateX(long groupPtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        return group.getTranslateX();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTranslateX(long groupPtr, float translateX) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.setTranslateX(translateX);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTranslateY(long groupPtr) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        return group.getTranslateY();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTranslateY(long groupPtr, float translateY) {
+        VGroup_Delegate group = getDelegate(groupPtr);
+        group.setTranslateY(translateY);
+    }
+
+    @LayoutlibDelegate
+    static void nSetPathData(long pathPtr, long pathDataPtr) {
+        VPath_Delegate path = getDelegate(pathPtr);
+        path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes());
+    }
+
+    @LayoutlibDelegate
+    static float nGetStrokeWidth(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getStrokeWidth();
+    }
+
+    @LayoutlibDelegate
+    static void nSetStrokeWidth(long pathPtr, float width) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setStrokeWidth(width);
+    }
+
+    @LayoutlibDelegate
+    static int nGetStrokeColor(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getStrokeColor();
+    }
+
+    @LayoutlibDelegate
+    static void nSetStrokeColor(long pathPtr, int strokeColor) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setStrokeColor(strokeColor);
+    }
+
+    @LayoutlibDelegate
+    static float nGetStrokeAlpha(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getStrokeAlpha();
+    }
+
+    @LayoutlibDelegate
+    static void nSetStrokeAlpha(long pathPtr, float alpha) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setStrokeAlpha(alpha);
+    }
+
+    @LayoutlibDelegate
+    static int nGetFillColor(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getFillColor();
+    }
+
+    @LayoutlibDelegate
+    static void nSetFillColor(long pathPtr, int fillColor) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setFillColor(fillColor);
+    }
+
+    @LayoutlibDelegate
+    static float nGetFillAlpha(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getFillAlpha();
+    }
+
+    @LayoutlibDelegate
+    static void nSetFillAlpha(long pathPtr, float fillAlpha) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setFillAlpha(fillAlpha);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTrimPathStart(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getTrimPathStart();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTrimPathStart(long pathPtr, float trimPathStart) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setTrimPathStart(trimPathStart);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTrimPathEnd(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getTrimPathEnd();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setTrimPathEnd(trimPathEnd);
+    }
+
+    @LayoutlibDelegate
+    static float nGetTrimPathOffset(long pathPtr) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        return path.getTrimPathOffset();
+    }
+
+    @LayoutlibDelegate
+    static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) {
+        VFullPath_Delegate path = getDelegate(pathPtr);
+        path.setTrimPathOffset(trimPathOffset);
+    }
+
+    /**
+     * Base class for all the internal Delegates that does two functions:
+     * <ol>
+     *     <li>Serves as base class to store all the delegates in one {@link DelegateManager}
+     *     <li>Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually
+     *     not need it
+     * </ol>
+     */
+    private interface VNativeObject {
+        void setName(String name);
+    }
+
+    private static class VClipPath_Delegate extends VPath_Delegate {
+        private VClipPath_Delegate() {
+            // Empty constructor.
+        }
+
+        private VClipPath_Delegate(VClipPath_Delegate copy) {
+            super(copy);
+        }
+
+        @Override
+        public boolean isClipPath() {
+            return true;
+        }
+    }
+
+    private static class VFullPath_Delegate extends VPath_Delegate {
+        // These constants need to be kept in sync with their values in VectorDrawable.VFullPath
+        private static final int STROKE_WIDTH_INDEX = 0;
+        private static final int STROKE_COLOR_INDEX = 1;
+        private static final int STROKE_ALPHA_INDEX = 2;
+        private static final int FILL_COLOR_INDEX = 3;
+        private static final int FILL_ALPHA_INDEX = 4;
+        private static final int TRIM_PATH_START_INDEX = 5;
+        private static final int TRIM_PATH_END_INDEX = 6;
+        private static final int TRIM_PATH_OFFSET_INDEX = 7;
+        private static final int STROKE_LINE_CAP_INDEX = 8;
+        private static final int STROKE_LINE_JOIN_INDEX = 9;
+        private static final int STROKE_MITER_LIMIT_INDEX = 10;
+
+        private static final int LINECAP_BUTT = 0;
+        private static final int LINECAP_ROUND = 1;
+        private static final int LINECAP_SQUARE = 2;
+
+        private static final int LINEJOIN_MITER = 0;
+        private static final int LINEJOIN_ROUND = 1;
+        private static final int LINEJOIN_BEVEL = 2;
+
+        /////////////////////////////////////////////////////
+        // Variables below need to be copied (deep copy if applicable) for mutation.
+
+        int mStrokeColor = Color.TRANSPARENT;
+        float mStrokeWidth = 0;
+
+        int mFillColor = Color.TRANSPARENT;
+        float mStrokeAlpha = 1.0f;
+        float mFillAlpha = 1.0f;
+        float mTrimPathStart = 0;
+        float mTrimPathEnd = 1;
+        float mTrimPathOffset = 0;
+
+        Cap mStrokeLineCap = BUTT;
+        Join mStrokeLineJoin = MITER;
+        float mStrokeMiterlimit = 4;
+
+        private VFullPath_Delegate() {
+            // Empty constructor.
+        }
+
+        private VFullPath_Delegate(VFullPath_Delegate copy) {
+            super(copy);
+
+            mStrokeColor = copy.mStrokeColor;
+            mStrokeWidth = copy.mStrokeWidth;
+            mStrokeAlpha = copy.mStrokeAlpha;
+            mFillColor = copy.mFillColor;
+            mFillAlpha = copy.mFillAlpha;
+            mTrimPathStart = copy.mTrimPathStart;
+            mTrimPathEnd = copy.mTrimPathEnd;
+            mTrimPathOffset = copy.mTrimPathOffset;
+
+            mStrokeLineCap = copy.mStrokeLineCap;
+            mStrokeLineJoin = copy.mStrokeLineJoin;
+            mStrokeMiterlimit = copy.mStrokeMiterlimit;
+        }
+
+        private int getStrokeLineCap() {
+            switch (mStrokeLineCap) {
+                case BUTT:
+                    return LINECAP_BUTT;
+                case ROUND:
+                    return LINECAP_ROUND;
+                case SQUARE:
+                    return LINECAP_SQUARE;
+                default:
+                    assert false;
+            }
+
+            return -1;
+        }
+
+        private void setStrokeLineCap(int cap) {
+            switch (cap) {
+                case LINECAP_BUTT:
+                    mStrokeLineCap = BUTT;
+                    break;
+                case LINECAP_ROUND:
+                    mStrokeLineCap = ROUND;
+                    break;
+                case LINECAP_SQUARE:
+                    mStrokeLineCap = SQUARE;
+                    break;
+                default:
+                    assert false;
+            }
+        }
+
+        private int getStrokeLineJoin() {
+            switch (mStrokeLineJoin) {
+                case MITER:
+                    return LINEJOIN_MITER;
+                case ROUND:
+                    return LINEJOIN_ROUND;
+                case BEVEL:
+                    return LINEJOIN_BEVEL;
+                default:
+                    assert false;
+            }
+
+            return -1;
+        }
+
+        private void setStrokeLineJoin(int join) {
+            switch (join) {
+                case LINEJOIN_BEVEL:
+                    mStrokeLineJoin = BEVEL;
+                    break;
+                case LINEJOIN_MITER:
+                    mStrokeLineJoin = MITER;
+                    break;
+                case LINEJOIN_ROUND:
+                    mStrokeLineJoin = Join.ROUND;
+                    break;
+                default:
+                    assert false;
+            }
+        }
+
+        private int getStrokeColor() {
+            return mStrokeColor;
+        }
+
+                private void setStrokeColor(int strokeColor) {
+            mStrokeColor = strokeColor;
+        }
+
+        private float getStrokeWidth() {
+            return mStrokeWidth;
+        }
+
+        private void setStrokeWidth(float strokeWidth) {
+            mStrokeWidth = strokeWidth;
+        }
+
+        private float getStrokeAlpha() {
+            return mStrokeAlpha;
+        }
+
+        private void setStrokeAlpha(float strokeAlpha) {
+            mStrokeAlpha = strokeAlpha;
+        }
+
+        private int getFillColor() {
+            return mFillColor;
+        }
+
+        private void setFillColor(int fillColor) {
+            mFillColor = fillColor;
+        }
+
+        private float getFillAlpha() {
+            return mFillAlpha;
+        }
+
+        private void setFillAlpha(float fillAlpha) {
+            mFillAlpha = fillAlpha;
+        }
+
+        private float getTrimPathStart() {
+            return mTrimPathStart;
+        }
+
+        private void setTrimPathStart(float trimPathStart) {
+            mTrimPathStart = trimPathStart;
+        }
+
+        private float getTrimPathEnd() {
+            return mTrimPathEnd;
+        }
+
+        private void setTrimPathEnd(float trimPathEnd) {
+            mTrimPathEnd = trimPathEnd;
+        }
+
+        private float getTrimPathOffset() {
+            return mTrimPathOffset;
+        }
+
+        private void setTrimPathOffset(float trimPathOffset) {
+            mTrimPathOffset = trimPathOffset;
+        }
+
+        private void setStrokeMiterlimit(float limit) {
+            mStrokeMiterlimit = limit;
+        }
+
+        private float getStrokeMiterlimit() {
+            return mStrokeMiterlimit;
+        }
+    }
+
+    private static class VGroup_Delegate implements VNativeObject {
+        // This constants need to be kept in sync with their definitions in VectorDrawable.Group
+        private static final int ROTATE_INDEX = 0;
+        private static final int PIVOT_X_INDEX = 1;
+        private static final int PIVOT_Y_INDEX = 2;
+        private static final int SCALE_X_INDEX = 3;
+        private static final int SCALE_Y_INDEX = 4;
+        private static final int TRANSLATE_X_INDEX = 5;
+        private static final int TRANSLATE_Y_INDEX = 6;
+
+        /////////////////////////////////////////////////////
+        // Variables below need to be copied (deep copy if applicable) for mutation.
+        final ArrayList<Object> mChildren = new ArrayList<>();
+        // mStackedMatrix is only used temporarily when drawing, it combines all
+        // the parents' local matrices with the current one.
+        private final Matrix mStackedMatrix = new Matrix();
+        // mLocalMatrix is updated based on the update of transformation information,
+        // either parsed from the XML or by animation.
+        private final Matrix mLocalMatrix = new Matrix();
+        private float mRotate = 0;
+        private float mPivotX = 0;
+        private float mPivotY = 0;
+        private float mScaleX = 1;
+        private float mScaleY = 1;
+        private float mTranslateX = 0;
+        private float mTranslateY = 0;
+        private int mChangingConfigurations;
+        private String mGroupName = null;
+
+        private VGroup_Delegate(VGroup_Delegate copy, ArrayMap<String, Object> targetsMap) {
+            mRotate = copy.mRotate;
+            mPivotX = copy.mPivotX;
+            mPivotY = copy.mPivotY;
+            mScaleX = copy.mScaleX;
+            mScaleY = copy.mScaleY;
+            mTranslateX = copy.mTranslateX;
+            mTranslateY = copy.mTranslateY;
+            mGroupName = copy.mGroupName;
+            mChangingConfigurations = copy.mChangingConfigurations;
+            if (mGroupName != null) {
+                targetsMap.put(mGroupName, this);
+            }
+
+            mLocalMatrix.set(copy.mLocalMatrix);
+
+            final ArrayList<Object> children = copy.mChildren;
+            //noinspection ForLoopReplaceableByForEach
+            for (int i = 0; i < children.size(); i++) {
+                Object copyChild = children.get(i);
+                if (copyChild instanceof VGroup_Delegate) {
+                    VGroup_Delegate copyGroup = (VGroup_Delegate) copyChild;
+                    mChildren.add(new VGroup_Delegate(copyGroup, targetsMap));
+                } else {
+                    VPath_Delegate newPath;
+                    if (copyChild instanceof VFullPath_Delegate) {
+                        newPath = new VFullPath_Delegate((VFullPath_Delegate) copyChild);
+                    } else if (copyChild instanceof VClipPath_Delegate) {
+                        newPath = new VClipPath_Delegate((VClipPath_Delegate) copyChild);
+                    } else {
+                        throw new IllegalStateException("Unknown object in the tree!");
+                    }
+                    mChildren.add(newPath);
+                    if (newPath.mPathName != null) {
+                        targetsMap.put(newPath.mPathName, newPath);
+                    }
+                }
+            }
+        }
+
+        private VGroup_Delegate() {
+        }
+
+        private void updateLocalMatrix() {
+            // The order we apply is the same as the
+            // RenderNode.cpp::applyViewPropertyTransforms().
+            mLocalMatrix.reset();
+            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+            mLocalMatrix.postScale(mScaleX, mScaleY);
+            mLocalMatrix.postRotate(mRotate, 0, 0);
+            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+        }
+
+        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+        private float getRotation() {
+            return mRotate;
+        }
+
+        private void setRotation(float rotation) {
+            if (rotation != mRotate) {
+                mRotate = rotation;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getPivotX() {
+            return mPivotX;
+        }
+
+        private void setPivotX(float pivotX) {
+            if (pivotX != mPivotX) {
+                mPivotX = pivotX;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getPivotY() {
+            return mPivotY;
+        }
+
+        private void setPivotY(float pivotY) {
+            if (pivotY != mPivotY) {
+                mPivotY = pivotY;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getScaleX() {
+            return mScaleX;
+        }
+
+        private void setScaleX(float scaleX) {
+            if (scaleX != mScaleX) {
+                mScaleX = scaleX;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getScaleY() {
+            return mScaleY;
+        }
+
+        private void setScaleY(float scaleY) {
+            if (scaleY != mScaleY) {
+                mScaleY = scaleY;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getTranslateX() {
+            return mTranslateX;
+        }
+
+        private void setTranslateX(float translateX) {
+            if (translateX != mTranslateX) {
+                mTranslateX = translateX;
+                updateLocalMatrix();
+            }
+        }
+
+        private float getTranslateY() {
+            return mTranslateY;
+        }
+
+        private void setTranslateY(float translateY) {
+            if (translateY != mTranslateY) {
+                mTranslateY = translateY;
+                updateLocalMatrix();
+            }
+        }
+
+        @Override
+        public void setName(String name) {
+            mGroupName = name;
+        }
+    }
+
+    public static class VPath_Delegate implements VNativeObject {
+        protected PathParser_Delegate.PathDataNode[] mNodes = null;
+        String mPathName;
+        int mChangingConfigurations;
+
+        public VPath_Delegate() {
+            // Empty constructor.
+        }
+
+        public VPath_Delegate(VPath_Delegate copy) {
+            mPathName = copy.mPathName;
+            mChangingConfigurations = copy.mChangingConfigurations;
+            mNodes = PathParser_Delegate.deepCopyNodes(copy.mNodes);
+        }
+
+        public void toPath(Path path) {
+            path.reset();
+            if (mNodes != null) {
+                PathParser_Delegate.PathDataNode.nodesToPath(mNodes,
+                        Path_Delegate.getDelegate(path.mNativePath));
+            }
+        }
+
+        @Override
+        public void setName(String name) {
+            mPathName = name;
+        }
+
+        public boolean isClipPath() {
+            return false;
+        }
+
+        private void setPathData(PathParser_Delegate.PathDataNode[] nodes) {
+            if (!PathParser_Delegate.canMorph(mNodes, nodes)) {
+                // This should not happen in the middle of animation.
+                mNodes = PathParser_Delegate.deepCopyNodes(nodes);
+            } else {
+                PathParser_Delegate.updateNodes(mNodes, nodes);
+            }
+        }
+    }
+
+    private static class VPathRenderer_Delegate implements VNativeObject {
+        /* Right now the internal data structure is organized as a tree.
+         * Each node can be a group node, or a path.
+         * A group node can have groups or paths as children, but a path node has
+         * no children.
+         * One example can be:
+         *                 Root Group
+         *                /    |     \
+         *           Group    Path    Group
+         *          /     \             |
+         *         Path   Path         Path
+         *
+         */
+        // Variables that only used temporarily inside the draw() call, so there
+        // is no need for deep copying.
+        private final Path mPath;
+        private final Path mRenderPath;
+        private final Matrix mFinalPathMatrix = new Matrix();
+        private final VGroup_Delegate mRootGroup;
+        private float mViewportWidth = 0;
+        private float mViewportHeight = 0;
+        private float mRootAlpha = 1.0f;
+        private Paint mStrokePaint;
+        private Paint mFillPaint;
+        private PathMeasure mPathMeasure;
+
+        private VPathRenderer_Delegate(VGroup_Delegate rootGroup) {
+            mRootGroup = rootGroup;
+            mPath = new Path();
+            mRenderPath = new Path();
+        }
+
+        private float getRootAlpha() {
+            return mRootAlpha;
+        }
+
+        private void setRootAlpha(float alpha) {
+            mRootAlpha = alpha;
+        }
+
+        private void drawGroupTree(VGroup_Delegate currentGroup, Matrix currentMatrix,
+                long canvasPtr, int w, int h, long filterPtr) {
+            // Calculate current group's matrix by preConcat the parent's and
+            // and the current one on the top of the stack.
+            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+            // Mi the local matrix at level i of the group tree.
+            currentGroup.mStackedMatrix.set(currentMatrix);
+            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+            // Save the current clip information, which is local to this group.
+            Canvas_Delegate.native_save(canvasPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+            // Draw the group tree in the same order as the XML file.
+            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+                Object child = currentGroup.mChildren.get(i);
+                if (child instanceof VGroup_Delegate) {
+                    VGroup_Delegate childGroup = (VGroup_Delegate) child;
+                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
+                            canvasPtr, w, h, filterPtr);
+                } else if (child instanceof VPath_Delegate) {
+                    VPath_Delegate childPath = (VPath_Delegate) child;
+                    drawPath(currentGroup, childPath, canvasPtr, w, h, filterPtr);
+                }
+            }
+            Canvas_Delegate.native_restore(canvasPtr, true);
+        }
+
+        public void draw(long canvasPtr, long filterPtr, int w, int h) {
+            // Traverse the tree in pre-order to draw.
+            drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
+        }
+
+        private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr,
+                int w,
+                int h,
+                long filterPtr) {
+            final float scaleX = w / mViewportWidth;
+            final float scaleY = h / mViewportHeight;
+            final float minScale = Math.min(scaleX, scaleY);
+            final Matrix groupStackedMatrix = VGroup.mStackedMatrix;
+
+            mFinalPathMatrix.set(groupStackedMatrix);
+            mFinalPathMatrix.postScale(scaleX, scaleY);
+
+            final float matrixScale = getMatrixScale(groupStackedMatrix);
+            if (matrixScale == 0) {
+                // When either x or y is scaled to 0, we don't need to draw anything.
+                return;
+            }
+            VPath.toPath(mPath);
+            final Path path = mPath;
+
+            mRenderPath.reset();
+
+            if (VPath.isClipPath()) {
+                mRenderPath.addPath(path, mFinalPathMatrix);
+                Canvas_Delegate.native_clipPath(canvasPtr, mRenderPath.mNativePath, Op
+                        .INTERSECT.nativeInt);
+            } else {
+                VFullPath_Delegate fullPath = (VFullPath_Delegate) VPath;
+                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
+                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
+                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
+
+                    if (mPathMeasure == null) {
+                        mPathMeasure = new PathMeasure();
+                    }
+                    mPathMeasure.setPath(mPath, false);
+
+                    float len = mPathMeasure.getLength();
+                    start = start * len;
+                    end = end * len;
+                    path.reset();
+                    if (start > end) {
+                        mPathMeasure.getSegment(start, len, path, true);
+                        mPathMeasure.getSegment(0f, end, path, true);
+                    } else {
+                        mPathMeasure.getSegment(start, end, path, true);
+                    }
+                    path.rLineTo(0, 0); // fix bug in measure
+                }
+                mRenderPath.addPath(path, mFinalPathMatrix);
+
+                if (fullPath.mFillColor != Color.TRANSPARENT) {
+                    if (mFillPaint == null) {
+                        mFillPaint = new Paint();
+                        mFillPaint.setStyle(Style.FILL);
+                        mFillPaint.setAntiAlias(true);
+                    }
+
+                    final Paint fillPaint = mFillPaint;
+                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+                    Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint
+                            .getNativeInstance
+                            ());
+                    // mFillPaint can not be null at this point so we will have a delegate
+                    assert fillPaintDelegate != null;
+                    fillPaintDelegate.setColorFilter(filterPtr);
+                    Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
+                            .getNativeInstance());
+                }
+
+                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
+                    if (mStrokePaint == null) {
+                        mStrokePaint = new Paint();
+                        mStrokePaint.setStyle(Style.STROKE);
+                        mStrokePaint.setAntiAlias(true);
+                    }
+
+                    final Paint strokePaint = mStrokePaint;
+                    if (fullPath.mStrokeLineJoin != null) {
+                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
+                    }
+
+                    if (fullPath.mStrokeLineCap != null) {
+                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
+                    }
+
+                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
+                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+                    Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint
+                            .getNativeInstance());
+                    // mStrokePaint can not be null at this point so we will have a delegate
+                    assert strokePaintDelegate != null;
+                    strokePaintDelegate.setColorFilter(filterPtr);
+                    final float finalStrokeScale = minScale * matrixScale;
+                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
+                    Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
+                            .getNativeInstance());
+                }
+            }
+        }
+
+        private float getMatrixScale(Matrix groupStackedMatrix) {
+            // Given unit vectors A = (0, 1) and B = (1, 0).
+            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
+            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
+            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
+            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
+            //
+            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
+            // scale on x and y axis, and take the minimal of these two.
+            // For skew case, an unit square will mapped to a parallelogram. And this function will
+            // return the minimal height of the 2 bases.
+            float[] unitVectors = new float[]{0, 1, 1, 0};
+            groupStackedMatrix.mapVectors(unitVectors);
+            float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
+            float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
+            float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
+                    unitVectors[2], unitVectors[3]);
+            float maxScale = MathUtils.max(scaleX, scaleY);
+
+            float matrixScale = 0;
+            if (maxScale > 0) {
+                matrixScale = MathUtils.abs(crossProduct) / maxScale;
+            }
+            if (DBG_VECTOR_DRAWABLE) {
+                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
+            }
+            return matrixScale;
+        }
+
+        @Override
+        public void setName(String name) {
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
index d3af837..6c34c70 100644
--- a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
@@ -24,7 +24,6 @@
 import android.annotation.NonNull;
 import android.graphics.Path_Delegate;
 
-import java.awt.geom.Path2D;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.logging.Level;
@@ -52,10 +51,18 @@
     @NonNull
     private PathDataNode[] mPathDataNodes;
 
+    public static PathParser_Delegate getDelegate(long nativePtr) {
+        return sManager.getDelegate(nativePtr);
+    }
+
     private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
         mPathDataNodes = nodes;
     }
 
+    public PathDataNode[] getPathDataNodes() {
+        return mPathDataNodes;
+    }
+
     @LayoutlibDelegate
     /*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
             stringLength) {
@@ -64,7 +71,7 @@
             return false;
         }
         assert pathString.length() == stringLength;
-        PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate.getJavaShape());
+        PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate);
         return true;
     }
 
@@ -75,7 +82,7 @@
         if (source == null || path_delegate == null) {
             return;
         }
-        PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate.getJavaShape());
+        PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate);
     }
 
     @LayoutlibDelegate
@@ -124,8 +131,11 @@
             out.mPathDataNodes = new PathDataNode[length];
         }
         for (int i = 0; i < length; i++) {
+            if (out.mPathDataNodes[i] == null) {
+                out.mPathDataNodes[i] = new PathDataNode(from.mPathDataNodes[i]);
+            }
             out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
-                    to.mPathDataNodes[i], fraction);
+                        to.mPathDataNodes[i], fraction);
         }
         return true;
     }
@@ -137,9 +147,13 @@
 
     @LayoutlibDelegate
     /*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "morphing path data isn't " +
-                "supported", null, null);
-        return false;
+        PathParser_Delegate fromPath = PathParser_Delegate.getDelegate(fromDataPtr);
+        PathParser_Delegate toPath = PathParser_Delegate.getDelegate(toDataPtr);
+        if (fromPath == null || toPath == null || fromPath.getPathDataNodes() == null || toPath
+                .getPathDataNodes() == null) {
+            return true;
+        }
+        return PathParser_Delegate.canMorph(fromPath.getPathDataNodes(), toPath.getPathDataNodes());
     }
 
     @LayoutlibDelegate
@@ -158,7 +172,7 @@
      * @return an array of the PathDataNode.
      */
     @NonNull
-    private static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
+    public static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
         int start = 0;
         int end = 1;
 
@@ -186,7 +200,7 @@
      * @return a deep copy of the <code>source</code>.
      */
     @NonNull
-    private static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
+    public static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
         PathDataNode[] copy = new PathDataNode[source.length];
         for (int i = 0; i < source.length; i++) {
             copy[i] = new PathDataNode(source[i]);
@@ -194,6 +208,45 @@
         return copy;
     }
 
+    /**
+     * @param nodesFrom The source path represented in an array of PathDataNode
+     * @param nodesTo The target path represented in an array of PathDataNode
+     * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
+     */
+    public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
+        if (nodesFrom == null || nodesTo == null) {
+            return false;
+        }
+
+        if (nodesFrom.length != nodesTo.length) {
+            return false;
+        }
+
+        for (int i = 0; i < nodesFrom.length; i ++) {
+            if (nodesFrom[i].mType != nodesTo[i].mType
+                    || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Update the target's data to match the source.
+     * Before calling this, make sure canMorph(target, source) is true.
+     *
+     * @param target The target path represented in an array of PathDataNode
+     * @param source The source path represented in an array of PathDataNode
+     */
+    public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
+        for (int i = 0; i < source.length; i ++) {
+            target[i].mType = source[i].mType;
+            for (int j = 0; j < source[i].mParams.length; j ++) {
+                target[i].mParams[j] = source[i].mParams[j];
+            }
+        }
+    }
+
     private static int nextStart(@NonNull String s, int end) {
         char c;
 
@@ -330,7 +383,7 @@
      * Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
      * PathDataNode can represent the whole "d" attribute.
      */
-    private static class PathDataNode {
+    public static class PathDataNode {
         private char mType;
         @NonNull
         private float[] mParams;
@@ -355,12 +408,13 @@
         }
 
         /**
-         * Convert an array of PathDataNode to Path.
+         * Convert an array of PathDataNode to Path. Reset the passed path as needed before
+         * calling this method.
          *
          * @param node The source array of PathDataNode.
          * @param path The target Path object.
          */
-        private static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path2D path) {
+        public static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path_Delegate path) {
             float[] current = new float[6];
             char previousCommand = 'm';
             //noinspection ForLoopReplaceableByForEach
@@ -387,24 +441,32 @@
         }
 
         @SuppressWarnings("PointlessArithmeticExpression")
-        private static void addCommand(@NonNull Path2D path, float[] current, char cmd,
-                char lastCmd, @NonNull float[] val) {
+        private static void addCommand(@NonNull Path_Delegate path, float[] current,
+                char previousCmd, char cmd, @NonNull float[] val) {
 
             int incr = 2;
-
-            float cx = current[0];
-            float cy = current[1];
-            float cpx = current[2];
-            float cpy = current[3];
-            float loopX = current[4];
-            float loopY = current[5];
+            float currentX = current[0];
+            float currentY = current[1];
+            float ctrlPointX = current[2];
+            float ctrlPointY = current[3];
+            float currentSegmentStartX = current[4];
+            float currentSegmentStartY = current[5];
+            float reflectiveCtrlPointX;
+            float reflectiveCtrlPointY;
 
             switch (cmd) {
                 case 'z':
                 case 'Z':
-                    path.closePath();
-                    cx = loopX;
-                    cy = loopY;
+                    path.close();
+                    // Path is closed here, but we need to move the pen to the
+                    // closed position. So we cache the segment's starting position,
+                    // and restore it here.
+                    currentX = currentSegmentStartX;
+                    currentY = currentSegmentStartY;
+                    ctrlPointX = currentSegmentStartX;
+                    ctrlPointY = currentSegmentStartY;
+                    path.moveTo(currentX, currentY);
+                    break;
                 case 'm':
                 case 'M':
                 case 'l':
@@ -432,185 +494,206 @@
                 case 'a':
                 case 'A':
                     incr = 7;
+                    break;
             }
 
             for (int k = 0; k < val.length; k += incr) {
-                boolean reflectCtrl;
-                float tempReflectedX, tempReflectedY;
-
                 switch (cmd) {
-                    case 'm':
-                        cx += val[k + 0];
-                        cy += val[k + 1];
+                    case 'm': // moveto - Start a new sub-path (relative)
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
+
                         if (k > 0) {
                             // According to the spec, if a moveto is followed by multiple
                             // pairs of coordinates, the subsequent pairs are treated as
                             // implicit lineto commands.
-                            path.lineTo(cx, cy);
+                            path.rLineTo(val[k + 0], val[k + 1]);
                         } else {
-                            path.moveTo(cx, cy);
-                            loopX = cx;
-                            loopY = cy;
+                            path.rMoveTo(val[k + 0], val[k + 1]);
+                            currentSegmentStartX = currentX;
+                            currentSegmentStartY = currentY;
                         }
                         break;
-                    case 'M':
-                        cx = val[k + 0];
-                        cy = val[k + 1];
+                    case 'M': // moveto - Start a new sub-path
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
+
                         if (k > 0) {
                             // According to the spec, if a moveto is followed by multiple
                             // pairs of coordinates, the subsequent pairs are treated as
                             // implicit lineto commands.
-                            path.lineTo(cx, cy);
+                            path.lineTo(val[k + 0], val[k + 1]);
                         } else {
-                            path.moveTo(cx, cy);
-                            loopX = cx;
-                            loopY = cy;
+                            path.moveTo(val[k + 0], val[k + 1]);
+                            currentSegmentStartX = currentX;
+                            currentSegmentStartY = currentY;
                         }
                         break;
-                    case 'l':
-                        cx += val[k + 0];
-                        cy += val[k + 1];
-                        path.lineTo(cx, cy);
+                    case 'l': // lineto - Draw a line from the current point (relative)
+                        path.rLineTo(val[k + 0], val[k + 1]);
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
                         break;
-                    case 'L':
-                        cx = val[k + 0];
-                        cy = val[k + 1];
-                        path.lineTo(cx, cy);
+                    case 'L': // lineto - Draw a line from the current point
+                        path.lineTo(val[k + 0], val[k + 1]);
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
                         break;
-                    case 'z':
-                    case 'Z':
-                        path.closePath();
-                        cx = loopX;
-                        cy = loopY;
+                    case 'h': // horizontal lineto - Draws a horizontal line (relative)
+                        path.rLineTo(val[k + 0], 0);
+                        currentX += val[k + 0];
                         break;
-                    case 'h':
-                        cx += val[k + 0];
-                        path.lineTo(cx, cy);
+                    case 'H': // horizontal lineto - Draws a horizontal line
+                        path.lineTo(val[k + 0], currentY);
+                        currentX = val[k + 0];
                         break;
-                    case 'H':
-                        path.lineTo(val[k + 0], cy);
-                        cx = val[k + 0];
+                    case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+                        path.rLineTo(0, val[k + 0]);
+                        currentY += val[k + 0];
                         break;
-                    case 'v':
-                        cy += val[k + 0];
-                        path.lineTo(cx, cy);
+                    case 'V': // vertical lineto - Draws a vertical line from the current point
+                        path.lineTo(currentX, val[k + 0]);
+                        currentY = val[k + 0];
                         break;
-                    case 'V':
-                        path.lineTo(cx, val[k + 0]);
-                        cy = val[k + 0];
-                        break;
-                    case 'c':
-                        path.curveTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
-                                cy + val[k + 3], cx + val[k + 4], cy + val[k + 5]);
-                        cpx = cx + val[k + 2];
-                        cpy = cy + val[k + 3];
-                        cx += val[k + 4];
-                        cy += val[k + 5];
-                        break;
-                    case 'C':
-                        path.curveTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                    case 'c': // curveto - Draws a cubic Bézier curve (relative)
+                        path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
                                 val[k + 4], val[k + 5]);
-                        cx = val[k + 4];
-                        cy = val[k + 5];
-                        cpx = val[k + 2];
-                        cpy = val[k + 3];
-                        break;
-                    case 's':
-                        reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
-                                lastCmd == 'S');
-                        path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
-                                * cy - cpy : cy, cx + val[k + 0], cy + val[k + 1], cx
-                                + val[k + 2], cy + val[k + 3]);
 
-                        cpx = cx + val[k + 0];
-                        cpy = cy + val[k + 1];
-                        cx += val[k + 2];
-                        cy += val[k + 3];
+                        ctrlPointX = currentX + val[k + 2];
+                        ctrlPointY = currentY + val[k + 3];
+                        currentX += val[k + 4];
+                        currentY += val[k + 5];
+
                         break;
-                    case 'S':
-                        reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
-                                lastCmd == 'S');
-                        path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
-                                        * cy - cpy : cy, val[k + 0], val[k + 1], val[k + 2],
-                                val[k + 3]);
-                        cpx = (val[k + 0]);
-                        cpy = (val[k + 1]);
-                        cx = val[k + 2];
-                        cy = val[k + 3];
+                    case 'C': // curveto - Draws a cubic Bézier curve
+                        path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                                val[k + 4], val[k + 5]);
+                        currentX = val[k + 4];
+                        currentY = val[k + 5];
+                        ctrlPointX = val[k + 2];
+                        ctrlPointY = val[k + 3];
                         break;
-                    case 'q':
-                        path.quadTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
-                                cy + val[k + 3]);
-                        cpx = cx + val[k + 0];
-                        cpy = cy + val[k + 1];
-                        // Note that we have to update cpx first, since cx will be updated here.
-                        cx += val[k + 2];
-                        cy += val[k + 3];
+                    case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1],
+                                val[k + 2], val[k + 3]);
+
+                        ctrlPointX = currentX + val[k + 0];
+                        ctrlPointY = currentY + val[k + 1];
+                        currentX += val[k + 2];
+                        currentY += val[k + 3];
                         break;
-                    case 'Q':
+                    case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = val[k + 0];
+                        ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
+                        break;
+                    case 'q': // Draws a quadratic Bézier (relative)
+                        path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = currentX + val[k + 0];
+                        ctrlPointY = currentY + val[k + 1];
+                        currentX += val[k + 2];
+                        currentY += val[k + 3];
+                        break;
+                    case 'Q': // Draws a quadratic Bézier
                         path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
-                        cx = val[k + 2];
-                        cy = val[k + 3];
-                        cpx = val[k + 0];
-                        cpy = val[k + 1];
+                        ctrlPointX = val[k + 0];
+                        ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
                         break;
-                    case 't':
-                        reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
-                                lastCmd == 'T');
-                        tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
-                        tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
-                        path.quadTo(tempReflectedX, tempReflectedY, cx + val[k + 0],
-                                cy + val[k + 1]);
-                        cpx = tempReflectedX;
-                        cpy = tempReflectedY;
-                        cx += val[k + 0];
-                        cy += val[k + 1];
+                    case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1]);
+                        ctrlPointX = currentX + reflectiveCtrlPointX;
+                        ctrlPointY = currentY + reflectiveCtrlPointY;
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
                         break;
-                    case 'T':
-                        reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
-                                lastCmd == 'T');
-                        tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
-                        tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
-                        path.quadTo(tempReflectedX, tempReflectedY, val[k + 0], val[k + 1]);
-                        cx = val[k + 0];
-                        cy = val[k + 1];
-                        cpx = tempReflectedX;
-                        cpy = tempReflectedY;
+                    case 'T': // Draws a quadratic Bézier curve (reflective control point)
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1]);
+                        ctrlPointX = reflectiveCtrlPointX;
+                        ctrlPointY = reflectiveCtrlPointY;
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
                         break;
-                    case 'a':
+                    case 'a': // Draws an elliptical arc
                         // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
-                        drawArc(path, cx, cy, val[k + 5] + cx, val[k + 6] + cy,
-                                val[k + 0], val[k + 1], val[k + 2], val[k + 3] != 0,
+                        drawArc(path,
+                                currentX,
+                                currentY,
+                                val[k + 5] + currentX,
+                                val[k + 6] + currentY,
+                                val[k + 0],
+                                val[k + 1],
+                                val[k + 2],
+                                val[k + 3] != 0,
                                 val[k + 4] != 0);
-                        cx += val[k + 5];
-                        cy += val[k + 6];
-                        cpx = cx;
-                        cpy = cy;
-
+                        currentX += val[k + 5];
+                        currentY += val[k + 6];
+                        ctrlPointX = currentX;
+                        ctrlPointY = currentY;
                         break;
-                    case 'A':
-                        drawArc(path, cx, cy, val[k + 5], val[k + 6], val[k + 0],
-                                val[k + 1], val[k + 2], val[k + 3] != 0,
+                    case 'A': // Draws an elliptical arc
+                        drawArc(path,
+                                currentX,
+                                currentY,
+                                val[k + 5],
+                                val[k + 6],
+                                val[k + 0],
+                                val[k + 1],
+                                val[k + 2],
+                                val[k + 3] != 0,
                                 val[k + 4] != 0);
-                        cx = val[k + 5];
-                        cy = val[k + 6];
-                        cpx = cx;
-                        cpy = cy;
+                        currentX = val[k + 5];
+                        currentY = val[k + 6];
+                        ctrlPointX = currentX;
+                        ctrlPointY = currentY;
                         break;
-
                 }
-                lastCmd = cmd;
+                previousCmd = cmd;
             }
-            current[0] = cx;
-            current[1] = cy;
-            current[2] = cpx;
-            current[3] = cpy;
-            current[4] = loopX;
-            current[5] = loopY;
-
+            current[0] = currentX;
+            current[1] = currentY;
+            current[2] = ctrlPointX;
+            current[3] = ctrlPointY;
+            current[4] = currentSegmentStartX;
+            current[5] = currentSegmentStartY;
         }
 
-        private static void drawArc(@NonNull Path2D p, float x0, float y0, float x1,
+        private static void drawArc(@NonNull Path_Delegate p, float x0, float y0, float x1,
                 float y1, float a, float b, float theta, boolean isMoreThanHalf,
                 boolean isPositiveArc) {
 
@@ -707,7 +790,7 @@
          * @param start The start angle of the arc on the ellipse
          * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
          */
-        private static void arcToBezier(@NonNull Path2D p, double cx, double cy, double a,
+        private static void arcToBezier(@NonNull Path_Delegate p, double cx, double cy, double a,
                 double b, double e1x, double e1y, double theta, double start,
                 double sweep) {
             // Taken from equations at:
@@ -744,8 +827,12 @@
                 double q2x = e2x - alpha * ep2x;
                 double q2y = e2y - alpha * ep2y;
 
-                p.curveTo((float) q1x, (float) q1y, (float) q2x, (float) q2y,
-                        (float) e2x, (float) e2y);
+                p.cubicTo((float) q1x,
+                        (float) q1y,
+                        (float) q2x,
+                        (float) q2y,
+                        (float) e2x,
+                        (float) e2y);
                 eta1 = eta2;
                 e1x = e2x;
                 e1y = e2y;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 85e2610..4039cdf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -484,6 +484,12 @@
     }
 
     @Override
+    public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+        int badgeDensity) {
+        return null;
+    }
+
+    @Override
     public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
         return null;
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 99af226..53f1912 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -60,6 +60,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
 import android.graphics.Canvas;
+import android.os.Looper;
 import android.preference.Preference_Delegate;
 import android.view.AttachInfo_Accessor;
 import android.view.BridgeInflater;
@@ -1398,6 +1399,14 @@
     }
 
     public void dispose() {
+        boolean createdLooper = false;
+        if (Looper.myLooper() == null) {
+            // Detaching the root view from the window will try to stop any running animations.
+            // The stop method checks that it can run in the looper so, if there is no current
+            // looper, we create a temporary one to complete the shutdown.
+            Bridge.prepareThread();
+            createdLooper = true;
+        }
         AttachInfo_Accessor.detachFromWindow(mViewRoot);
         if (mCanvas != null) {
             mCanvas.release();
@@ -1412,5 +1421,9 @@
         mImage = null;
         mViewRoot = null;
         mContentRoot = null;
+
+        if (createdLooper) {
+            Bridge.cleanupThread();
+        }
     }
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 8a23e4b..8c3bd2f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -269,6 +269,7 @@
         "android.graphics.SweepGradient",
         "android.graphics.Typeface",
         "android.graphics.Xfermode",
+        "android.graphics.drawable.VectorDrawable",
         "android.os.SystemClock",
         "android.os.SystemProperties",
         "android.text.AndroidBidi",
@@ -321,7 +322,12 @@
             "org.kxml2.io.KXmlParser"
         };
 
+    /**
+     * List of fields for which we will update the visibility to be public. This is sometimes
+     * needed when access from the delegate classes is needed.
+     */
     private final static String[] PROMOTED_FIELDS = new String[] {
+        "android.graphics.drawable.VectorDrawable#mVectorState",
         "android.view.Choreographer#mLastFrameTimeNanos"
     };
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e2dd111..a5bfd3c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -889,24 +889,6 @@
     }
 
     /**
-     * Sets whether or not the given network is metered from a network policy
-     * point of view. A network should be classified as metered when the user is
-     * sensitive to heavy data usage on that connection due to monetary costs,
-     * data limitations or battery/performance issues. A typical example would
-     * be a wifi connection where the user was being charged for usage.
-     * @param netId the integer that identifies the network configuration
-     * to the supplicant.
-     * @param isMetered True to mark the network as metered.
-     * @return {@code true} if the operation succeeded.
-     * @hide
-     */
-    @SystemApi
-    public boolean setMetered(int netId, boolean isMetered) {
-        // TODO(jjoslin): Implement
-        return false;
-    }
-
-    /**
      * Remove the specified network from the list of configured networks.
      * This may result in the asynchronous delivery of state change
      * events.