Merge "Fix build" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 7156800..dc7e280 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19221,7 +19221,6 @@
     method public double getElevationUncertaintyInDeg();
     method public byte getLossOfLock();
     method public byte getMultipathIndicator();
-    method public byte getPrn();
     method public double getPseudorangeInMeters();
     method public double getPseudorangeRateCarrierInMetersPerSec();
     method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
@@ -19232,6 +19231,7 @@
     method public long getReceivedGpsTowUncertaintyInNs();
     method public double getSnrInDb();
     method public short getState();
+    method public short getSvid();
     method public short getTimeFromLastBitInMs();
     method public double getTimeOffsetInNs();
     method public boolean hasAzimuthInDeg();
@@ -19291,7 +19291,6 @@
     method public void setElevationUncertaintyInDeg(double);
     method public void setLossOfLock(byte);
     method public void setMultipathIndicator(byte);
-    method public void setPrn(byte);
     method public void setPseudorangeInMeters(double);
     method public void setPseudorangeRateCarrierInMetersPerSec(double);
     method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
@@ -19302,6 +19301,7 @@
     method public void setReceivedGpsTowUncertaintyInNs(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);
@@ -19356,17 +19356,17 @@
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
-    method public byte getPrn();
     method public short getStatus();
     method public short getSubmessageId();
+    method public short getSvid();
     method public byte 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 setPrn(byte);
     method public void setStatus(short);
     method public void setSubmessageId(short);
+    method public void setSvid(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
@@ -19412,8 +19412,8 @@
     method public int getConstellationType(int);
     method public float getElevation(int);
     method public int getNumSatellites();
-    method public int getPrn(int);
     method public float getSnr(int);
+    method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
@@ -52969,10 +52969,6 @@
 
 package java.nio.channels {
 
-  public class AcceptPendingException extends java.lang.IllegalStateException {
-    ctor public AcceptPendingException();
-  }
-
   public class AlreadyBoundException extends java.lang.IllegalStateException {
     ctor public AlreadyBoundException();
   }
@@ -52981,68 +52977,10 @@
     ctor public AlreadyConnectedException();
   }
 
-  public abstract interface AsynchronousByteChannel implements java.nio.channels.AsynchronousChannel {
-    method public abstract void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-  }
-
-  public abstract interface AsynchronousChannel implements java.nio.channels.Channel {
-    method public abstract void close() throws java.io.IOException;
-  }
-
-  public abstract class AsynchronousChannelGroup {
-    ctor protected AsynchronousChannelGroup(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract boolean isShutdown();
-    method public abstract boolean isTerminated();
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void shutdown();
-    method public abstract void shutdownNow() throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withCachedThreadPool(java.util.concurrent.ExecutorService, int) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withFixedThreadPool(int, java.util.concurrent.ThreadFactory) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withThreadPool(java.util.concurrent.ExecutorService) throws java.io.IOException;
-  }
-
   public class AsynchronousCloseException extends java.nio.channels.ClosedChannelException {
     ctor public AsynchronousCloseException();
   }
 
-  public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
-    ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
-    method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
-    method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
-  }
-
-  public abstract class AsynchronousSocketChannel implements java.nio.channels.AsynchronousByteChannel java.nio.channels.NetworkChannel {
-    ctor protected AsynchronousSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
-    method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-    method public abstract java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel shutdownInput() throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel shutdownOutput() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-  }
-
   public abstract interface ByteChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.WritableByteChannel {
   }
 
@@ -53059,9 +52997,7 @@
     method public static java.nio.channels.ReadableByteChannel newChannel(java.io.InputStream);
     method public static java.nio.channels.WritableByteChannel newChannel(java.io.OutputStream);
     method public static java.io.InputStream newInputStream(java.nio.channels.ReadableByteChannel);
-    method public static java.io.InputStream newInputStream(java.nio.channels.AsynchronousByteChannel);
     method public static java.io.OutputStream newOutputStream(java.nio.channels.WritableByteChannel);
-    method public static java.io.OutputStream newOutputStream(java.nio.channels.AsynchronousByteChannel);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.lang.String);
     method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int);
@@ -53080,16 +53016,11 @@
     ctor public ClosedSelectorException();
   }
 
-  public abstract interface CompletionHandler {
-    method public abstract void completed(V, A);
-    method public abstract void failed(java.lang.Throwable, A);
-  }
-
   public class ConnectionPendingException extends java.lang.IllegalStateException {
     ctor public ConnectionPendingException();
   }
 
-  public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.MulticastChannel java.nio.channels.ScatteringByteChannel {
+  public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
     ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider);
     method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
@@ -53168,40 +53099,14 @@
     ctor public IllegalBlockingModeException();
   }
 
-  public class IllegalChannelGroupException extends java.lang.IllegalArgumentException {
-    ctor public IllegalChannelGroupException();
-  }
-
   public class IllegalSelectorException extends java.lang.IllegalArgumentException {
     ctor public IllegalSelectorException();
   }
 
-  public class InterruptedByTimeoutException extends java.io.IOException {
-    ctor public InterruptedByTimeoutException();
-  }
-
   public abstract interface InterruptibleChannel implements java.nio.channels.Channel {
     method public abstract void close() throws java.io.IOException;
   }
 
-  public abstract class MembershipKey {
-    ctor protected MembershipKey();
-    method public abstract java.nio.channels.MembershipKey block(java.net.InetAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.MulticastChannel channel();
-    method public abstract void drop();
-    method public abstract java.net.InetAddress group();
-    method public abstract boolean isValid();
-    method public abstract java.net.NetworkInterface networkInterface();
-    method public abstract java.net.InetAddress sourceAddress();
-    method public abstract java.nio.channels.MembershipKey unblock(java.net.InetAddress);
-  }
-
-  public abstract interface MulticastChannel implements java.nio.channels.NetworkChannel {
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.nio.channels.MembershipKey join(java.net.InetAddress, java.net.NetworkInterface) throws java.io.IOException;
-    method public abstract java.nio.channels.MembershipKey join(java.net.InetAddress, java.net.NetworkInterface, java.net.InetAddress) throws java.io.IOException;
-  }
-
   public abstract interface NetworkChannel implements java.nio.channels.Channel {
     method public abstract java.nio.channels.NetworkChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
@@ -53251,10 +53156,6 @@
     method public final int validOps();
   }
 
-  public class ReadPendingException extends java.lang.IllegalStateException {
-    ctor public ReadPendingException();
-  }
-
   public abstract interface ReadableByteChannel implements java.nio.channels.Channel {
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
   }
@@ -53332,10 +53233,6 @@
     method public final int validOps();
   }
 
-  public class ShutdownChannelGroupException extends java.lang.IllegalStateException {
-    ctor public ShutdownChannelGroupException();
-  }
-
   public abstract class SocketChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel {
     ctor protected SocketChannel(java.nio.channels.spi.SelectorProvider);
     method public abstract java.nio.channels.SocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
@@ -53371,10 +53268,6 @@
     method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
   }
 
-  public class WritePendingException extends java.lang.IllegalStateException {
-    ctor public WritePendingException();
-  }
-
 }
 
 package java.nio.channels.spi {
@@ -53421,15 +53314,6 @@
     method protected abstract java.nio.channels.SelectionKey register(java.nio.channels.spi.AbstractSelectableChannel, int, java.lang.Object);
   }
 
-  public abstract class AsynchronousChannelProvider {
-    ctor protected AsynchronousChannelProvider();
-    method public abstract java.nio.channels.AsynchronousChannelGroup openAsynchronousChannelGroup(int, java.util.concurrent.ThreadFactory) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousChannelGroup openAsynchronousChannelGroup(java.util.concurrent.ExecutorService, int) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel openAsynchronousSocketChannel(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.spi.AsynchronousChannelProvider provider();
-  }
-
   public abstract class SelectorProvider {
     ctor protected SelectorProvider();
     method public java.nio.channels.Channel inheritedChannel() throws java.io.IOException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 1c89672..61f72f3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -20401,7 +20401,6 @@
     method public double getElevationUncertaintyInDeg();
     method public byte getLossOfLock();
     method public byte getMultipathIndicator();
-    method public byte getPrn();
     method public double getPseudorangeInMeters();
     method public double getPseudorangeRateCarrierInMetersPerSec();
     method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
@@ -20412,6 +20411,7 @@
     method public long getReceivedGpsTowUncertaintyInNs();
     method public double getSnrInDb();
     method public short getState();
+    method public short getSvid();
     method public short getTimeFromLastBitInMs();
     method public double getTimeOffsetInNs();
     method public boolean hasAzimuthInDeg();
@@ -20471,7 +20471,6 @@
     method public void setElevationUncertaintyInDeg(double);
     method public void setLossOfLock(byte);
     method public void setMultipathIndicator(byte);
-    method public void setPrn(byte);
     method public void setPseudorangeInMeters(double);
     method public void setPseudorangeRateCarrierInMetersPerSec(double);
     method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
@@ -20482,6 +20481,7 @@
     method public void setReceivedGpsTowUncertaintyInNs(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);
@@ -20536,17 +20536,17 @@
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
-    method public byte getPrn();
     method public short getStatus();
     method public short getSubmessageId();
+    method public short getSvid();
     method public byte 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 setPrn(byte);
     method public void setStatus(short);
     method public void setSubmessageId(short);
+    method public void setSvid(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
@@ -20592,8 +20592,8 @@
     method public int getConstellationType(int);
     method public float getElevation(int);
     method public int getNumSatellites();
-    method public int getPrn(int);
     method public float getSnr(int);
+    method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
@@ -26682,6 +26682,7 @@
     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);
@@ -56057,10 +56058,6 @@
 
 package java.nio.channels {
 
-  public class AcceptPendingException extends java.lang.IllegalStateException {
-    ctor public AcceptPendingException();
-  }
-
   public class AlreadyBoundException extends java.lang.IllegalStateException {
     ctor public AlreadyBoundException();
   }
@@ -56069,68 +56066,10 @@
     ctor public AlreadyConnectedException();
   }
 
-  public abstract interface AsynchronousByteChannel implements java.nio.channels.AsynchronousChannel {
-    method public abstract void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-  }
-
-  public abstract interface AsynchronousChannel implements java.nio.channels.Channel {
-    method public abstract void close() throws java.io.IOException;
-  }
-
-  public abstract class AsynchronousChannelGroup {
-    ctor protected AsynchronousChannelGroup(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract boolean isShutdown();
-    method public abstract boolean isTerminated();
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void shutdown();
-    method public abstract void shutdownNow() throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withCachedThreadPool(java.util.concurrent.ExecutorService, int) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withFixedThreadPool(int, java.util.concurrent.ThreadFactory) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withThreadPool(java.util.concurrent.ExecutorService) throws java.io.IOException;
-  }
-
   public class AsynchronousCloseException extends java.nio.channels.ClosedChannelException {
     ctor public AsynchronousCloseException();
   }
 
-  public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
-    ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
-    method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
-    method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
-  }
-
-  public abstract class AsynchronousSocketChannel implements java.nio.channels.AsynchronousByteChannel java.nio.channels.NetworkChannel {
-    ctor protected AsynchronousSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
-    method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-    method public abstract java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel shutdownInput() throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel shutdownOutput() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-  }
-
   public abstract interface ByteChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.WritableByteChannel {
   }
 
@@ -56147,9 +56086,7 @@
     method public static java.nio.channels.ReadableByteChannel newChannel(java.io.InputStream);
     method public static java.nio.channels.WritableByteChannel newChannel(java.io.OutputStream);
     method public static java.io.InputStream newInputStream(java.nio.channels.ReadableByteChannel);
-    method public static java.io.InputStream newInputStream(java.nio.channels.AsynchronousByteChannel);
     method public static java.io.OutputStream newOutputStream(java.nio.channels.WritableByteChannel);
-    method public static java.io.OutputStream newOutputStream(java.nio.channels.AsynchronousByteChannel);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.lang.String);
     method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int);
@@ -56168,16 +56105,11 @@
     ctor public ClosedSelectorException();
   }
 
-  public abstract interface CompletionHandler {
-    method public abstract void completed(V, A);
-    method public abstract void failed(java.lang.Throwable, A);
-  }
-
   public class ConnectionPendingException extends java.lang.IllegalStateException {
     ctor public ConnectionPendingException();
   }
 
-  public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.MulticastChannel java.nio.channels.ScatteringByteChannel {
+  public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
     ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider);
     method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
@@ -56256,40 +56188,14 @@
     ctor public IllegalBlockingModeException();
   }
 
-  public class IllegalChannelGroupException extends java.lang.IllegalArgumentException {
-    ctor public IllegalChannelGroupException();
-  }
-
   public class IllegalSelectorException extends java.lang.IllegalArgumentException {
     ctor public IllegalSelectorException();
   }
 
-  public class InterruptedByTimeoutException extends java.io.IOException {
-    ctor public InterruptedByTimeoutException();
-  }
-
   public abstract interface InterruptibleChannel implements java.nio.channels.Channel {
     method public abstract void close() throws java.io.IOException;
   }
 
-  public abstract class MembershipKey {
-    ctor protected MembershipKey();
-    method public abstract java.nio.channels.MembershipKey block(java.net.InetAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.MulticastChannel channel();
-    method public abstract void drop();
-    method public abstract java.net.InetAddress group();
-    method public abstract boolean isValid();
-    method public abstract java.net.NetworkInterface networkInterface();
-    method public abstract java.net.InetAddress sourceAddress();
-    method public abstract java.nio.channels.MembershipKey unblock(java.net.InetAddress);
-  }
-
-  public abstract interface MulticastChannel implements java.nio.channels.NetworkChannel {
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.nio.channels.MembershipKey join(java.net.InetAddress, java.net.NetworkInterface) throws java.io.IOException;
-    method public abstract java.nio.channels.MembershipKey join(java.net.InetAddress, java.net.NetworkInterface, java.net.InetAddress) throws java.io.IOException;
-  }
-
   public abstract interface NetworkChannel implements java.nio.channels.Channel {
     method public abstract java.nio.channels.NetworkChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
@@ -56339,10 +56245,6 @@
     method public final int validOps();
   }
 
-  public class ReadPendingException extends java.lang.IllegalStateException {
-    ctor public ReadPendingException();
-  }
-
   public abstract interface ReadableByteChannel implements java.nio.channels.Channel {
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
   }
@@ -56420,10 +56322,6 @@
     method public final int validOps();
   }
 
-  public class ShutdownChannelGroupException extends java.lang.IllegalStateException {
-    ctor public ShutdownChannelGroupException();
-  }
-
   public abstract class SocketChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel {
     ctor protected SocketChannel(java.nio.channels.spi.SelectorProvider);
     method public abstract java.nio.channels.SocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
@@ -56459,10 +56357,6 @@
     method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
   }
 
-  public class WritePendingException extends java.lang.IllegalStateException {
-    ctor public WritePendingException();
-  }
-
 }
 
 package java.nio.channels.spi {
@@ -56509,15 +56403,6 @@
     method protected abstract java.nio.channels.SelectionKey register(java.nio.channels.spi.AbstractSelectableChannel, int, java.lang.Object);
   }
 
-  public abstract class AsynchronousChannelProvider {
-    ctor protected AsynchronousChannelProvider();
-    method public abstract java.nio.channels.AsynchronousChannelGroup openAsynchronousChannelGroup(int, java.util.concurrent.ThreadFactory) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousChannelGroup openAsynchronousChannelGroup(java.util.concurrent.ExecutorService, int) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel openAsynchronousSocketChannel(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.spi.AsynchronousChannelProvider provider();
-  }
-
   public abstract class SelectorProvider {
     ctor protected SelectorProvider();
     method public java.nio.channels.Channel inheritedChannel() throws java.io.IOException;
diff --git a/api/test-current.txt b/api/test-current.txt
index 929b7cb..17d788f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -19229,7 +19229,6 @@
     method public double getElevationUncertaintyInDeg();
     method public byte getLossOfLock();
     method public byte getMultipathIndicator();
-    method public byte getPrn();
     method public double getPseudorangeInMeters();
     method public double getPseudorangeRateCarrierInMetersPerSec();
     method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
@@ -19240,6 +19239,7 @@
     method public long getReceivedGpsTowUncertaintyInNs();
     method public double getSnrInDb();
     method public short getState();
+    method public short getSvid();
     method public short getTimeFromLastBitInMs();
     method public double getTimeOffsetInNs();
     method public boolean hasAzimuthInDeg();
@@ -19299,7 +19299,6 @@
     method public void setElevationUncertaintyInDeg(double);
     method public void setLossOfLock(byte);
     method public void setMultipathIndicator(byte);
-    method public void setPrn(byte);
     method public void setPseudorangeInMeters(double);
     method public void setPseudorangeRateCarrierInMetersPerSec(double);
     method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
@@ -19310,6 +19309,7 @@
     method public void setReceivedGpsTowUncertaintyInNs(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);
@@ -19364,17 +19364,17 @@
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
-    method public byte getPrn();
     method public short getStatus();
     method public short getSubmessageId();
+    method public short getSvid();
     method public byte 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 setPrn(byte);
     method public void setStatus(short);
     method public void setSubmessageId(short);
+    method public void setSvid(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
@@ -19420,8 +19420,8 @@
     method public int getConstellationType(int);
     method public float getElevation(int);
     method public int getNumSatellites();
-    method public int getPrn(int);
     method public float getSnr(int);
+    method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
@@ -52986,10 +52986,6 @@
 
 package java.nio.channels {
 
-  public class AcceptPendingException extends java.lang.IllegalStateException {
-    ctor public AcceptPendingException();
-  }
-
   public class AlreadyBoundException extends java.lang.IllegalStateException {
     ctor public AlreadyBoundException();
   }
@@ -52998,68 +52994,10 @@
     ctor public AlreadyConnectedException();
   }
 
-  public abstract interface AsynchronousByteChannel implements java.nio.channels.AsynchronousChannel {
-    method public abstract void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-  }
-
-  public abstract interface AsynchronousChannel implements java.nio.channels.Channel {
-    method public abstract void close() throws java.io.IOException;
-  }
-
-  public abstract class AsynchronousChannelGroup {
-    ctor protected AsynchronousChannelGroup(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
-    method public abstract boolean isShutdown();
-    method public abstract boolean isTerminated();
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void shutdown();
-    method public abstract void shutdownNow() throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withCachedThreadPool(java.util.concurrent.ExecutorService, int) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withFixedThreadPool(int, java.util.concurrent.ThreadFactory) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousChannelGroup withThreadPool(java.util.concurrent.ExecutorService) throws java.io.IOException;
-  }
-
   public class AsynchronousCloseException extends java.nio.channels.ClosedChannelException {
     ctor public AsynchronousCloseException();
   }
 
-  public abstract class AsynchronousServerSocketChannel implements java.nio.channels.AsynchronousChannel java.nio.channels.NetworkChannel {
-    ctor protected AsynchronousServerSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract void accept(A, java.nio.channels.CompletionHandler<java.nio.channels.AsynchronousSocketChannel, ? super A>);
-    method public abstract java.util.concurrent.Future<java.nio.channels.AsynchronousSocketChannel> accept();
-    method public final java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel bind(java.net.SocketAddress, int) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousServerSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousServerSocketChannel open() throws java.io.IOException;
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
-  }
-
-  public abstract class AsynchronousSocketChannel implements java.nio.channels.AsynchronousByteChannel java.nio.channels.NetworkChannel {
-    ctor protected AsynchronousSocketChannel(java.nio.channels.spi.AsynchronousChannelProvider);
-    method public abstract java.nio.channels.AsynchronousSocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
-    method public abstract void connect(java.net.SocketAddress, A, java.nio.channels.CompletionHandler<java.lang.Void, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Void> connect(java.net.SocketAddress);
-    method public abstract java.net.SocketAddress getRemoteAddress() throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousSocketChannel open(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.AsynchronousSocketChannel open() throws java.io.IOException;
-    method public final java.nio.channels.spi.AsynchronousChannelProvider provider();
-    method public abstract void read(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void read(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> read(java.nio.ByteBuffer);
-    method public abstract void read(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-    method public abstract java.nio.channels.AsynchronousSocketChannel setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel shutdownInput() throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel shutdownOutput() throws java.io.IOException;
-    method public abstract void write(java.nio.ByteBuffer, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public final void write(java.nio.ByteBuffer, A, java.nio.channels.CompletionHandler<java.lang.Integer, ? super A>);
-    method public abstract java.util.concurrent.Future<java.lang.Integer> write(java.nio.ByteBuffer);
-    method public abstract void write(java.nio.ByteBuffer[], int, int, long, java.util.concurrent.TimeUnit, A, java.nio.channels.CompletionHandler<java.lang.Long, ? super A>);
-  }
-
   public abstract interface ByteChannel implements java.nio.channels.ReadableByteChannel java.nio.channels.WritableByteChannel {
   }
 
@@ -53076,9 +53014,7 @@
     method public static java.nio.channels.ReadableByteChannel newChannel(java.io.InputStream);
     method public static java.nio.channels.WritableByteChannel newChannel(java.io.OutputStream);
     method public static java.io.InputStream newInputStream(java.nio.channels.ReadableByteChannel);
-    method public static java.io.InputStream newInputStream(java.nio.channels.AsynchronousByteChannel);
     method public static java.io.OutputStream newOutputStream(java.nio.channels.WritableByteChannel);
-    method public static java.io.OutputStream newOutputStream(java.nio.channels.AsynchronousByteChannel);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.lang.String);
     method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int);
@@ -53097,16 +53033,11 @@
     ctor public ClosedSelectorException();
   }
 
-  public abstract interface CompletionHandler {
-    method public abstract void completed(V, A);
-    method public abstract void failed(java.lang.Throwable, A);
-  }
-
   public class ConnectionPendingException extends java.lang.IllegalStateException {
     ctor public ConnectionPendingException();
   }
 
-  public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.MulticastChannel java.nio.channels.ScatteringByteChannel {
+  public abstract class DatagramChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.ScatteringByteChannel {
     ctor protected DatagramChannel(java.nio.channels.spi.SelectorProvider);
     method public abstract java.nio.channels.DatagramChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.nio.channels.DatagramChannel connect(java.net.SocketAddress) throws java.io.IOException;
@@ -53185,40 +53116,14 @@
     ctor public IllegalBlockingModeException();
   }
 
-  public class IllegalChannelGroupException extends java.lang.IllegalArgumentException {
-    ctor public IllegalChannelGroupException();
-  }
-
   public class IllegalSelectorException extends java.lang.IllegalArgumentException {
     ctor public IllegalSelectorException();
   }
 
-  public class InterruptedByTimeoutException extends java.io.IOException {
-    ctor public InterruptedByTimeoutException();
-  }
-
   public abstract interface InterruptibleChannel implements java.nio.channels.Channel {
     method public abstract void close() throws java.io.IOException;
   }
 
-  public abstract class MembershipKey {
-    ctor protected MembershipKey();
-    method public abstract java.nio.channels.MembershipKey block(java.net.InetAddress) throws java.io.IOException;
-    method public abstract java.nio.channels.MulticastChannel channel();
-    method public abstract void drop();
-    method public abstract java.net.InetAddress group();
-    method public abstract boolean isValid();
-    method public abstract java.net.NetworkInterface networkInterface();
-    method public abstract java.net.InetAddress sourceAddress();
-    method public abstract java.nio.channels.MembershipKey unblock(java.net.InetAddress);
-  }
-
-  public abstract interface MulticastChannel implements java.nio.channels.NetworkChannel {
-    method public abstract void close() throws java.io.IOException;
-    method public abstract java.nio.channels.MembershipKey join(java.net.InetAddress, java.net.NetworkInterface) throws java.io.IOException;
-    method public abstract java.nio.channels.MembershipKey join(java.net.InetAddress, java.net.NetworkInterface, java.net.InetAddress) throws java.io.IOException;
-  }
-
   public abstract interface NetworkChannel implements java.nio.channels.Channel {
     method public abstract java.nio.channels.NetworkChannel bind(java.net.SocketAddress) throws java.io.IOException;
     method public abstract java.net.SocketAddress getLocalAddress() throws java.io.IOException;
@@ -53268,10 +53173,6 @@
     method public final int validOps();
   }
 
-  public class ReadPendingException extends java.lang.IllegalStateException {
-    ctor public ReadPendingException();
-  }
-
   public abstract interface ReadableByteChannel implements java.nio.channels.Channel {
     method public abstract int read(java.nio.ByteBuffer) throws java.io.IOException;
   }
@@ -53349,10 +53250,6 @@
     method public final int validOps();
   }
 
-  public class ShutdownChannelGroupException extends java.lang.IllegalStateException {
-    ctor public ShutdownChannelGroupException();
-  }
-
   public abstract class SocketChannel extends java.nio.channels.spi.AbstractSelectableChannel implements java.nio.channels.ByteChannel java.nio.channels.GatheringByteChannel java.nio.channels.NetworkChannel java.nio.channels.ScatteringByteChannel {
     ctor protected SocketChannel(java.nio.channels.spi.SelectorProvider);
     method public abstract java.nio.channels.SocketChannel bind(java.net.SocketAddress) throws java.io.IOException;
@@ -53388,10 +53285,6 @@
     method public abstract int write(java.nio.ByteBuffer) throws java.io.IOException;
   }
 
-  public class WritePendingException extends java.lang.IllegalStateException {
-    ctor public WritePendingException();
-  }
-
 }
 
 package java.nio.channels.spi {
@@ -53438,15 +53331,6 @@
     method protected abstract java.nio.channels.SelectionKey register(java.nio.channels.spi.AbstractSelectableChannel, int, java.lang.Object);
   }
 
-  public abstract class AsynchronousChannelProvider {
-    ctor protected AsynchronousChannelProvider();
-    method public abstract java.nio.channels.AsynchronousChannelGroup openAsynchronousChannelGroup(int, java.util.concurrent.ThreadFactory) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousChannelGroup openAsynchronousChannelGroup(java.util.concurrent.ExecutorService, int) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public abstract java.nio.channels.AsynchronousSocketChannel openAsynchronousSocketChannel(java.nio.channels.AsynchronousChannelGroup) throws java.io.IOException;
-    method public static java.nio.channels.spi.AsynchronousChannelProvider provider();
-  }
-
   public abstract class SelectorProvider {
     ctor protected SelectorProvider();
     method public java.nio.channels.Channel inheritedChannel() throws java.io.IOException;
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 3385a17..980329f 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -807,8 +807,6 @@
     }
 
     /**
-     * AnimatorSet is only reversible when the set contains no sequential animation, and no child
-     * animators have a start delay.
      * @hide
      */
     @Override
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 55c6353..35b7c39 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3358,13 +3358,9 @@
                 return mN.bigContentView;
             } else if (mStyle != null) {
                 result = mStyle.makeBigContentView();
-            } else if (mActions.size() == 0) {
-                return null;
-            }
-            if (result == null) {
-                result = applyStandardTemplateWithActions(getBigBaseLayoutResource());
-            } else {
                 hideLine1Text(result);
+            } else if (mActions.size() != 0) {
+                result = applyStandardTemplateWithActions(getBigBaseLayoutResource());
             }
             adaptNotificationHeaderForBigContentView(result);
             return result;
@@ -3384,11 +3380,15 @@
         }
 
         private void hideLine1Text(RemoteViews result) {
-            result.setViewVisibility(R.id.text_line_1, View.GONE);
+            if (result != null) {
+                result.setViewVisibility(R.id.text_line_1, View.GONE);
+            }
         }
 
         private void adaptNotificationHeaderForBigContentView(RemoteViews result) {
-            result.setBoolean(R.id.notification_header, "setExpanded", true);
+            if (result != null) {
+                result.setBoolean(R.id.notification_header, "setExpanded", true);
+            }
         }
 
         /**
@@ -4326,6 +4326,15 @@
             return makeMediaBigContentView();
         }
 
+        /**
+         * @hide
+         */
+        @Override
+        public RemoteViews makeHeadsUpContentView() {
+            RemoteViews expanded = makeMediaBigContentView();
+            return expanded != null ? expanded : makeMediaContentView();
+        }
+
         /** @hide */
         @Override
         public void addExtras(Bundle extras) {
@@ -4407,6 +4416,13 @@
 
         private RemoteViews makeMediaBigContentView() {
             final int actionCount = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS);
+            // Dont add an expanded view if there is no more content to be revealed
+            int actionsInCompact = mActionsToShowInCompact == null
+                    ? 0
+                    : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT);
+            if (mBuilder.mN.mLargeIcon == null && actionCount <= actionsInCompact) {
+                return null;
+            }
             RemoteViews big = mBuilder.applyStandardTemplate(
                     R.layout.notification_template_material_big_media,
                     false);
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 43a0cc7..f58b16a 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -178,6 +178,11 @@
      */
     public static final int RESIZE_MODE_RESIZEABLE_AND_PIPABLE = 3;
     /**
+     * Activity is does not support resizing, but we are forcing it to be resizeable.
+     * @hide
+     */
+    public static final int RESIZE_MODE_FORCE_RESIZEABLE = 4;
+    /**
      * Value indicating if the resizing mode the activity supports.
      * See {@link android.R.attr#resizeableActivity}.
      * @hide
@@ -786,7 +791,9 @@
 
     /** @hide */
     public static boolean isResizeableMode(int mode) {
-        return mode == RESIZE_MODE_RESIZEABLE || mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
+        return mode == RESIZE_MODE_RESIZEABLE
+                || mode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE
+                || mode == RESIZE_MODE_FORCE_RESIZEABLE;
     }
 
     /** @hide */
@@ -800,6 +807,8 @@
                 return "RESIZE_MODE_RESIZEABLE";
             case RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
                 return "RESIZE_MODE_RESIZEABLE_AND_PIPABLE";
+            case RESIZE_MODE_FORCE_RESIZEABLE:
+                return "RESIZE_MODE_FORCE_RESIZEABLE";
             default:
                 return "unknown=" + mode;
         }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 5dddebd..5ae8d4c 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -80,6 +80,7 @@
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
@@ -3448,7 +3449,7 @@
                 a.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
             } else if (a.info.screenOrientation == SCREEN_ORIENTATION_UNSPECIFIED
                     && (a.info.flags & FLAG_IMMERSIVE) == 0) {
-                a.info.resizeMode = RESIZE_MODE_CROP_WINDOWS;
+                a.info.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
             }
 
             if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 3f36d65..b6fe68a 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -105,7 +105,8 @@
     /**
      * Broadcast action: the active scorer has been changed. Scorer apps may listen to this to
      * perform initialization once selected as the active scorer, or clean up unneeded resources
-     * if another scorer has been selected. Note that it is unnecessary to clear existing scores as
+     * if another scorer has been selected. This is an explicit broadcast only sent to the
+     * previous scorer and new scorer. Note that it is unnecessary to clear existing scores as
      * this is handled by the system.
      *
      * <p>The new scorer will be specified in {@link #EXTRA_NEW_SCORER}.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index dc0e249..69d564f 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1141,6 +1141,8 @@
         UserInfo user = null;
         try {
             user = mService.createUser(name, flags);
+            // TODO: Keep this in sync with
+            // UserManagerService.LocalService.createUserEvenWhenDisallowed
             if (user != null && !user.isAdmin()) {
                 mService.setUserRestriction(DISALLOW_SMS, true, user.id);
                 mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id);
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 58a0269..d2ece8b 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
 
 /**
@@ -106,4 +107,12 @@
      * non-ephemeral users left.
      */
     public abstract void removeAllUsers();
+
+    /**
+     * Same as UserManager.createUser(), but bypasses the check for DISALLOW_ADD_USER.
+     *
+     * <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
+     * createAndManageUser is called by the device owner.
+     */
+    public abstract UserInfo createUserEvenWhenDisallowed(String name, int flags);
 }
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index 675803c..707c0fcb 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.Nullable;
 import android.view.View;
 
 import static android.text.TextDirectionHeuristics.FIRSTSTRONG_LTR;
@@ -390,14 +391,17 @@
      * @return Input string after applying the above processing. {@code null} if {@code str} is
      *     {@code null}.
      */
-    public String unicodeWrap(String str, TextDirectionHeuristic heuristic, boolean isolate) {
+    public @Nullable String unicodeWrap(@Nullable String str, TextDirectionHeuristic heuristic,
+            boolean isolate) {
+        if (str == null) return null;
         return unicodeWrap((CharSequence) str, heuristic, isolate).toString();
     }
 
     /**
      * @hide
      */
-    public CharSequence unicodeWrap(CharSequence str, TextDirectionHeuristic heuristic, boolean isolate) {
+    public @Nullable CharSequence unicodeWrap(@Nullable CharSequence str,
+            TextDirectionHeuristic heuristic, boolean isolate) {
         if (str == null) return null;
         final boolean isRtl = heuristic.isRtl(str, 0, str.length());
         SpannableStringBuilder result = new SpannableStringBuilder();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2612ab2..bba5a17 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6874,6 +6874,15 @@
      * @param info The info whose drawing order should be populated
      */
     private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
+        /*
+         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
+         * drawing order may not be well-defined, and some Views with custom drawing order may
+         * not be initialized sufficiently to respond properly getChildDrawingOrder.
+         */
+        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
+            info.setDrawingOrder(0);
+            return;
+        }
         int drawingOrderInParent = 1;
         // Iterate up the hierarchy if parents are not important for a11y
         View viewAtDrawingLevel = this;
diff --git a/core/java/com/android/internal/util/LineBreakBufferedWriter.java b/core/java/com/android/internal/util/LineBreakBufferedWriter.java
index f831e7a..552a93f 100644
--- a/core/java/com/android/internal/util/LineBreakBufferedWriter.java
+++ b/core/java/com/android/internal/util/LineBreakBufferedWriter.java
@@ -96,7 +96,7 @@
 
     @Override
     public void write(int c) {
-        if (bufferIndex < bufferSize) {
+        if (bufferIndex < buffer.length) {
             buffer[bufferIndex] = (char)c;
             bufferIndex++;
             if ((char)c == '\n') {
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
index 14badb7..7a3c598 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -43,13 +43,12 @@
     return env;
 }
 
-static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener, jint id) {
+static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) {
     class AnimationListenerBridge : public AnimationListener {
     public:
-        AnimationListenerBridge(JNIEnv* env, jobject finishListener, jint id) {
+        AnimationListenerBridge(JNIEnv* env, jobject finishListener) {
             mFinishListener = env->NewGlobalRef(finishListener);
             env->GetJavaVM(&mJvm);
-            mId = id;
         }
 
         virtual ~AnimationListenerBridge() {
@@ -64,7 +63,7 @@
             env->CallStaticVoidMethod(
                     gVectorDrawableAnimatorClassInfo.clazz,
                     gVectorDrawableAnimatorClassInfo.callOnFinished,
-                    mFinishListener, mId);
+                    mFinishListener);
             releaseJavaObject();
         }
 
@@ -77,9 +76,8 @@
 
         JavaVM* mJvm;
         jobject mFinishListener;
-        jint mId;
     };
-    return new AnimationListenerBridge(env, finishListener, id);
+    return new AnimationListenerBridge(env, finishListener);
 }
 
 static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr,
@@ -144,16 +142,15 @@
     holder->setPropertyDataSource(propertyData, length);
     env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT);
 }
-static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) {
+static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
     PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
-    AnimationListener* listener = createAnimationListener(env, finishListener, id);
+    // TODO: keep a ref count in finish listener
+    AnimationListener* listener = createAnimationListener(env, finishListener);
     set->start(listener);
 }
 
-static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) {
-    PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
-    AnimationListener* listener = createAnimationListener(env, finishListener, id);
-    set->reverse(listener);
+static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
+    // TODO: implement reverse
 }
 
 static void end(JNIEnv*, jobject, jlong animatorSetPtr) {
@@ -175,8 +172,8 @@
     {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
     {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
     {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
-    {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)start},
-    {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)reverse},
+    {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start},
+    {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse},
     {"nEnd", "!(J)V", (void*)end},
     {"nReset", "!(J)V", (void*)reset},
 };
@@ -189,7 +186,7 @@
 
     gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie(
             env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished",
-            "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V");
+            "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V");
     return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable",
             gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index c9eac79..0926e9b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -184,7 +184,7 @@
 
 static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) {
     BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
-    animator->cancel();
+    animator->end();
 }
 
 // ----------------------------------------------------------------------------
diff --git a/core/res/res/layout/floating_popup_container.xml b/core/res/res/layout/floating_popup_container.xml
index dd161e3..ca03737 100644
--- a/core/res/res/layout/floating_popup_container.xml
+++ b/core/res/res/layout/floating_popup_container.xml
@@ -19,8 +19,8 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:padding="0dp"
-    android:layout_margin="20dp"
-    android:elevation="2dp"
+    android:layout_margin="@android:dimen/text_edit_floating_toolbar_margin"
+    android:elevation="@android:dimen/text_edit_floating_toolbar_elevation"
     android:focusable="true"
     android:focusableInTouchMode="true"
     android:background="?attr/floatingToolbarPopupBackgroundDrawable"/>
diff --git a/core/res/res/layout/text_edit_suggestion_container.xml b/core/res/res/layout/text_edit_suggestion_container.xml
index 17e93d0..b2589da 100644
--- a/core/res/res/layout/text_edit_suggestion_container.xml
+++ b/core/res/res/layout/text_edit_suggestion_container.xml
@@ -22,8 +22,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:elevation="2dp"
-        android:layout_margin="20dp"
+        android:elevation="@android:dimen/text_edit_floating_toolbar_elevation"
+        android:layout_margin="@android:dimen/text_edit_floating_toolbar_margin"
         android:background="@drawable/text_edit_suggestions_window"
         android:dropDownSelector="@drawable/list_selector_background"
         android:divider="@null">
diff --git a/core/res/res/layout/text_edit_suggestion_container_material.xml b/core/res/res/layout/text_edit_suggestion_container_material.xml
index 7826803..20a80489 100644
--- a/core/res/res/layout/text_edit_suggestion_container_material.xml
+++ b/core/res/res/layout/text_edit_suggestion_container_material.xml
@@ -24,8 +24,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:background="?android:attr/floatingToolbarPopupBackgroundDrawable"
-        android:elevation="2dp"
-        android:layout_margin="20dp"
+        android:elevation="@android:dimen/text_edit_floating_toolbar_elevation"
+        android:layout_margin="@android:dimen/text_edit_floating_toolbar_margin"
         android:orientation="vertical"
         android:divider="?android:attr/listDivider"
         android:showDividers="middle">
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 96a81d1..2fe4f66 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -82,6 +82,9 @@
     <dimen name="text_size_medium_material">18sp</dimen>
     <dimen name="text_size_small_material">14sp</dimen>
 
+    <dimen name="text_edit_floating_toolbar_elevation">2dp</dimen>
+    <dimen name="text_edit_floating_toolbar_margin">20dp</dimen>
+
     <dimen name="floating_window_z">16dp</dimen>
     <dimen name="floating_window_margin_left">16dp</dimen>
     <dimen name="floating_window_margin_top">8dp</dimen>
diff --git a/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java b/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
index 49ae104..4845c4e 100644
--- a/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
@@ -180,6 +180,22 @@
         assertOutput("aaaaaaaaaabbbbbc\nd", "ddddddddd");
     }
 
+    public void testMoreThenInitialCapacitySimpleWrites() {
+        // This check is different from testMoreThanBufferSizeChar. The initial capacity is lower
+        // than the maximum buffer size here.
+        final LineBreakBufferedWriter lw = new LineBreakBufferedWriter(mWriter, 1024, 3);
+
+        for(int i = 0; i < 10; i++) {
+            lw.print('$');
+        }
+        for(int i = 0; i < 10; i++) {
+            lw.print('%');
+        }
+        lw.flush();
+
+        assertOutput("$$$$$$$$$$%%%%%%%%%%");
+    }
+
     private void assertOutput(String... golden) {
         List<String> goldList = createTestGolden(golden);
         assertEquals(goldList, mWriter.getStrings());
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 99bc306..af8ccf5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -238,6 +238,9 @@
             mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas);
         }
         mAnimatedVectorState.mVectorDrawable.draw(canvas);
+        if (isStarted()) {
+            invalidateSelf();
+        }
     }
 
     @Override
@@ -608,6 +611,10 @@
         return mAnimatorSet.isRunning();
     }
 
+    private boolean isStarted() {
+        return mAnimatorSet.isStarted();
+    }
+
     /**
      * Resets the AnimatedVectorDrawable to the start state as specified in the animators.
      */
@@ -619,6 +626,12 @@
     @Override
     public void start() {
         ensureAnimatorSet();
+
+        // If any one of the animator has not ended, do nothing.
+        if (isStarted()) {
+            return;
+        }
+
         mAnimatorSet.start();
         invalidateSelf();
     }
@@ -639,7 +652,6 @@
     @Override
     public void stop() {
         mAnimatorSet.end();
-        invalidateSelf();
     }
 
     /**
@@ -762,9 +774,6 @@
      * @hide
      */
     public static class VectorDrawableAnimator {
-        private static final int NONE = 0;
-        private static final int START_ANIMATION = 1;
-        private static final int REVERSE_ANIMATION = 2;
         private AnimatorListener mListener = null;
         private final LongArray mStartDelays = new LongArray();
         private PropertyValuesHolder.PropertyValues mTmpValues =
@@ -773,6 +782,7 @@
         private boolean mContainsSequentialAnimators = false;
         private boolean mStarted = false;
         private boolean mInitialized = false;
+        private boolean mAnimationPending = false;
         private boolean mIsReversible = false;
         // This needs to be set before parsing starts.
         private boolean mShouldIgnoreInvalidAnim;
@@ -780,8 +790,7 @@
         private final VirtualRefBasePtr mSetRefBasePtr;
         private WeakReference<RenderNode> mTarget = null;
         private WeakReference<RenderNode> mLastSeenTarget = null;
-        private int mLastListenerId = 0;
-        private int mPendingAnimationAction = NONE;
+
 
         VectorDrawableAnimator() {
             mSetPtr = nCreateAnimatorSet();
@@ -801,7 +810,6 @@
             mInitialized = true;
 
             // Check reversible.
-            mIsReversible = true;
             if (mContainsSequentialAnimators) {
                 mIsReversible = false;
             } else {
@@ -813,6 +821,7 @@
                     }
                 }
             }
+            mIsReversible = true;
         }
 
         private void parseAnimatorSet(AnimatorSet set, long startTime) {
@@ -1033,22 +1042,27 @@
          * to the last seen RenderNode target and start right away.
          */
         protected void recordLastSeenTarget(DisplayListCanvas canvas) {
-            mLastSeenTarget = new WeakReference<RenderNode>(
-                    RenderNodeAnimatorSetHelper.getTarget(canvas));
-            if (mPendingAnimationAction != NONE) {
+            if (mAnimationPending) {
+                mLastSeenTarget = new WeakReference<RenderNode>(
+                        RenderNodeAnimatorSetHelper.getTarget(canvas));
                 if (DBG_ANIMATION_VECTOR_DRAWABLE) {
                     Log.d(LOGTAG, "Target is set in the next frame");
                 }
-                if (mPendingAnimationAction == START_ANIMATION) {
-                    start();
-                } else if (mPendingAnimationAction == REVERSE_ANIMATION) {
-                    reverse();
-                }
-                mPendingAnimationAction = NONE;
+                mAnimationPending = false;
+                start();
+            } else {
+                mLastSeenTarget = new WeakReference<RenderNode>(
+                        RenderNodeAnimatorSetHelper.getTarget(canvas));
             }
+
         }
 
         private boolean setTarget(RenderNode node) {
+            if (mTarget != null && mTarget.get() != null) {
+                // TODO: Maybe we want to support target change.
+                throw new IllegalStateException("Target already set!");
+            }
+
             node.addAnimator(this);
             mTarget = new WeakReference<RenderNode>(node);
             return true;
@@ -1067,8 +1081,12 @@
                 return;
             }
 
+            if (mStarted) {
+                return;
+            }
+
             if (!useLastSeenTarget()) {
-                mPendingAnimationAction = START_ANIMATION;
+                mAnimationPending = true;
                 return;
             }
 
@@ -1076,45 +1094,38 @@
                 Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
             }
 
-            mStarted = true;
-            nStart(mSetPtr, this, ++mLastListenerId);
+           nStart(mSetPtr, this);
             if (mListener != null) {
                 mListener.onAnimationStart(null);
             }
+            mStarted = true;
         }
 
         public void end() {
-            if (mInitialized && useLastSeenTarget()) {
-                // If no target has ever been set, no-op
+            if (mInitialized && mStarted) {
                 nEnd(mSetPtr);
+                onAnimationEnd();
             }
         }
 
-        public void reset() {
-            if (mInitialized && useLastSeenTarget()) {
-                // If no target has ever been set, no-op
-                nReset(mSetPtr);
+        void reset() {
+            if (!mInitialized) {
+                return;
             }
+            // TODO: Need to implement reset.
+            Log.w(LOGTAG, "Reset is yet to be implemented");
+            nReset(mSetPtr);
         }
 
         // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
         // animators or when the animator set has a start delay
         void reverse() {
-            if (!mIsReversible || !mInitialized) {
+            if (!mIsReversible) {
                 return;
             }
-            if (!useLastSeenTarget()) {
-                mPendingAnimationAction = REVERSE_ANIMATION;
-                return;
-            }
-            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
-            }
-            mStarted = true;
-            nReverse(mSetPtr, this, ++mLastListenerId);
-            if (mListener != null) {
-                mListener.onAnimationStart(null);
-            }
+            // TODO: Need to support reverse (non-public API)
+            Log.w(LOGTAG, "Reverse is yet to be implemented");
+            nReverse(mSetPtr, this);
         }
 
         public long getAnimatorNativePtr() {
@@ -1144,13 +1155,7 @@
             mListener = null;
         }
 
-        private void onAnimationEnd(int listenerId) {
-            if (listenerId != mLastListenerId) {
-                return;
-            }
-            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
-                Log.d(LOGTAG, "on finished called from native");
-            }
+        private void onAnimationEnd() {
             mStarted = false;
             if (mListener != null) {
                 mListener.onAnimationEnd(null);
@@ -1159,8 +1164,11 @@
         }
 
         // onFinished: should be called from native
-        private static void callOnFinished(VectorDrawableAnimator set, int id) {
-            set.onAnimationEnd(id);
+        private static void callOnFinished(VectorDrawableAnimator set) {
+            if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                Log.d(LOGTAG, "on finished called from native");
+            }
+            set.onAnimationEnd();
         }
     }
 
@@ -1180,8 +1188,8 @@
     private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
             float endValue);
     private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
-    private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set, int id);
-    private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set, int id);
+    private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set);
+    private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set);
     private static native void nEnd(long animatorSetPtr);
     private static native void nReset(long animatorSetPtr);
 }
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 372bcb3..7bd2b24 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -42,8 +42,7 @@
         , mStartTime(0)
         , mDuration(300)
         , mStartDelay(0)
-        , mMayRunAsync(true)
-        , mPlayTime(0) {
+        , mMayRunAsync(true) {
 }
 
 BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
@@ -86,113 +85,20 @@
     onAttached();
 }
 
-void BaseRenderNodeAnimator::start() {
-    mStagingPlayState = PlayState::Running;
-    mStagingRequests.push_back(Request::Start);
-    onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::cancel() {
-    mStagingPlayState = PlayState::Finished;
-    mStagingRequests.push_back(Request::Cancel);
-    onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::reset() {
-    mStagingPlayState = PlayState::Finished;
-    mStagingRequests.push_back(Request::Reset);
-    onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::reverse() {
-    mStagingPlayState = PlayState::Reversing;
-    mStagingRequests.push_back(Request::Reverse);
-    onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::end() {
-    mStagingPlayState = PlayState::Finished;
-    mStagingRequests.push_back(Request::End);
-    onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
-    switch (request) {
-    case Request::Start:
-        mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
-                        mPlayTime : 0;
-        mPlayState = PlayState::Running;
-        break;
-    case Request::Reverse:
-        mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
-                        mPlayTime : mDuration;
-        mPlayState = PlayState::Reversing;
-        break;
-    case Request::Reset:
-        mPlayTime = 0;
-        mPlayState = PlayState::Finished;
-        break;
-    case Request::Cancel:
-        mPlayState = PlayState::Finished;
-        break;
-    case Request::End:
-        mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
-        mPlayState = PlayState::Finished;
-        break;
-    default:
-        LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
-    };
-}
-
 void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
     if (!mHasStartValue) {
         doSetStartValue(getValue(mTarget));
     }
-
-    if (!mStagingRequests.empty()) {
-        // Keep track of the play state and play time before they are changed when
-        // staging requests are resolved.
-        nsecs_t currentPlayTime = mPlayTime;
-        PlayState prevFramePlayState = mPlayState;
-
-        // Resolve staging requests one by one.
-        for (Request request : mStagingRequests) {
-            resolveStagingRequest(request);
+    if (mStagingPlayState > mPlayState) {
+        if (mStagingPlayState == PlayState::Restarted) {
+            mStagingPlayState = PlayState::Running;
         }
-        mStagingRequests.clear();
-
-        if (mStagingPlayState == PlayState::Finished) {
-            // Set the staging play time and end the animation
-            updatePlayTime(mPlayTime);
+        mPlayState = mStagingPlayState;
+        // Oh boy, we're starting! Man the battle stations!
+        if (mPlayState == PlayState::Running) {
+            transitionToRunning(context);
+        } else if (mPlayState == PlayState::Finished) {
             callOnFinishedListener(context);
-        } else if (mStagingPlayState == PlayState::Running
-                || mStagingPlayState == PlayState::Reversing) {
-            bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
-            if (prevFramePlayState != mStagingPlayState) {
-                transitionToRunning(context);
-            }
-            if (changed) {
-                // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was
-                // requested from UI thread). It is achieved by modifying mStartTime, such that
-                // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the
-                // case of reversing)
-                nsecs_t currentFrameTime = context.frameTimeMs();
-                if (mPlayState == PlayState::Reversing) {
-                    // Reverse is not supported for animations with a start delay, so here we
-                    // assume no start delay.
-                    mStartTime = currentFrameTime  - (mDuration - mPlayTime);
-                } else {
-                    // Animation should play forward
-                    if (mPlayTime == 0) {
-                        // If the request is to start from the beginning, include start delay.
-                        mStartTime = currentFrameTime + mStartDelay;
-                    } else {
-                        // If the request is to seek to a non-zero play time, then we skip start
-                        // delay.
-                        mStartTime = currentFrameTime - mPlayTime;
-                    }
-                }
-            }
         }
     }
 }
@@ -230,37 +136,37 @@
 
     // This should be set before setValue() so animators can query this time when setValue
     // is called.
-    nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime;
-    bool finished = updatePlayTime(currentPlayTime);
-    if (finished && mPlayState != PlayState::Finished) {
-        mPlayState = PlayState::Finished;
-        callOnFinishedListener(context);
-    }
-    return finished;
-}
+    nsecs_t currentFrameTime = context.frameTimeMs();
+    onPlayTimeChanged(currentFrameTime - mStartTime);
 
-bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
-    mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime;
-    onPlayTimeChanged(mPlayTime);
     // If BaseRenderNodeAnimator is handling the delay (not typical), then
     // because the staging properties reflect the final value, we always need
     // to call setValue even if the animation isn't yet running or is still
     // being delayed as we need to override the staging value
-    if (playTime < 0) {
+    if (mStartTime > context.frameTimeMs()) {
         setValue(mTarget, mFromValue);
         return false;
     }
 
     float fraction = 1.0f;
-    if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
-        fraction = mPlayTime / (float) mDuration;
+
+    if (mPlayState == PlayState::Running && mDuration > 0) {
+        fraction = (float)(currentFrameTime - mStartTime) / mDuration;
     }
-    fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
+    if (fraction >= 1.0f) {
+        fraction = 1.0f;
+        mPlayState = PlayState::Finished;
+    }
 
     fraction = mInterpolator->interpolate(fraction);
     setValue(mTarget, mFromValue + (mDeltaValue * fraction));
 
-    return playTime >= mDuration;
+    if (mPlayState == PlayState::Finished) {
+        callOnFinishedListener(context);
+        return true;
+    }
+
+    return false;
 }
 
 void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index fcbc11b..2c9c9c3 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -24,8 +24,6 @@
 
 #include "utils/Macros.h"
 
-#include <vector>
-
 namespace android {
 namespace uirenderer {
 
@@ -61,14 +59,14 @@
         mMayRunAsync = mayRunAsync;
     }
     bool mayRunAsync() { return mMayRunAsync; }
-    ANDROID_API void start();
-    ANDROID_API void reset();
-    ANDROID_API void reverse();
-    // Terminates the animation at its current progress.
-    ANDROID_API void cancel();
-
-    // Terminates the animation and skip to the end of the animation.
-    ANDROID_API void end();
+    ANDROID_API void start() {
+        if (mStagingPlayState == PlayState::NotStarted) {
+            mStagingPlayState = PlayState::Running;
+        } else {
+            mStagingPlayState = PlayState::Restarted;
+        }
+        onStagingPlayStateChanged(); }
+    ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
 
     void attach(RenderNode* target);
     virtual void onAttached() {}
@@ -76,41 +74,36 @@
     void pushStaging(AnimationContext& context);
     bool animate(AnimationContext& context);
 
-    bool isRunning() { return mPlayState == PlayState::Running
-            || mPlayState == PlayState::Reversing; }
+    bool isRunning() { return mPlayState == PlayState::Running; }
     bool isFinished() { return mPlayState == PlayState::Finished; }
     float finalValue() { return mFinalValue; }
 
     ANDROID_API virtual uint32_t dirtyMask() = 0;
 
     void forceEndNow(AnimationContext& context);
-    RenderNode* target() { return mTarget; }
 
 protected:
     // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI
     // thread and Render Thread animation state, respectively.
     // From the UI thread, mStagingPlayState transition looks like
-    // NotStarted -> Running/Reversing -> Finished
-    //                ^                     |
-    //                |                     |
-    //                ----------------------
+    // NotStarted -> Running -> Finished
+    //                ^            |
+    //                |            |
+    //            Restarted <------
     // Note: For mStagingState, the Finished state (optional) is only set when the animation is
     // terminated by user.
     //
     // On Render Thread, mPlayState transition:
-    // NotStart -> Running/Reversing-> Finished
-    //                ^                 |
-    //                |                 |
-    //                ------------------
-    // Note that if the animation is in Running/Reversing state, calling start or reverse again
-    // would do nothing if the animation has the same play direction as the request; otherwise,
-    // the animation would start from where it is and change direction (i.e. Reversing <-> Running)
+    // NotStart -> Running -> Finished
+    //                ^            |
+    //                |            |
+    //                -------------
 
     enum class PlayState {
         NotStarted,
         Running,
-        Reversing,
         Finished,
+        Restarted,
     };
 
     BaseRenderNodeAnimator(float finalValue);
@@ -118,6 +111,7 @@
 
     virtual float getValue(RenderNode* target) const = 0;
     virtual void setValue(RenderNode* target, float value) = 0;
+    RenderNode* target() { return mTarget; }
 
     void callOnFinishedListener(AnimationContext& context);
 
@@ -138,28 +132,13 @@
     nsecs_t mDuration;
     nsecs_t mStartDelay;
     bool mMayRunAsync;
-    // Play Time tracks the progress of animation, it should always be [0, mDuration], 0 being
-    // the beginning of the animation, will reach mDuration at the end of an animation.
-    nsecs_t mPlayTime;
 
     sp<AnimationListener> mListener;
 
 private:
-    enum class Request {
-        Start,
-        Reverse,
-        Reset,
-        Cancel,
-        End
-    };
     inline void checkMutable();
     virtual void transitionToRunning(AnimationContext& context);
     void doSetStartValue(float value);
-    bool updatePlayTime(nsecs_t playTime);
-    void resolveStagingRequest(Request request);
-
-    std::vector<Request> mStagingRequests;
-
 };
 
 class RenderPropertyAnimator : public BaseRenderNodeAnimator {
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 2b49b47..cd30b18 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -27,8 +27,9 @@
 
 using namespace std;
 
-static void detach(sp<BaseRenderNodeAnimator>& animator) {
+static void unref(BaseRenderNodeAnimator* animator) {
     animator->detach();
+    animator->decStrong(nullptr);
 }
 
 AnimatorManager::AnimatorManager(RenderNode& parent)
@@ -37,12 +38,14 @@
 }
 
 AnimatorManager::~AnimatorManager() {
-    for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
-    for_each(mAnimators.begin(), mAnimators.end(), detach);
+    for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
+    for_each(mAnimators.begin(), mAnimators.end(), unref);
 }
 
 void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
-    mNewAnimators.emplace_back(animator.get());
+    animator->incStrong(nullptr);
+    animator->attach(&mParent);
+    mNewAnimators.push_back(animator.get());
 }
 
 void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
@@ -53,31 +56,25 @@
             &mParent, mParent.getName());
 }
 
+template<typename T>
+static void move_all(T& source, T& dest) {
+    dest.reserve(source.size() + dest.size());
+    for (typename T::iterator it = source.begin(); it != source.end(); it++) {
+        dest.push_back(*it);
+    }
+    source.clear();
+}
+
 void AnimatorManager::pushStaging() {
     if (mNewAnimators.size()) {
         LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
                 "Trying to start new animators on %p (%s) without an animation handle!",
                 &mParent, mParent.getName());
-        // Only add animators that are not already in the on-going animator list.
-        for (auto& animator : mNewAnimators) {
-            RenderNode* targetRenderNode = animator->target();
-            if (targetRenderNode == &mParent) {
-                // Animator already in the animator list: skip adding again
-                continue;
-            }
-
-            if (targetRenderNode){
-                // If the animator is already in another RenderNode's animator list, remove animator from
-                // that list and add animator to current RenderNode's list.
-                targetRenderNode->animators().removeActiveAnimator(animator);
-            }
-            animator->attach(&mParent);
-            mAnimators.push_back(std::move(animator));
-        }
-        mNewAnimators.clear();
+        // Since this is a straight move, we don't need to inc/dec the ref count
+        move_all(mNewAnimators, mAnimators);
     }
-    for (auto& animator : mAnimators) {
-        animator->pushStaging(mAnimationHandle->context());
+    for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
+        (*it)->pushStaging(mAnimationHandle->context());
     }
 }
 
@@ -86,11 +83,11 @@
     AnimateFunctor(TreeInfo& info, AnimationContext& context)
             : dirtyMask(0), mInfo(info), mContext(context) {}
 
-    bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+    bool operator() (BaseRenderNodeAnimator* animator) {
         dirtyMask |= animator->dirtyMask();
         bool remove = animator->animate(mContext);
         if (remove) {
-            animator->detach();
+            animator->decStrong(nullptr);
         } else {
             if (animator->isRunning()) {
                 mInfo.out.hasAnimations = true;
@@ -132,18 +129,20 @@
 
 uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
     AnimateFunctor functor(info, mAnimationHandle->context());
-    auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
+    std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
+    newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
     mAnimators.erase(newEnd, mAnimators.end());
     mAnimationHandle->notifyAnimationsRan();
     mParent.mProperties.updateMatrix();
     return functor.dirtyMask;
 }
 
-static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
-    animator->cancel();
+static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
+    animator->end();
     if (animator->listener()) {
-        animator->listener()->onAnimationFinished(animator.get());
+        animator->listener()->onAnimationFinished(animator);
     }
+    animator->decStrong(nullptr);
 }
 
 void AnimatorManager::endAllStagingAnimators() {
@@ -154,16 +153,13 @@
     mNewAnimators.clear();
 }
 
-void AnimatorManager::removeActiveAnimator(const sp<BaseRenderNodeAnimator>& animator) {
-    std::remove(mAnimators.begin(), mAnimators.end(), animator);
-}
-
 class EndActiveAnimatorsFunctor {
 public:
     EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
 
-    void operator() (sp<BaseRenderNodeAnimator>& animator) {
+    void operator() (BaseRenderNodeAnimator* animator) {
         animator->forceEndNow(mContext);
+        animator->decStrong(nullptr);
     }
 
 private:
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
index c24ef47..fb75eb8 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -62,17 +62,13 @@
 private:
     uint32_t animateCommon(TreeInfo& info);
 
-    // This would remove the animator from mAnimators list. It should only be called during
-    // push staging.
-    void removeActiveAnimator(const sp<BaseRenderNodeAnimator>& animator);
-
     RenderNode& mParent;
     AnimationHandle* mAnimationHandle;
 
     // To improve the efficiency of resizing & removing from the vector
     // use manual ref counting instead of sp<>.
-    std::vector< sp<BaseRenderNodeAnimator> > mNewAnimators;
-    std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
+    std::vector<BaseRenderNodeAnimator*> mNewAnimators;
+    std::vector<BaseRenderNodeAnimator*> mAnimators;
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
index b29f91f..eca1afcc 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -17,8 +17,6 @@
 #include "PropertyValuesAnimatorSet.h"
 #include "RenderNode.h"
 
-#include <algorithm>
-
 namespace android {
 namespace uirenderer {
 
@@ -55,26 +53,16 @@
 }
 
 void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
-    if (playTime == 0 && mDuration > 0) {
-        // Reset all the animators
-        for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) {
-            // Note that this set may containing animators modifying the same property, so when we
-            // reset the animators, we need to make sure the animators that end the first will
-            // have the final say on what the property value should be.
-            (*it)->setFraction(0);
-        }
-    } else if (playTime >= mDuration) {
-        // Skip all the animators to end
-        for (auto& anim : mAnimators) {
-            anim->setFraction(1);
-        }
-    } else {
-        for (auto& anim : mAnimators) {
-            anim->setCurrentPlayTime(playTime);
-        }
+    for (size_t i = 0; i < mAnimators.size(); i++) {
+        mAnimators[i]->setCurrentPlayTime(playTime);
     }
 }
 
+void PropertyValuesAnimatorSet::reset() {
+    // TODO: implement reset through adding a play state because we need to support reset() even
+    // during an animation run.
+}
+
 void PropertyValuesAnimatorSet::start(AnimationListener* listener) {
     init();
     mOneShotListener = listener;
@@ -82,23 +70,20 @@
 }
 
 void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) {
-    init();
-    mOneShotListener = listener;
-    BaseRenderNodeAnimator::reverse();
+// TODO: implement reverse
 }
 
 void PropertyValuesAnimatorSet::init() {
     if (mInitialized) {
         return;
     }
-
-    // Sort the animators by their total duration. Note that all the animators in the set start at
-    // the same time, so the ones with longer total duration (which includes start delay) will
-    // be the ones that end later.
-    std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) {
-        return a->getTotalDuration() < b->getTotalDuration();
-    });
-    mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration();
+    nsecs_t maxDuration = 0;
+    for (size_t i = 0; i < mAnimators.size(); i++) {
+        if (maxDuration < mAnimators[i]->getTotalDuration()) {
+            maxDuration = mAnimators[i]->getTotalDuration();
+        }
+    }
+    mDuration = maxDuration;
     mInitialized = true;
 }
 
@@ -121,19 +106,18 @@
 void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
     if (playTime >= mStartDelay && playTime < mTotalDuration) {
          nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration;
-         float fraction = currentIterationPlayTime / (float) mDuration;
-         setFraction(fraction);
+         mLatestFraction = currentIterationPlayTime / (float) mDuration;
     } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) {
-        // This makes sure we only set the fraction = 1 once. It is needed because there might
-        // be another animator modifying the same property after this animator finishes, we need
-        // to make sure we don't set conflicting values on the same property within one frame.
-        setFraction(1.0f);
+        mLatestFraction = 1.0f;
+    } else {
+        return;
     }
+
+    setFraction(mLatestFraction);
 }
 
 void PropertyAnimator::setFraction(float fraction) {
-    mLatestFraction = fraction;
-    float interpolatedFraction = mInterpolator->interpolate(fraction);
+    float interpolatedFraction = mInterpolator->interpolate(mLatestFraction);
     mPropertyValuesHolder->setFraction(interpolatedFraction);
 }
 
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index c7ae7c0..4c7ce52 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -50,6 +50,7 @@
 
     void start(AnimationListener* listener);
     void reverse(AnimationListener* listener);
+    void reset();
 
     void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
             Interpolator* interpolators, int64_t startDelays,
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index d8f507c..a490685 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -28,7 +28,7 @@
  */
 public final class GnssMeasurement implements Parcelable {
     private int mFlags;
-    private byte mPrn;
+    private short mSvid;
     private double mTimeOffsetInNs;
     private short mState;
     private long mReceivedGpsTowInNs;
@@ -198,7 +198,7 @@
      */
     public void set(GnssMeasurement measurement) {
         mFlags = measurement.mFlags;
-        mPrn = measurement.mPrn;
+        mSvid = measurement.mSvid;
         mTimeOffsetInNs = measurement.mTimeOffsetInNs;
         mState = measurement.mState;
         mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs;
@@ -248,15 +248,15 @@
      * Gets the Pseudo-random number (PRN).
      * Range: [1, 32]
      */
-    public byte getPrn() {
-        return mPrn;
+    public short getSvid() {
+        return mSvid;
     }
 
     /**
      * Sets the Pseud-random number (PRN).
      */
-    public void setPrn(byte value) {
-        mPrn = value;
+    public void setSvid(short value) {
+        mSvid = value;
     }
 
     /**
@@ -1210,7 +1210,7 @@
             GnssMeasurement gnssMeasurement = new GnssMeasurement();
 
             gnssMeasurement.mFlags = parcel.readInt();
-            gnssMeasurement.mPrn = parcel.readByte();
+            gnssMeasurement.mSvid = (short) parcel.readInt();
             gnssMeasurement.mTimeOffsetInNs = parcel.readDouble();
             gnssMeasurement.mState = (short) parcel.readInt();
             gnssMeasurement.mReceivedGpsTowInNs = parcel.readLong();
@@ -1253,9 +1253,10 @@
         }
     };
 
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mFlags);
-        parcel.writeByte(mPrn);
+        parcel.writeInt(mSvid);
         parcel.writeDouble(mTimeOffsetInNs);
         parcel.writeInt(mState);
         parcel.writeLong(mReceivedGpsTowInNs);
@@ -1301,7 +1302,7 @@
         final String formatWithUncertainty = "   %-29s = %-25s   %-40s = %s\n";
         StringBuilder builder = new StringBuilder("GnssMeasurement:\n");
 
-        builder.append(String.format(format, "Prn", mPrn));
+        builder.append(String.format(format, "Svid", mSvid));
 
         builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
 
@@ -1422,7 +1423,7 @@
 
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
-        setPrn(Byte.MIN_VALUE);
+        setSvid((short) 0);
         setTimeOffsetInNs(Long.MIN_VALUE);
         setState(STATE_UNKNOWN);
         setReceivedGpsTowInNs(Long.MIN_VALUE);
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index 0e011d5..86328eb 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -26,7 +26,7 @@
 import java.security.InvalidParameterException;
 
 /**
- * A class containing a GPS satellite Navigation Message.
+ * A class containing a GNSS satellite Navigation Message.
  */
 public final class GnssNavigationMessage implements Parcelable {
 
@@ -84,7 +84,7 @@
     // End enumerations in sync with gps.h
 
     private byte mType;
-    private byte mPrn;
+    private short mSvid;
     private short mMessageId;
     private short mSubmessageId;
     private byte[] mData;
@@ -99,7 +99,7 @@
      */
     public void set(GnssNavigationMessage navigationMessage) {
         mType = navigationMessage.mType;
-        mPrn = navigationMessage.mPrn;
+        mSvid = navigationMessage.mSvid;
         mMessageId = navigationMessage.mMessageId;
         mSubmessageId = navigationMessage.mSubmessageId;
         mData = navigationMessage.mData;
@@ -153,15 +153,15 @@
      * Gets the Pseudo-random number.
      * Range: [1, 32].
      */
-    public byte getPrn() {
-        return mPrn;
+    public short getSvid() {
+        return mSvid;
     }
 
     /**
      * Sets the Pseud-random number.
      */
-    public void setPrn(byte value) {
-        mPrn = value;
+    public void setSvid(short value) {
+        mSvid = value;
     }
 
     /**
@@ -256,7 +256,7 @@
             GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
 
             navigationMessage.setType(parcel.readByte());
-            navigationMessage.setPrn(parcel.readByte());
+            navigationMessage.setSvid((short) parcel.readInt());
             navigationMessage.setMessageId((short) parcel.readInt());
             navigationMessage.setSubmessageId((short) parcel.readInt());
 
@@ -281,9 +281,10 @@
         }
     };
 
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeByte(mType);
-        parcel.writeByte(mPrn);
+        parcel.writeInt(mSvid);
         parcel.writeInt(mMessageId);
         parcel.writeInt(mSubmessageId);
         parcel.writeInt(mData.length);
@@ -302,7 +303,7 @@
         StringBuilder builder = new StringBuilder("GnssNavigationMessage:\n");
 
         builder.append(String.format(format, "Type", getTypeString()));
-        builder.append(String.format(format, "Prn", mPrn));
+        builder.append(String.format(format, "Svid", mSvid));
         builder.append(String.format(format, "Status", getStatusString()));
         builder.append(String.format(format, "MessageId", mMessageId));
         builder.append(String.format(format, "SubmessageId", mSubmessageId));
@@ -321,7 +322,7 @@
 
     private void initialize() {
         mType = MESSAGE_TYPE_UNKNOWN;
-        mPrn = 0;
+        mSvid = 0;
         mMessageId = -1;
         mSubmessageId = -1;
         mData = EMPTY_ARRAY;
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 77e8a5b..906e944 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -47,24 +47,26 @@
     public static final int GNSS_SV_FLAGS_USED_IN_FIX = (1 << 2);
 
     /** @hide */
-    public static final int PRN_SHIFT_WIDTH = 3;
+    public static final int SVID_SHIFT_WIDTH = 7;
+    /** @hide */
+    public static final int CONSTELLATION_TYPE_SHIFT_WIDTH = 3;
+    /** @hide */
+    public static final int CONSTELLATION_TYPE_MASK = 0xf;
 
     /* These package private values are modified by the LocationManager class */
-    /* package */ int[] mPrnWithFlags;
+    /* package */ int[] mSvidWithFlags;
     /* package */ float[] mSnrs;
     /* package */ float[] mElevations;
     /* package */ float[] mAzimuths;
-    /* package */ int[] mConstellationTypes;
     /* package */ int mSvCount;
 
-    GnssStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations, float[] azimuths,
-            int[] constellationTypes) {
+    GnssStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+            float[] azimuths) {
         mSvCount = svCount;
-        mPrnWithFlags = prnWithFlags;
+        mSvidWithFlags = svidWithFlags;
         mSnrs = snrs;
         mElevations = elevations;
         mAzimuths = azimuths;
-        mConstellationTypes = constellationTypes;
     }
 
     /**
@@ -79,15 +81,16 @@
      * @param satIndex the index of the satellite in the list.
      */
     public int getConstellationType(int satIndex) {
-        return mConstellationTypes[satIndex];
+        return (mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
+                & CONSTELLATION_TYPE_MASK;
     }
 
     /**
      * Retrieves the pseudo-random number of the satellite at the specified position.
      * @param satIndex the index of the satellite in the list.
      */
-    public int getPrn(int satIndex) {
-        return mPrnWithFlags[satIndex] >> PRN_SHIFT_WIDTH;
+    public int getSvid(int satIndex) {
+        return mSvidWithFlags[satIndex] >> SVID_SHIFT_WIDTH;
     }
 
     /**
@@ -119,7 +122,7 @@
      * @param satIndex the index of the satellite in the list.
      */
     public boolean hasEphemeris(int satIndex) {
-        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
     }
 
     /**
@@ -127,7 +130,7 @@
      * @param satIndex the index of the satellite in the list.
      */
     public boolean hasAlmanac(int satIndex) {
-        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
+        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
     }
 
     /**
@@ -135,6 +138,6 @@
      * @param satIndex the index of the satellite in the list.
      */
     public boolean usedInFix(int satIndex) {
-        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_USED_IN_FIX) != 0;
+        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_USED_IN_FIX) != 0;
     }
 }
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 8d2f781..e41e20c 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -138,15 +138,19 @@
     // For API-compat a public ctor() is not available
     GpsStatus() {}
 
-    private void setStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations,
-            float[] azimuths, int[] constellationTypes) { 
+    private void setStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+            float[] azimuths) {
         clearSatellites();
         for (int i = 0; i < svCount; i++) {
+            final int constellationType =
+                    (svidWithFlags[i] >> GnssStatus.CONSTELLATION_TYPE_SHIFT_WIDTH)
+                    & GnssStatus.CONSTELLATION_TYPE_MASK;
             // Skip all non-GPS satellites.
-            if (constellationTypes[i] != GnssStatus.CONSTELLATION_GPS) {
+            if (constellationType != GnssStatus.CONSTELLATION_GPS) {
+                // TODO: translate the defacto pre-N use of  prn's >32 to new struct
                 continue;
             }
-            int prn = prnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH;
+            int prn = svidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH;
             if (prn > 0 && prn <= NUM_SATELLITES) {
                 GpsSatellite satellite = mSatellites.get(prn);
                 if (satellite == null) {
@@ -159,11 +163,11 @@
                 satellite.mElevation = elevations[i];
                 satellite.mAzimuth = azimuths[i];
                 satellite.mHasEphemeris =
-                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+                        (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
                 satellite.mHasAlmanac =
-                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
+                        (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
                 satellite.mUsedInFix =
-                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0;
+                        (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0;
             }
         }
     }
@@ -176,8 +180,8 @@
      */
     void setStatus(GnssStatus status, int timeToFirstFix) {
         mTimeToFirstFix = timeToFirstFix;
-        setStatus(status.mSvCount, status.mPrnWithFlags, status.mSnrs, status.mElevations,
-                status.mAzimuths, status.mConstellationTypes);
+        setStatus(status.mSvCount, status.mSvidWithFlags, status.mSnrs, status.mElevations,
+                status.mAzimuths);
     }
 
     void setTimeToFirstFix(int ttff) {
diff --git a/location/java/android/location/IGnssStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl
index d1c6a85..8c7d06e 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[] prnWithFlags, in float[] snrs,
-            in float[] elevations, in float[] azimuths, in int[] constellationTypes);
+    void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] snrs,
+            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 30cf101..23f0710 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1562,10 +1562,9 @@
 
         @Override
         public void onSvStatusChanged(int svCount, int[] prnWithFlags,
-                float[] snrs, float[] elevations, float[] azimuths, int[] constellationTypes) {
+                float[] snrs, float[] elevations, float[] azimuths) {
             if (mGnssCallback != null) {
-                mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths,
-                        constellationTypes);
+                mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths);
 
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 726538e..f8735b2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -101,7 +101,6 @@
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperationService.OpType;
 import com.android.documentsui.services.FileOperations;
-
 import com.google.common.collect.Lists;
 
 import java.lang.annotation.Retention;
@@ -194,6 +193,11 @@
 
         mRecView.setItemAnimator(new DirectoryItemAnimator(getActivity()));
 
+        // Make the RecyclerView unfocusable. This is needed in order for the focus search code in
+        // FocusManager to work correctly. Setting android:focusable=false in the layout xml doesn't
+        // work, for some reason.
+        mRecView.setFocusable(false);
+
         // TODO: Add a divider between views (which might use RecyclerView.ItemDecoration).
         if (DEBUG_ENABLE_DND) {
             setupDragAndDropOnDirectoryView(mRecView);
@@ -264,7 +268,7 @@
         mSelectionManager.addCallback(selectionListener);
 
         // Make sure this is done after the RecyclerView is set up.
-        mFocusManager = new FocusManager(mRecView, mSelectionManager);
+        mFocusManager = new FocusManager(mRecView);
 
         mModel = new Model();
         mModel.addUpdateListener(mAdapter);
@@ -1262,16 +1266,37 @@
             }
 
             if (mFocusManager.handleKey(doc, keyCode, event)) {
+                // Handle range selection adjustments. Extending the selection will adjust the
+                // bounds of the in-progress range selection. Each time an unshifted navigation
+                // event is received, the range selection is restarted.
+                if (shouldExtendSelection(event)) {
+                    if (!mSelectionManager.isRangeSelectionActive()) {
+                        // Start a range selection if one isn't active
+                        mSelectionManager.startRangeSelection(doc.getAdapterPosition());
+                    }
+                    mSelectionManager.snapRangeSelection(mFocusManager.getFocusPosition());
+                } else {
+                    mSelectionManager.endRangeSelection();
+                }
                 return true;
             }
 
             // Handle enter key events
             if (keyCode == KeyEvent.KEYCODE_ENTER) {
-                return onActivate(doc);
+                if (event.isShiftPressed()) {
+                    return onSelect(doc);
+                } else {
+                    return onActivate(doc);
+                }
             }
 
             return false;
         }
+
+        private boolean shouldExtendSelection(KeyEvent event) {
+            return Events.isNavigationKeyCode(event.getKeyCode()) &&
+                    event.isShiftPressed();
+        }
     }
 
     private final class ModelUpdateListener implements Model.UpdateListener {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
index ad010a6..93ec842 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
@@ -16,7 +16,7 @@
 
 package com.android.documentsui.dirlist;
 
-import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -32,16 +32,14 @@
 
     private RecyclerView mView;
     private RecyclerView.Adapter<?> mAdapter;
-    private LinearLayoutManager mLayout;
-    private MultiSelectManager mSelectionManager;
+    private GridLayoutManager mLayout;
 
     private int mLastFocusPosition = RecyclerView.NO_POSITION;
 
-    public FocusManager(RecyclerView view, MultiSelectManager selectionManager) {
+    public FocusManager(RecyclerView view) {
         mView = view;
         mAdapter = view.getAdapter();
-        mLayout = (LinearLayoutManager) view.getLayoutManager();
-        mSelectionManager = selectionManager;
+        mLayout = (GridLayoutManager) view.getLayoutManager();
     }
 
     /**
@@ -54,19 +52,24 @@
      * @return Whether the event was handled.
      */
     public boolean handleKey(DocumentHolder doc, int keyCode, KeyEvent event) {
+        boolean extendSelection = false;
+        // Translate space/shift-space into PgDn/PgUp
+        if (keyCode == KeyEvent.KEYCODE_SPACE) {
+            if (event.isShiftPressed()) {
+                keyCode = KeyEvent.KEYCODE_PAGE_UP;
+            } else {
+                keyCode = KeyEvent.KEYCODE_PAGE_DOWN;
+            }
+        } else {
+            extendSelection = event.isShiftPressed();
+        }
+
         if (Events.isNavigationKeyCode(keyCode)) {
             // Find the target item and focus it.
             int endPos = findTargetPosition(doc.itemView, keyCode, event);
 
             if (endPos != RecyclerView.NO_POSITION) {
                 focusItem(endPos);
-                boolean extendSelection = event.isShiftPressed();
-
-                // Handle any necessary adjustments to selection.
-                if (extendSelection) {
-                    int startPos = doc.getAdapterPosition();
-                    mSelectionManager.selectRange(startPos, endPos);
-                }
             }
             // Swallow all navigation keystrokes. Otherwise they go to the app's global
             // key-handler, which will route them back to the DF and cause focus to be reset.
@@ -97,6 +100,13 @@
     }
 
     /**
+     * @return The adapter position of the last focused item.
+     */
+    public int getFocusPosition() {
+        return mLastFocusPosition;
+    }
+
+    /**
      * Finds the destination position where the focus should land for a given navigation event.
      *
      * @param view The view that received the event.
@@ -124,12 +134,27 @@
             case KeyEvent.KEYCODE_DPAD_DOWN:
                 searchDir = View.FOCUS_DOWN;
                 break;
-            case KeyEvent.KEYCODE_DPAD_LEFT:
-                searchDir = View.FOCUS_LEFT;
-                break;
-            case KeyEvent.KEYCODE_DPAD_RIGHT:
-                searchDir = View.FOCUS_RIGHT;
-                break;
+        }
+
+        if (inGridMode()) {
+            int currentPosition = mView.getChildAdapterPosition(view);
+            // Left and right arrow keys only work in grid mode.
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_DPAD_LEFT:
+                    if (currentPosition > 0) {
+                        // Stop backward focus search at the first item, otherwise focus will wrap
+                        // around to the last visible item.
+                        searchDir = View.FOCUS_BACKWARD;
+                    }
+                    break;
+                case KeyEvent.KEYCODE_DPAD_RIGHT:
+                    if (currentPosition < mAdapter.getItemCount() - 1) {
+                        // Stop forward focus search at the last item, otherwise focus will wrap
+                        // around to the first visible item.
+                        searchDir = View.FOCUS_FORWARD;
+                    }
+                    break;
+            }
         }
 
         if (searchDir != -1) {
@@ -228,4 +253,11 @@
                     });
         }
     }
+
+    /**
+     * @return Whether the layout manager is currently in a grid-configuration.
+     */
+    private boolean inGridMode() {
+        return mLayout.getSpanCount() > 1;
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index d60825b..c8b6f85 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -370,39 +370,41 @@
     }
 
     /**
-     * Handle a range selection event.
-     * <li> If the MSM is currently in single-select mode, only the last item in the range will
-     * actually be selected.
-     * <li>If a range selection is not already active, one will be started, and the given range of
-     * items will be selected.  The given startPos becomes the anchor for the range selection.
-     * <li>If a range selection is already active, the anchor is not changed. The range is extended
-     * from its current anchor to endPos.
+     * Starts a range selection. If a range selection is already active, this will start a new range
+     * selection (which will reset the range anchor).
      *
-     * @param startPos
-     * @param endPos
+     * @param pos The anchor position for the selection range.
      */
-    public void selectRange(int startPos, int endPos) {
-        // In single-select mode, just select the last item in the range.
-        if (mSingleSelect) {
-            attemptSelect(mAdapter.getModelId(endPos));
-            return;
-        }
+    void startRangeSelection(int pos) {
+      attemptSelect(mAdapter.getModelId(pos));
+      setSelectionRangeBegin(pos);
+    }
 
-        // In regular (i.e. multi-select) mode
-        if (!isRangeSelectionActive()) {
-            // If a range selection isn't active, start one up
-            attemptSelect(mAdapter.getModelId(startPos));
-            setSelectionRangeBegin(startPos);
-        }
-        // Extend the range selection
-        mRanger.snapSelection(endPos);
+    /**
+     * Sets the end point for the current range selection, started by a call to
+     * {@link #startRangeSelection(int)}. This function should only be called when a range selection
+     * is active (see {@link #isRangeSelectionActive()}. Items in the range [anchor, end] will be
+     * selected.
+     *
+     * @param pos The new end position for the selection range.
+     */
+    void snapRangeSelection(int pos) {
+        checkNotNull(mRanger);
+        mRanger.snapSelection(pos);
         notifySelectionChanged();
     }
 
     /**
+     * Stops an in-progress range selection.
+     */
+    void endRangeSelection() {
+        mRanger = null;
+    }
+
+    /**
      * @return Whether or not there is a current range selection active.
      */
-    private boolean isRangeSelectionActive() {
+    boolean isRangeSelectionActive() {
         return mRanger != null;
     }
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
index d95fb49..9447d9c1 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
@@ -189,6 +189,54 @@
         assertSelection(items.get(20));
     }
 
+    public void testRangeSelection() {
+        mManager.startRangeSelection(15);
+        mManager.snapRangeSelection(19);
+        assertRangeSelection(15, 19);
+    }
+
+    public void testRangeSelection_snapExpand() {
+        mManager.startRangeSelection(15);
+        mManager.snapRangeSelection(19);
+        mManager.snapRangeSelection(27);
+        assertRangeSelection(15, 27);
+    }
+
+    public void testRangeSelection_snapContract() {
+        mManager.startRangeSelection(15);
+        mManager.snapRangeSelection(27);
+        mManager.snapRangeSelection(19);
+        assertRangeSelection(15, 19);
+    }
+
+    public void testRangeSelection_snapInvert() {
+        mManager.startRangeSelection(15);
+        mManager.snapRangeSelection(27);
+        mManager.snapRangeSelection(3);
+        assertRangeSelection(3, 15);
+    }
+
+    public void testRangeSelection_multiple() {
+        mManager.startRangeSelection(15);
+        mManager.snapRangeSelection(27);
+        mManager.endRangeSelection();
+        mManager.startRangeSelection(42);
+        mManager.snapRangeSelection(57);
+        assertSelectionSize(29);
+        assertRangeSelected(15, 27);
+        assertRangeSelected(42, 57);
+
+    }
+
+    public void testRangeSelection_singleSelect() {
+        mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE, null);
+        mManager.addCallback(mCallback);
+        mManager.startRangeSelection(11);
+        mManager.snapRangeSelection(19);
+        assertSelectionSize(1);
+        assertSelection(items.get(19));
+    }
+
     public void testProvisionalSelection() {
         Selection s = mManager.getSelection();
         assertSelection();
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
index 73171c7..1d6197a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
@@ -65,7 +65,7 @@
     }
 
     public Tile getTile(int position) {
-        return mItems.get(position).tile;
+        return mItems.get(position) != null ? mItems.get(position).tile : null;
     }
 
     @Override
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 7149065..4c3b61b 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -3494,7 +3494,7 @@
          */
         int preflightFullBackup(PackageInfo pkg, IBackupAgent agent);
 
-        long expectedSize();
+        long getExpectedSizeOrErrorCode();
     };
 
     class FullBackupEngine {
@@ -4555,6 +4555,10 @@
                     // now wait to get our result back
                     mLatch.await();
                     int totalSize = mResult.get();
+                    // If preflight timeouted, mResult will contain error code.
+                    if (totalSize < 0) {
+                        return totalSize;
+                    }
                     if (MORE_DEBUG) {
                         Slog.v(TAG, "Got preflight response; size=" + totalSize);
                     }
@@ -4600,7 +4604,7 @@
             }
 
             @Override
-            public long expectedSize() {
+            public long getExpectedSizeOrErrorCode() {
                 try {
                     mLatch.await();
                     return mResult.get();
@@ -4649,7 +4653,7 @@
             }
 
             long expectedSize() {
-                return mPreflight.expectedSize();
+                return mPreflight.getExpectedSizeOrErrorCode();
             }
         }
     }
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index a4455e9..07d472d 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -882,6 +884,11 @@
 
     @Override
     public int checkAudioOperation(int code, int usage, int uid, String packageName) {
+        if (isApplicationSuspended(packageName, uid)) {
+            Log.i(TAG, "Audio disabled for suspended package=" + packageName + " for uid=" + uid);
+            return AppOpsManager.MODE_IGNORED;
+        }
+
         synchronized (this) {
             final int mode = checkRestrictionLocked(code, usage, uid, packageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
@@ -891,6 +898,23 @@
         return checkOperation(code, uid, packageName);
     }
 
+    private boolean isApplicationSuspended(String pkg, int uid) {
+        int userId = UserHandle.getUserId(uid);
+
+        ApplicationInfo ai;
+        try {
+            ai = AppGlobals.getPackageManager().getApplicationInfo(pkg, 0, userId);
+            if (ai == null) {
+                Log.w(TAG, "No application info for package " + pkg + " and user " + userId);
+                return false;
+            }
+        } catch (RemoteException re) {
+            throw new SecurityException("Could not talk to package manager service");
+        }
+
+        return ((ai.flags & FLAG_SUSPENDED) != 0);
+    }
+
     private int checkRestrictionLocked(int code, int usage, int uid, String packageName) {
         final SparseArray<Restriction> usageRestrictions = mAudioRestrictions.get(code);
         if (usageRestrictions != null) {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b984e19..879bb6f 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -234,12 +234,24 @@
             // safety as scores should never be compared across apps; in practice, Settings should
             // only be allowing valid apps to be set as scorers, so failure here should be rare.
             clearInternal();
+            // Get the scorer that is about to be replaced, if any, so we can notify it directly.
+            NetworkScorerAppData prevScorer = NetworkScorerAppManager.getActiveScorer(mContext);
             boolean result = NetworkScorerAppManager.setActiveScorer(mContext, packageName);
-            if (result) {
+            if (result) { // new scorer successfully set
                 registerPackageReceiverIfNeeded();
                 Intent intent = new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED);
-                intent.putExtra(NetworkScoreManager.EXTRA_NEW_SCORER, packageName);
-                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+                if (prevScorer != null) { // Directly notify the old scorer.
+                    intent.setPackage(prevScorer.mPackageName);
+                    // TODO: Need to update when we support per-user scorers. http://b/23422763
+                    mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+                }
+
+                if (packageName != null) { // Then notify the new scorer
+                    intent.putExtra(NetworkScoreManager.EXTRA_NEW_SCORER, packageName);
+                    intent.setPackage(packageName);
+                    // TODO: Need to update when we support per-user scorers. http://b/23422763
+                    mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+                }
             }
             return result;
         } finally {
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index bef6f0a..1b9d968 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -62,7 +62,7 @@
     static final boolean DEBUG_LRU = DEBUG_ALL || false;
     static final boolean DEBUG_MU = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
-    static final boolean DEBUG_PAUSE = DEBUG_ALL || true;
+    static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
     static final boolean DEBUG_POWER = DEBUG_ALL || false;
     static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
     static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false;
@@ -85,7 +85,7 @@
     static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false;
     static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
     static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false;
-    static final boolean DEBUG_VISIBILITY = DEBUG_ALL || true;
+    static final boolean DEBUG_VISIBILITY = DEBUG_ALL || false;
     static final boolean DEBUG_VISIBLE_BEHIND = DEBUG_ALL_ACTIVITIES || false;
     static final boolean DEBUG_USAGE_STATS = DEBUG_ALL || false;
     static final boolean DEBUG_PERMISSIONS_REVIEW = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ddba070..5061901 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -20802,7 +20802,7 @@
             pkgUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId);
         } catch (RemoteException e) {
         }
-        if (pkgUid == -1) {
+        if (userId != UserHandle.USER_ALL && pkgUid == -1) {
             throw new IllegalArgumentException(
                     "Cannot kill dependents of non-existing package " + packageName);
         }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 75dabc96..1103ea4 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -768,7 +768,6 @@
         r.state = ActivityState.RESUMED;
         if (DEBUG_STATES) Slog.v(TAG_STATES,
                 "Moving to RESUMED: " + r + " (starting new instance)");
-        r.stopped = false;
         mResumedActivity = r;
         r.task.touchActiveTime();
         mRecentTasks.addLocked(r.task);
@@ -1228,9 +1227,11 @@
      * this function updates the rest of our state to match that fact.
      */
     private void completeResumeLocked(ActivityRecord next) {
+        next.visible = true;
         next.idle = false;
         next.results = null;
         next.newIntents = null;
+        next.stopped = false;
 
         if (next.isHomeActivity()) {
             ProcessRecord app = next.task.mActivities.get(0).app;
@@ -1729,6 +1730,8 @@
 
         // This activity is not currently visible, but is running. Tell it to become visible.
         if (r.state == ActivityState.RESUMED || r == starting) {
+            Slog.d(TAG_VISIBILITY, "Not making visible, r=" + r + " state=" + r.state
+                    + " starting=" + starting);
             return;
         }
 
@@ -2291,7 +2294,6 @@
             // From this point on, if something goes wrong there is no way
             // to recover the activity.
             try {
-                next.visible = true;
                 completeResumeLocked(next);
             } catch (Exception e) {
                 // If any exception gets thrown, toss away this
@@ -2302,8 +2304,6 @@
                 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                 return true;
             }
-            next.stopped = false;
-
         } else {
             // Whoops, need to restart this activity!
             if (!next.hasBeenLaunched) {
@@ -4283,6 +4283,12 @@
                 // "restart!".
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                         "Config is relaunching resumed " + r);
+
+                if (DEBUG_STATES && !r.visible) {
+                    Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + r
+                            + " called by " + Debug.getCallers(4));
+                }
+
                 relaunchActivityLocked(r, r.configChangeFlags, true, preserveWindow);
             } else {
                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
@@ -4433,9 +4439,21 @@
         }
 
         if (andResume) {
-            r.results = null;
-            r.newIntents = null;
+            if (DEBUG_STATES) {
+                Slog.d(TAG_STATES, "Resumed after relaunch " + r);
+            }
             r.state = ActivityState.RESUMED;
+            // Relaunch-resume could happen either when the app is already in the front,
+            // or while it's being brought to front. In the latter case, it's marked RESUMED
+            // but not yet visible (or stopped). We need to complete the resume here as the
+            // code in resumeTopActivityInnerLocked to complete the resume might be skipped.
+            if (!r.visible || r.stopped) {
+                mWindowManager.setAppVisibility(r.appToken, true);
+                completeResumeLocked(r);
+            } else {
+                r.results = null;
+                r.newIntents = null;
+            }
         } else {
             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
             r.state = ActivityState.PAUSED;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 98a7ead..b45430d 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -70,6 +70,7 @@
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
@@ -122,9 +123,6 @@
     private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
     private static final String ATTR_CALLING_UID = "calling_uid";
     private static final String ATTR_CALLING_PACKAGE = "calling_package";
-    // TODO(b/26847884): Currently needed while migrating to resize_mode.
-    // Can be removed at some later point.
-    private static final String ATTR_RESIZEABLE = "resizeable";
     private static final String ATTR_RESIZE_MODE = "resize_mode";
     private static final String ATTR_PRIVILEGED = "privileged";
     private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
@@ -1169,7 +1167,7 @@
         int nextTaskId = INVALID_TASK_ID;
         int callingUid = -1;
         String callingPackage = "";
-        int resizeMode = RESIZE_MODE_UNRESIZEABLE;
+        int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
         boolean privileged = false;
         Rect bounds = null;
 
@@ -1231,11 +1229,10 @@
                 callingUid = Integer.valueOf(attrValue);
             } else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
                 callingPackage = attrValue;
-            } else if (ATTR_RESIZEABLE.equals(attrName)) {
-                resizeMode = Boolean.valueOf(attrValue)
-                        ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_CROP_WINDOWS;
             } else if (ATTR_RESIZE_MODE.equals(attrName)) {
                 resizeMode = Integer.valueOf(attrValue);
+                resizeMode = (resizeMode == RESIZE_MODE_CROP_WINDOWS)
+                        ? RESIZE_MODE_FORCE_RESIZEABLE : resizeMode;
             } else if (ATTR_PRIVILEGED.equals(attrName)) {
                 privileged = Boolean.valueOf(attrValue);
             } else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 8dec587..218e529 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -2546,6 +2546,7 @@
                             Slog.v(TAG, "Pushing back running sync due to a higher priority sync");
                         }
                         deferActiveSyncH(asc);
+                        break;
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index ffc52b3..c1eb844 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1557,15 +1557,13 @@
      * called from native code to update SV info
      */
     private void reportSvStatus() {
-        int svCount = native_read_sv_status(mPrnWithFlags, mSnrs, mSvElevations, mSvAzimuths,
-                mConstellationTypes);
+        int svCount = native_read_sv_status(mSvidWithFlags, mSnrs, mSvElevations, mSvAzimuths);
         mListenerHelper.onSvStatusChanged(
                 svCount,
-                mPrnWithFlags,
+                mSvidWithFlags,
                 mSnrs,
                 mSvElevations,
-                mSvAzimuths,
-                mConstellationTypes);
+                mSvAzimuths);
 
         if (VERBOSE) {
             Log.v(TAG, "SV count: " + svCount);
@@ -1573,19 +1571,19 @@
         // Calculate number of sets used in fix.
         int usedInFixCount = 0;
         for (int i = 0; i < svCount; i++) {
-            if ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
+            if ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
                 ++usedInFixCount;
             }
             if (VERBOSE) {
-                Log.v(TAG, "prn: " + (mPrnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH) +
+                Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
                         " snr: " + mSnrs[i]/10 +
                         " elev: " + mSvElevations[i] +
                         " azimuth: " + mSvAzimuths[i] +
-                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
+                        ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
                                 ? "  " : " E") +
-                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
+                        ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
                                 ? "  " : " A") +
-                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
+                        ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
                                 ? "" : "U"));
             }
         }
@@ -2398,14 +2396,13 @@
     }
 
     // for GPS SV statistics
-    private static final int MAX_SVS = 512;
+    private static final int MAX_SVS = 64;
 
     // preallocated arrays, to avoid memory allocation in reportStatus()
-    private int mPrnWithFlags[] = new int[MAX_SVS];
+    private int mSvidWithFlags[] = new int[MAX_SVS];
     private float mSnrs[] = new float[MAX_SVS];
     private float mSvElevations[] = new float[MAX_SVS];
     private float mSvAzimuths[] = new float[MAX_SVS];
-    private int mConstellationTypes[] = new int[MAX_SVS];
     private int mSvCount;
     // preallocated to avoid memory allocation in reportNmea()
     private byte[] mNmeaBuffer = new byte[120];
@@ -2426,7 +2423,7 @@
     // 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,
-            float[] azimuths, int[] constellationTypes);
+            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/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 9840c61..0b3111c 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -77,8 +77,7 @@
             final int[] prnWithFlags,
             final float[] snrs,
             final float[] elevations,
-            final float[] azimuths,
-            final int[] constellationTypes) {
+            final float[] azimuths) {
         Operation operation = new Operation() {
             @Override
             public void execute(IGnssStatusListener listener) throws RemoteException {
@@ -87,8 +86,7 @@
                         prnWithFlags,
                         snrs,
                         elevations,
-                        azimuths,
-                        constellationTypes);
+                        azimuths);
             }
         };
         foreach(operation);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 3cc7b10..22d0994 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1789,6 +1789,10 @@
             Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
             return null;
         }
+        return createUserInternalUnchecked(name, flags, parentId);
+    }
+
+    private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) {
         if (ActivityManager.isLowRamDeviceStatic()) {
             return null;
         }
@@ -2975,6 +2979,17 @@
                 am.switchUser(UserHandle.USER_SYSTEM);
             }
         }
+
+        @Override
+        public UserInfo createUserEvenWhenDisallowed(String name, int flags) {
+            UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL);
+            // Keep this in sync with UserManager.createUser
+            if (user != null && !user.isAdmin()) {
+                setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
+                setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, true, user.id);
+            }
+            return user;
+        }
     }
 
     /* Remove all the users except of the system one. */
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index c3a6f5d..3e8269a 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -29,6 +29,7 @@
 import android.os.Binder;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.util.AndroidRuntimeException;
@@ -141,7 +142,7 @@
                                 // only kills dependents of packages that are being removed.
                                 try {
                                     ActivityManagerNative.getDefault().killPackageDependents(
-                                        oldProviderName, getContext().getUserId());
+                                        oldProviderName, UserHandle.USER_ALL);
                                 } catch (RemoteException e) {
                                 }
                             }
@@ -209,7 +210,7 @@
         try {
             if (oldPackage != null) {
                 ActivityManagerNative.getDefault().killPackageDependents(
-                        oldPackage.packageName, getContext().getUserId());
+                        oldPackage.packageName, UserHandle.USER_ALL);
             }
         } catch (RemoteException e) {
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 0979cd3..e229c5e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -37,8 +37,8 @@
     static final boolean DEBUG = false;
     static final boolean DEBUG_ADD_REMOVE = false;
     static final boolean DEBUG_FOCUS = false;
-    static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
-    static final boolean DEBUG_ANIM = false;
+    static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || true;
+    static final boolean DEBUG_ANIM = true;
     static final boolean DEBUG_KEYGUARD = false;
     static final boolean DEBUG_LAYOUT = false;
     static final boolean DEBUG_LAYERS = false;
@@ -50,7 +50,7 @@
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_APP_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
-    static final boolean DEBUG_APP_TRANSITIONS = false;
+    static final boolean DEBUG_APP_TRANSITIONS = true;
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d1ffaa0..b0ece63 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1192,7 +1192,7 @@
                 break;
             }
         }
-        if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
                 "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
                         + windows.size());
         windows.add(i + 1, win);
@@ -1224,7 +1224,7 @@
                 //apptoken note that the window could be a floating window
                 //that was created later or a window at the top of the list of
                 //windows associated with this token.
-                if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
                         "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
                                 + windows.size());
                 windows.add(newIdx + 1, win);
@@ -1262,7 +1262,7 @@
             }
         }
         i++;
-        if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
                 "Free window: Adding window " + win + " at " + i + " of " + windows.size());
         windows.add(i, win);
         mWindowsChanged = true;
@@ -1333,7 +1333,7 @@
     }
 
     private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
-        if (DEBUG_FOCUS_LIGHT) Slog.d(TAG_WM, "addWindowToListInOrderLocked: win=" + win +
+        if (DEBUG_FOCUS) Slog.d(TAG_WM, "addWindowToListInOrderLocked: win=" + win +
                 " Callers=" + Debug.getCallers(4));
         if (win.mAttachedWindow == null) {
             final WindowToken token = win.mToken;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0201296..f8f8363 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1347,7 +1347,7 @@
             }
         } else {
             if (DEBUG_ANIM && isAnimating()) {
-                Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
+                //Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
             }
             displayed = true;
         }
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e75775f..cdd5519 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -68,13 +68,14 @@
 static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
 static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
 
-#define MAX_SATELLITE_COUNT 512
-#define MAX_GPS_SATELLITE_COUNT 512
+#define GPS_MAX_SATELLITE_COUNT 32
+#define GNSS_MAX_SATELLITE_COUNT 64
 
-#define PRN_SHIFT_WIDTH 3
+#define SVID_SHIFT_WIDTH 7
+#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
 
 // temporary storage for GPS callbacks
-static GnssSvInfo sGnssSvList[MAX_SATELLITE_COUNT];
+static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
 static size_t sGnssSvListSize;
 static const char* sNmeaString;
 static int sNmeaStringLength;
@@ -113,56 +114,75 @@
 {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     size_t status_size = sv_status->size;
-    // Some drive doesn't set the size field correctly. Assume GpsSvStatus_v1 if
-    // it doesn't provide a valid size.
+    // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
+    // if it doesn't provide a valid size.
     if (status_size == 0) {
-        status_size = sizeof(GpsSvStatus_v1);
+        ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
     }
-    if (status_size == sizeof(GpsSvStatus)) {
-        sGnssSvListSize = sv_status->gnss_sv_list_size;
-        // Cramp the list size
-        if (sGnssSvListSize > MAX_SATELLITE_COUNT) {
-            sGnssSvListSize = MAX_SATELLITE_COUNT;
-        }
-        // Copy GNSS SV info into sGnssSvList, if any.
-        if (sGnssSvListSize > 0 && sv_status->gnss_sv_list) {
-            memcpy(sGnssSvList, sv_status->gnss_sv_list, sizeof(GnssSvInfo) * sGnssSvListSize);
-        }
-    } else if (status_size == sizeof(GpsSvStatus_v1)) {
-        sGnssSvListSize = sv_status->num_svs;
-        // Cramp the list size
-        if (sGnssSvListSize > MAX_GPS_SATELLITE_COUNT) {
-            sGnssSvListSize = MAX_GPS_SATELLITE_COUNT;
-        }
-        uint32_t ephemeris_mask = sv_status->ephemeris_mask;
-        uint32_t almanac_mask = sv_status->almanac_mask;
-        uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
-        for (size_t i = 0; i < sGnssSvListSize; i++) {
-            GnssSvInfo& info = sGnssSvList[i];
+    sGnssSvListSize = sv_status->num_svs;
+    // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
+    if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
+        ALOGW("Too many satellites %zd. Clamps to %d.",
+              sGnssSvListSize,
+              GPS_MAX_SATELLITE_COUNT);
+        sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
+    }
+    uint32_t ephemeris_mask = sv_status->ephemeris_mask;
+    uint32_t almanac_mask = sv_status->almanac_mask;
+    uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
+    for (size_t i = 0; i < sGnssSvListSize; i++) {
+        GnssSvInfo& info = sGnssSvList[i];
+        info.svid = sv_status->sv_list[i].prn;
+        // TODO: implement the correct logic to derive the constellation type
+        // based on PRN ranges.
+        if (info.svid >=1 && info.svid <= 32) {
             info.constellation = GNSS_CONSTELLATION_GPS;
-            info.prn = sv_status->sv_list[i].prn;
-            info.snr = sv_status->sv_list[i].snr;
-            info.elevation = sv_status->sv_list[i].elevation;
-            info.azimuth = sv_status->sv_list[i].azimuth;
-            info.flags = GNSS_SV_FLAGS_NONE;
-            if (info.prn > 0 && info.prn <= 32) {
-              int32_t this_prn_mask = (1 << (info.prn - 1));
-              if ((ephemeris_mask & this_prn_mask) != 0) {
+        } else {
+            info.constellation = GNSS_CONSTELLATION_UNKNOWN;
+        }
+        info.snr = sv_status->sv_list[i].snr;
+        info.elevation = sv_status->sv_list[i].elevation;
+        info.azimuth = sv_status->sv_list[i].azimuth;
+        info.flags = GNSS_SV_FLAGS_NONE;
+        if (info.svid > 0 && info.svid <= 32) {
+            int32_t this_svid_mask = (1 << (info.svid - 1));
+            if ((ephemeris_mask & this_svid_mask) != 0) {
                 info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
-              }
-              if ((almanac_mask & this_prn_mask) != 0) {
+            }
+            if ((almanac_mask & this_svid_mask) != 0) {
                 info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
-              }
-              if ((used_in_fix_mask & this_prn_mask) != 0) {
+            }
+            if ((used_in_fix_mask & this_svid_mask) != 0) {
                 info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
-              }
             }
         }
-    } else {
-        sGnssSvListSize = 0;
-        ALOGE("Invalid size of GpsSvStatus found: %zd.", status_size);
+    }
+    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
+static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    size_t status_size = sv_status->size;
+    // Check the size, and reject the object that has invalid size.
+    if (status_size != sizeof(GnssSvStatus)) {
+        ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
         return;
     }
+    sGnssSvListSize = sv_status->num_svs;
+    // Clamp the list size
+    if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
+        ALOGD("Too many satellites %zd. Clamps to %d.",
+              sGnssSvListSize,
+              GNSS_MAX_SATELLITE_COUNT);
+        sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
+    }
+    // Copy GNSS SV info into sGnssSvList, if any.
+    if (sGnssSvListSize > 0) {
+        memcpy(sGnssSvList,
+               sv_status->gnss_sv_list,
+               sizeof(GnssSvInfo) * sGnssSvListSize);
+    }
     env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
@@ -228,6 +248,7 @@
     create_thread_callback,
     request_utc_time_callback,
     set_system_info_callback,
+    gnss_sv_status_callback,
 };
 
 static void xtra_download_request_callback()
@@ -677,31 +698,30 @@
 }
 
 static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
-        jintArray prnWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
-        jfloatArray azumArray, jintArray constellationTypeArray)
+        jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
+        jfloatArray azumArray)
 {
     // this should only be called from within a call to reportSvStatus
-    jint* prnWithFlags = env->GetIntArrayElements(prnWithFlagArray, 0);
+    jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
     jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
-    jint* constellationTypes = env->GetIntArrayElements(constellationTypeArray, 0);
 
     // GNSS SV info.
     for (size_t i = 0; i < sGnssSvListSize; ++i) {
         const GnssSvInfo& info = sGnssSvList[i];
-        constellationTypes[i] = info.constellation;
-        prnWithFlags[i] = (info.prn << PRN_SHIFT_WIDTH) | info.flags;
+        svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
+            (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
+            info.flags;
         snrs[i] = info.snr;
         elev[i] = info.elevation;
         azim[i] = info.azimuth;
     }
 
-    env->ReleaseIntArrayElements(prnWithFlagArray, prnWithFlags, 0);
+    env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
     env->ReleaseFloatArrayElements(snrArray, snrs, 0);
     env->ReleaseFloatArrayElements(elevArray, elev, 0);
     env->ReleaseFloatArrayElements(azumArray, azim, 0);
-    env->ReleaseIntArrayElements(constellationTypeArray, constellationTypes, 0);
     return (jint) sGnssSvListSize;
 }
 
@@ -968,370 +988,341 @@
     return JNI_FALSE;
 }
 
-static jobject translate_gps_clock(JNIEnv* env, void* data, size_t size) {
-    const char* doubleSignature = "(D)V";
-    const char* longSignature = "(J)V";
+template<class T>
+class JavaMethodHelper {
+  public:
+   // Helper function to call setter on a Java object.
+   static void callJavaMethod(
+           JNIEnv* env,
+           jclass clazz,
+           jobject object,
+           const char* method_name,
+           T value);
 
-    GpsClock* clock = reinterpret_cast<GpsClock*>(data);
+  private:
+    static const char *const signature_;
+};
 
-    jclass gpsClockClass = env->FindClass("android/location/GnssClock");
-    jmethodID gpsClockCtor = env->GetMethodID(gpsClockClass, "<init>", "()V");
+template<class T>
+void JavaMethodHelper<T>::callJavaMethod(
+        JNIEnv* env,
+        jclass clazz,
+        jobject object,
+        const char* method_name,
+        T value) {
+    jmethodID method = env->GetMethodID(clazz, method_name, signature_);
+    env->CallVoidMethod(object, method, value);
+}
 
-    jobject gpsClockObject = env->NewObject(gpsClockClass, gpsClockCtor);
+class JavaObject {
+  public:
+   JavaObject(JNIEnv* env, const char* class_name);
+   virtual ~JavaObject();
+
+   template<class T>
+   void callSetter(const char* method_name, T value);
+   template<class T>
+   void callSetter(const char* method_name, T* value, size_t size);
+   jobject get();
+
+  private:
+   JNIEnv* env_;
+   jclass clazz_;
+   jobject object_;
+};
+
+JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
+    clazz_ = env_->FindClass(class_name);
+    jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
+    object_ = env_->NewObject(clazz_, ctor);
+}
+
+JavaObject::~JavaObject() {
+    env_->DeleteLocalRef(clazz_);
+}
+
+template<class T>
+void JavaObject::callSetter(const char* method_name, T value) {
+    JavaMethodHelper<T>::callJavaMethod(
+            env_, clazz_, object_, method_name, value);
+}
+
+template<>
+void JavaObject::callSetter(
+        const char* method_name, uint8_t* value, size_t size) {
+    jbyteArray array = env_->NewByteArray(size);
+    env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
+    jmethodID method = env_->GetMethodID(
+            clazz_,
+            method_name,
+            "([B)V");
+    env_->CallVoidMethod(object_, method, array);
+}
+
+jobject JavaObject::get() {
+    return object_;
+}
+
+// Define Java method signatures for all known types.
+
+template<>
+const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
+template<>
+const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
+template<>
+const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
+template<>
+const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
+template<>
+const char *const JavaMethodHelper<int>::signature_ = "(I)V";
+template<>
+const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
+template<>
+const char *const JavaMethodHelper<float>::signature_ = "(F)V";
+template<>
+const char *const JavaMethodHelper<double>::signature_ = "(D)V";
+template<>
+const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
+
+#define SET(setter, value) object.callSetter("set" # setter, (value))
+#define SET_IF(flag, setter, value) \
+        if (flags & (flag)) object.callSetter("set" # setter, (value))
+
+static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
+    JavaObject object(env, "android/location/GnssClock");
     GpsClockFlags flags = clock->flags;
 
-    if (flags & GPS_CLOCK_HAS_LEAP_SECOND) {
-        jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setLeapSecond", "(S)V");
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->leap_second);
-   }
+    SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
+    SET(Type, clock->type);
+    SET(TimeInNs, clock->time_ns);
+    SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
+           TimeUncertaintyInNs,
+           clock->time_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
+           BiasUncertaintyInNs,
+           clock->bias_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
+           DriftUncertaintyInNsPerSec,
+           clock->drift_uncertainty_nsps);
 
-   jmethodID typeSetterMethod = env->GetMethodID(gpsClockClass, "setType", "(B)V");
-   env->CallVoidMethod(gpsClockObject, typeSetterMethod, clock->type);
-
-    jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setTimeInNs", longSignature);
-    env->CallVoidMethod(gpsClockObject, setterMethod, clock->time_ns);
-
-    if (flags & GPS_CLOCK_HAS_TIME_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setTimeUncertaintyInNs", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->time_uncertainty_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_FULL_BIAS) {
-        jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setFullBiasInNs", longSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->full_bias_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_BIAS) {
-        jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setBiasInNs", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->bias_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_BIAS_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setBiasUncertaintyInNs", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->bias_uncertainty_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_DRIFT) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setDriftInNsPerSec", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->drift_nsps);
-    }
-
-    if (flags & GPS_CLOCK_HAS_DRIFT_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setDriftUncertaintyInNsPerSec", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->drift_uncertainty_nsps);
-    }
-
+    /*
     if (flags & GPS_CLOCK_TYPE_LOCAL_HW_TIME) {
-        if (size == sizeof(GpsClock)) {
+        if (size == sizeof(GnssClock)) {
             jmethodID setterMethod =
                     env->GetMethodID(gpsClockClass,
                                      "setTimeOfLastHwClockDiscontinuityInNs",
                                      longSignature);
             env->CallVoidMethod(gpsClockObject,
                                 setterMethod,
-                                clock->time_of_last_hw_clock_discontinuity_ns);
+                                reinterpret_cast<GnssClock*>(clock)->time_of_last_hw_clock_discontinuity_ns);
         }
     }
+    */
 
-    env->DeleteLocalRef(gpsClockClass);
-    return gpsClockObject;
+    return object.get();
 }
 
-static jobject translate_gps_measurement(JNIEnv* env, void* data, size_t size) {
-    const char* byteSignature = "(B)V";
-    const char* shortSignature = "(S)V";
-    const char* intSignature = "(I)V";
-    const char* longSignature = "(J)V";
-    const char* floatSignature = "(F)V";
-    const char* doubleSignature = "(D)V";
+static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
+    JavaObject object(env, "android/location/GnssClock");
+    GpsClockFlags flags = clock->flags;
 
-    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
-    jmethodID gnssMeasurementCtor = env->GetMethodID(gnssMeasurementClass, "<init>", "()V");
-    GpsMeasurement* measurement = reinterpret_cast<GpsMeasurement*>(data);
+    SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
+    SET(Type, clock->type);
+    SET(TimeInNs, clock->time_ns);
+    SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
+           TimeUncertaintyInNs,
+           clock->time_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
+           BiasUncertaintyInNs,
+           clock->bias_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
+           DriftUncertaintyInNsPerSec,
+           clock->drift_uncertainty_nsps);
 
-    jobject gnssMeasurementObject = env->NewObject(gnssMeasurementClass, gnssMeasurementCtor);
+    SET_IF(GPS_CLOCK_TYPE_LOCAL_HW_TIME,
+           TimeOfLastHwClockDiscontinuityInNs,
+           clock->time_of_last_hw_clock_discontinuity_ns);
+
+    return object.get();
+}
+
+static jobject translate_gps_measurement(JNIEnv* env,
+                                         GpsMeasurement* measurement) {
+    JavaObject object(env, "android/location/GnssMeasurement");
     GpsMeasurementFlags flags = measurement->flags;
 
-    jmethodID prnSetterMethod = env->GetMethodID(gnssMeasurementClass, "setPrn", byteSignature);
-    env->CallVoidMethod(gnssMeasurementObject, prnSetterMethod, measurement->prn);
+    SET(Svid, static_cast<int16_t>(measurement->prn));
+    SET(TimeOffsetInNs, measurement->time_offset_ns);
+    SET(State, measurement->state);
+    SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns);
+    SET(ReceivedGpsTowUncertaintyInNs,
+        measurement->received_gps_tow_uncertainty_ns);
+    SET(Cn0InDbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyInMetersPerSec,
+        measurement->pseudorange_rate_uncertainty_mps);
+    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
+    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+        measurement->accumulated_delta_range_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE,
+           PseudorangeInMeters,
+           measurement->pseudorange_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
+           PseudorangeUncertaintyInMeters,
+           measurement->pseudorange_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE,
+           CodePhaseInChips,
+           measurement->code_phase_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
+           CodePhaseUncertaintyInChips,
+           measurement->code_phase_uncertainty_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
+           CarrierFrequencyInHz,
+           measurement->carrier_frequency_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES,
+           CarrierCycles,
+           measurement->carrier_cycles);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE,
+           CarrierPhase,
+           measurement->carrier_phase);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
+           CarrierPhaseUncertainty,
+           measurement->carrier_phase_uncertainty);
+    SET(LossOfLock, measurement->loss_of_lock);
+    SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
+    SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
+           TimeFromLastBitInMs,
+           measurement->time_from_last_bit_ms);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT,
+           DopplerShiftInHz,
+           measurement->doppler_shift_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
+           DopplerShiftUncertaintyInHz,
+           measurement->doppler_shift_uncertainty_hz);
+    SET(MultipathIndicator, measurement->multipath_indicator);
+    SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION,
+           ElevationInDeg,
+           measurement->elevation_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
+           ElevationUncertaintyInDeg,
+           measurement->elevation_uncertainty_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH,
+           AzimuthInDeg,
+           measurement->azimuth_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
+           AzimuthUncertaintyInDeg,
+           measurement->azimuth_uncertainty_deg);
+    SET(UsedInFix,
+        (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
 
-    jmethodID timeOffsetSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setTimeOffsetInNs", doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            timeOffsetSetterMethod,
-            measurement->time_offset_ns);
-
-    jmethodID stateSetterMethod = env->GetMethodID(gnssMeasurementClass, "setState", shortSignature);
-    env->CallVoidMethod(gnssMeasurementObject, stateSetterMethod, measurement->state);
-
-    jmethodID receivedGpsTowSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setReceivedGpsTowInNs", longSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            receivedGpsTowSetterMethod,
-            measurement->received_gps_tow_ns);
-
-    jmethodID receivedGpsTowUncertaintySetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setReceivedGpsTowUncertaintyInNs",
-            longSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            receivedGpsTowUncertaintySetterMethod,
-            measurement->received_gps_tow_uncertainty_ns);
-
-    jmethodID cn0SetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setCn0InDbHz", doubleSignature);
-    env->CallVoidMethod(gnssMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz);
-
-    jmethodID pseudorangeRateSetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setPseudorangeRateInMetersPerSec",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            pseudorangeRateSetterMethod,
-            measurement->pseudorange_rate_mps);
-
-    jmethodID pseudorangeRateUncertaintySetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setPseudorangeRateUncertaintyInMetersPerSec",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            pseudorangeRateUncertaintySetterMethod,
-            measurement->pseudorange_rate_uncertainty_mps);
-
-    jmethodID accumulatedDeltaRangeStateSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setAccumulatedDeltaRangeState", shortSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            accumulatedDeltaRangeStateSetterMethod,
-            measurement->accumulated_delta_range_state);
-
-    jmethodID accumulatedDeltaRangeSetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setAccumulatedDeltaRangeInMeters",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            accumulatedDeltaRangeSetterMethod,
-            measurement->accumulated_delta_range_m);
-
-    jmethodID accumulatedDeltaRangeUncertaintySetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setAccumulatedDeltaRangeUncertaintyInMeters",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            accumulatedDeltaRangeUncertaintySetterMethod,
-            measurement->accumulated_delta_range_uncertainty_m);
-
-    if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setPseudorangeInMeters", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->pseudorange_m);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setPseudorangeUncertaintyInMeters",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->pseudorange_uncertainty_m);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCodePhaseInChips", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->code_phase_chips);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setCodePhaseUncertaintyInChips",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->code_phase_uncertainty_chips);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCarrierFrequencyInHz", floatSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->carrier_frequency_hz);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_CYCLES) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCarrierCycles", longSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->carrier_cycles);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCarrierPhase", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->carrier_phase);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setCarrierPhaseUncertainty",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->carrier_phase_uncertainty);
-    }
-
-    jmethodID lossOfLockSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setLossOfLock", byteSignature);
-    env->CallVoidMethod(gnssMeasurementObject, lossOfLockSetterMethod, measurement->loss_of_lock);
-
-    if (flags & GPS_MEASUREMENT_HAS_BIT_NUMBER) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setBitNumber", intSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->bit_number);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setTimeFromLastBitInMs", shortSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->time_from_last_bit_ms);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setDopplerShiftInHz", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->doppler_shift_hz);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setDopplerShiftUncertaintyInHz",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->doppler_shift_uncertainty_hz);
-    }
-
-    jmethodID multipathIndicatorSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setMultipathIndicator", byteSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            multipathIndicatorSetterMethod,
-            measurement->multipath_indicator);
-
-    if (flags & GPS_MEASUREMENT_HAS_SNR) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setSnrInDb", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->snr_db);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_ELEVATION) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setElevationInDeg", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->elevation_deg);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setElevationUncertaintyInDeg", doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->elevation_uncertainty_deg);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_AZIMUTH) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setAzimuthInDeg", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->azimuth_deg);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setAzimuthUncertaintyInDeg",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->azimuth_uncertainty_deg);
-    }
-
-    jmethodID usedInFixSetterMethod = env->GetMethodID(gnssMeasurementClass, "setUsedInFix", "(Z)V");
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            usedInFixSetterMethod,
-            (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
-
-    if (size == sizeof(GpsMeasurement)) {
-      jmethodID setterMethod =
-          env->GetMethodID(gnssMeasurementClass,
-                           "setPseudorangeRateCarrierInMetersPerSec",
-                           doubleSignature);
-      env->CallVoidMethod(
-          gnssMeasurementObject,
-          setterMethod,
-          measurement->pseudorange_rate_carrier_mps);
-
-      setterMethod =
-          env->GetMethodID(gnssMeasurementClass,
-                           "setPseudorangeRateCarrierUncertaintyInMetersPerSec",
-                           doubleSignature);
-      env->CallVoidMethod(
-          gnssMeasurementObject,
-          setterMethod,
-          measurement->pseudorange_rate_carrier_uncertainty_mps);
-    }
-
-    env->DeleteLocalRef(gnssMeasurementClass);
-    return gnssMeasurementObject;
+    return object.get();
 }
 
-/**
- * <T> can only be GpsData or GpsData_v1. Must rewrite this function if more
- * types are introduced in the future releases.
- */
-template<class T>
-static jobjectArray translate_gps_measurements(JNIEnv* env, void* data) {
-    T* gps_data = reinterpret_cast<T*>(data);
-    size_t measurementCount = gps_data->measurement_count;
-    if (measurementCount == 0) {
+static jobject translate_gnss_measurement(JNIEnv* env,
+                                          GnssMeasurement* measurement) {
+    JavaObject object(env, "android/location/GnssMeasurement");
+    GpsMeasurementFlags flags = measurement->flags;
+
+    SET(Svid, measurement->svid);
+    SET(TimeOffsetInNs, measurement->time_offset_ns);
+    SET(State, measurement->state);
+    SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns);
+    SET(ReceivedGpsTowUncertaintyInNs,
+        measurement->received_gps_tow_uncertainty_ns);
+    SET(Cn0InDbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyInMetersPerSec,
+        measurement->pseudorange_rate_uncertainty_mps);
+    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
+    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+        measurement->accumulated_delta_range_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE,
+           PseudorangeInMeters,
+           measurement->pseudorange_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
+           PseudorangeUncertaintyInMeters,
+           measurement->pseudorange_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE,
+           CodePhaseInChips,
+           measurement->code_phase_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
+           CodePhaseUncertaintyInChips,
+           measurement->code_phase_uncertainty_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
+           CarrierFrequencyInHz,
+           measurement->carrier_frequency_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES,
+           CarrierCycles,
+           measurement->carrier_cycles);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE,
+           CarrierPhase,
+           measurement->carrier_phase);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
+           CarrierPhaseUncertainty,
+           measurement->carrier_phase_uncertainty);
+    SET(LossOfLock, measurement->loss_of_lock);
+    SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
+    SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
+           TimeFromLastBitInMs,
+           measurement->time_from_last_bit_ms);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT,
+           DopplerShiftInHz,
+           measurement->doppler_shift_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
+           DopplerShiftUncertaintyInHz,
+           measurement->doppler_shift_uncertainty_hz);
+    SET(MultipathIndicator, measurement->multipath_indicator);
+    SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION,
+           ElevationInDeg,
+           measurement->elevation_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
+           ElevationUncertaintyInDeg,
+           measurement->elevation_uncertainty_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH,
+           AzimuthInDeg,
+           measurement->azimuth_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
+           AzimuthUncertaintyInDeg,
+           measurement->azimuth_uncertainty_deg);
+    SET(UsedInFix,
+        (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
+
+    SET(PseudorangeRateCarrierInMetersPerSec,
+        measurement->pseudorange_rate_carrier_mps);
+    SET(PseudorangeRateCarrierUncertaintyInMetersPerSec,
+        measurement->pseudorange_rate_carrier_uncertainty_mps);
+
+    return object.get();
+}
+
+static jobjectArray translate_gps_measurements(JNIEnv* env,
+                                               GpsMeasurement* measurements,
+                                               size_t count) {
+    if (count == 0) {
         return NULL;
     }
 
-    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
+    jclass gnssMeasurementClass = env->FindClass(
+            "android/location/GnssMeasurement");
     jobjectArray gnssMeasurementArray = env->NewObjectArray(
-            measurementCount,
+            count,
             gnssMeasurementClass,
             NULL /* initialElement */);
 
-    for (uint16_t i = 0; i < measurementCount; ++i) {
+    for (uint16_t i = 0; i < count; ++i) {
         jobject gnssMeasurement = translate_gps_measurement(
             env,
-            &(gps_data->measurements[i]),
-            sizeof(gps_data->measurements[0]));
+            &measurements[i]);
         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
         env->DeleteLocalRef(gnssMeasurement);
     }
@@ -1340,27 +1331,37 @@
     return gnssMeasurementArray;
 }
 
-static void measurement_callback(GpsData* data) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (data == NULL) {
-        ALOGE("Invalid data provided to gps_measurement_callback");
-        return;
-    }
-    if (data->size != sizeof(GpsData) && data->size != sizeof(GpsData_v1)) {
-        ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%zd", data->size);
-        return;
+static jobjectArray translate_gnss_measurements(JNIEnv* env,
+                                                GnssMeasurement* measurements,
+                                                size_t count) {
+    if (count == 0) {
+        return NULL;
     }
 
-    jobject gpsClock;
-    jobjectArray measurementArray;
-    if (data->size == sizeof(GpsData)) {
-        gpsClock = translate_gps_clock(env, &data->clock, sizeof(GpsClock));
-        measurementArray = translate_gps_measurements<GpsData>(env, data);
-    } else {
-        gpsClock = translate_gps_clock(env, &data->clock, sizeof(GpsClock_v1));
-        measurementArray = translate_gps_measurements<GpsData_v1>(env, data);
+    jclass gnssMeasurementClass = env->FindClass(
+            "android/location/GnssMeasurement");
+    jobjectArray gnssMeasurementArray = env->NewObjectArray(
+            count,
+            gnssMeasurementClass,
+            NULL /* initialElement */);
+
+    for (uint16_t i = 0; i < count; ++i) {
+        jobject gnssMeasurement = translate_gnss_measurement(
+            env,
+            &measurements[i]);
+        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
+        env->DeleteLocalRef(gnssMeasurement);
     }
-    jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
+
+    env->DeleteLocalRef(gnssMeasurementClass);
+    return gnssMeasurementArray;
+}
+
+static void set_measurement_data(JNIEnv *env,
+                                 jobject clock,
+                                 jobjectArray measurementArray) {
+    jclass gnssMeasurementsEventClass = env->FindClass(
+            "android/location/GnssMeasurementsEvent");
     jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
         gnssMeasurementsEventClass,
         "<init>",
@@ -1369,21 +1370,68 @@
     jobject gnssMeasurementsEvent = env->NewObject(
         gnssMeasurementsEventClass,
         gnssMeasurementsEventCtor,
-        gpsClock,
+        clock,
         measurementArray);
-
-    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gnssMeasurementsEvent);
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportMeasurementData,
+                        gnssMeasurementsEvent);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-
-    env->DeleteLocalRef(gpsClock);
-    env->DeleteLocalRef(measurementArray);
     env->DeleteLocalRef(gnssMeasurementsEventClass);
     env->DeleteLocalRef(gnssMeasurementsEvent);
 }
 
+static void measurement_callback(GpsData* data) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (data == NULL) {
+        ALOGE("Invalid data provided to gps_measurement_callback");
+        return;
+    }
+    if (data->size != sizeof(GpsData)) {
+        ALOGE("Invalid GpsData size found in gps_measurement_callback, "
+              "size=%zd",
+              data->size);
+        return;
+    }
+
+    jobject clock;
+    jobjectArray measurementArray;
+    clock = translate_gps_clock(env, &data->clock);
+    measurementArray = translate_gps_measurements(
+            env, data->measurements, data->measurement_count);
+    set_measurement_data(env, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+}
+
+static void gnss_measurement_callback(GnssData* data) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (data == NULL) {
+        ALOGE("Invalid data provided to gps_measurement_callback");
+        return;
+    }
+    if (data->size != sizeof(GpsData)) {
+        ALOGE("Invalid GpsData size found in gps_measurement_callback, "
+              "size=%zd",
+              data->size);
+        return;
+    }
+
+    jobject clock;
+    jobjectArray measurementArray;
+    clock = translate_gnss_clock(env, &data->clock);
+    measurementArray = translate_gnss_measurements(
+            env, data->measurements, data->measurement_count);
+    set_measurement_data(env, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+}
+
 GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
     sizeof(GpsMeasurementCallbacks),
     measurement_callback,
+    gnss_measurement_callback,
 };
 
 static jboolean android_location_GnssLocationProvider_is_measurement_supported(
@@ -1431,69 +1479,86 @@
         ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
         return NULL;
     }
+    JavaObject object(env, "android/location/GnssNavigationMessage");
+    SET(Type, message->type);
+    SET(Svid, static_cast<int16_t>(message->prn));
+    SET(MessageId, message->message_id);
+    SET(SubmessageId, message->submessage_id);
+    object.callSetter("setData", data, dataLength);
+    return object.get();
+}
 
-    jclass navigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
-    jmethodID navigationMessageCtor = env->GetMethodID(navigationMessageClass, "<init>", "()V");
-    jobject navigationMessageObject = env->NewObject(navigationMessageClass, navigationMessageCtor);
+static jobject translate_gnss_navigation_message(
+        JNIEnv* env, GnssNavigationMessage* message) {
+    size_t dataLength = message->data_length;
+    uint8_t* data = message->data;
+    if (dataLength == 0 || data == NULL) {
+        ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
+        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);
+    object.callSetter("setData", data, dataLength);
+    return object.get();
+}
 
-    jmethodID setTypeMethod = env->GetMethodID(navigationMessageClass, "setType", "(B)V");
-    env->CallVoidMethod(navigationMessageObject, setTypeMethod, message->type);
-
-    jmethodID setPrnMethod = env->GetMethodID(navigationMessageClass, "setPrn", "(B)V");
-    env->CallVoidMethod(navigationMessageObject, setPrnMethod, message->prn);
-
-    jmethodID setMessageIdMethod = env->GetMethodID(navigationMessageClass, "setMessageId", "(S)V");
-    env->CallVoidMethod(navigationMessageObject, setMessageIdMethod, message->message_id);
-
-    jmethodID setSubmessageIdMethod =
-            env->GetMethodID(navigationMessageClass, "setSubmessageId", "(S)V");
-    env->CallVoidMethod(navigationMessageObject, setSubmessageIdMethod, message->submessage_id);
-
-    jbyteArray dataArray = env->NewByteArray(dataLength);
-    env->SetByteArrayRegion(dataArray, 0, dataLength, (jbyte*) data);
-    jmethodID setDataMethod = env->GetMethodID(navigationMessageClass, "setData", "([B)V");
-    env->CallVoidMethod(navigationMessageObject, setDataMethod, dataArray);
-
-    env->DeleteLocalRef(navigationMessageClass);
-    env->DeleteLocalRef(dataArray);
-    return navigationMessageObject;
+static void set_navigation_message(jobject navigationMessage) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jclass navigationMessageEventClass =
+            env->FindClass("android/location/GnssNavigationMessageEvent");
+    jmethodID navigationMessageEventCtor = env->GetMethodID(
+            navigationMessageEventClass,
+            "<init>",
+            "(Landroid/location/GnssNavigationMessage;)V");
+    jobject navigationMessageEvent = env->NewObject(
+            navigationMessageEventClass,
+            navigationMessageEventCtor,
+            navigationMessage);
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportNavigationMessages,
+                        navigationMessageEvent);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    env->DeleteLocalRef(navigationMessageEventClass);
+    env->DeleteLocalRef(navigationMessageEvent);
 }
 
 static void navigation_message_callback(GpsNavigationMessage* message) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
     if (message == NULL) {
         ALOGE("Invalid Navigation Message provided to callback");
         return;
     }
-
-    if (message->size == sizeof(GpsNavigationMessage)) {
-        jobject navigationMessage = translate_gps_navigation_message(env, message);
-
-        jclass navigationMessageEventClass =
-                env->FindClass("android/location/GnssNavigationMessageEvent");
-        jmethodID navigationMessageEventCtor = env->GetMethodID(
-                navigationMessageEventClass,
-                "<init>",
-                "(Landroid/location/GnssNavigationMessage;)V");
-        jobject navigationMessageEvent = env->NewObject(
-                navigationMessageEventClass,
-                navigationMessageEventCtor,
-                navigationMessage);
-
-        env->CallVoidMethod(mCallbacksObj, method_reportNavigationMessages, navigationMessageEvent);
-        checkAndClearExceptionFromCallback(env, __FUNCTION__);
-
-        env->DeleteLocalRef(navigationMessage);
-        env->DeleteLocalRef(navigationMessageEventClass);
-        env->DeleteLocalRef(navigationMessageEvent);
-    } else {
+    if (message->size != sizeof(GpsNavigationMessage)) {
         ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
+        return;
     }
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject navigationMessage = translate_gps_navigation_message(env, message);
+    set_navigation_message(navigationMessage);
+    env->DeleteLocalRef(navigationMessage);
+}
+
+static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
+    if (message == NULL) {
+        ALOGE("Invalid Navigation Message provided to callback");
+        return;
+    }
+    if (message->size != sizeof(GnssNavigationMessage)) {
+        ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
+        return;
+    }
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject navigationMessage = translate_gnss_navigation_message(env, message);
+    set_navigation_message(navigationMessage);
+    env->DeleteLocalRef(navigationMessage);
 }
 
 GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
     sizeof(GpsNavigationMessageCallbacks),
     navigation_message_callback,
+    gnss_navigation_message_callback,
 };
 
 static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
@@ -1567,7 +1632,7 @@
             "(I)V",
             (void*)android_location_GnssLocationProvider_delete_aiding_data},
     {"native_read_sv_status",
-            "([I[F[F[F[I)I",
+            "([I[F[F[F)I",
             (void*)android_location_GnssLocationProvider_read_sv_status},
     {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
     {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b7138d2..d7222a5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1249,7 +1249,9 @@
                     if (packageName == null || packageName.equals(adminPackage)) {
                         if (mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) == null
                                 || mIPackageManager.getReceiverInfo(
-                                    aa.info.getComponent(), 0, userHandle) == null) {
+                                    aa.info.getComponent(),
+                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
+                                    userHandle) == null) {
                             removed = true;
                             policy.mAdminList.remove(i);
                             policy.mAdminMap.remove(aa.info.getComponent());
@@ -6791,6 +6793,10 @@
             throw new IllegalArgumentException("profileOwner " + profileOwner + " and admin "
                     + admin + " are not in the same package");
         }
+        // Only allow the system user to use this method
+        if (!mInjector.binderGetCallingUserHandle().isSystem()) {
+            throw new SecurityException("createAndManageUser was called from non-system user");
+        }
         // Create user.
         UserHandle user = null;
         synchronized (this) {
@@ -6802,7 +6808,8 @@
                 if ((flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0) {
                     userInfoFlags |= UserInfo.FLAG_EPHEMERAL;
                 }
-                UserInfo userInfo = mUserManager.createUser(name, userInfoFlags);
+                UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name,
+                        userInfoFlags);
                 if (userInfo != null) {
                     user = userInfo.getUserHandle();
                 }
@@ -7132,7 +7139,7 @@
                 List<ResolveInfo> activitiesToEnable = mIPackageManager.queryIntentActivities(
                         intent,
                         intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                        0, // no flags
+                        PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE,
                         parentUserId);
 
                 if (VERBOSE_LOG) {
@@ -8526,26 +8533,32 @@
             mPackagesToRemove.add(packageUserPair);
         }
 
-        final List<ComponentName> activeAdminsList = getActiveAdmins(userId);
-        if (activeAdminsList == null || activeAdminsList.size() == 0) {
-            startUninstallIntent(packageName, userId);
-            return;
-        }
+        // All active admins on the user.
+        final List<ComponentName> allActiveAdmins = getActiveAdmins(userId);
 
-        for (ComponentName activeAdmin : activeAdminsList) {
-            if (packageName.equals(activeAdmin.getPackageName())) {
-                removeActiveAdmin(activeAdmin, userId);
+        // Active admins in the target package.
+        final List<ComponentName> packageActiveAdmins = new ArrayList<>();
+        if (allActiveAdmins != null) {
+            for (ComponentName activeAdmin : allActiveAdmins) {
+                if (packageName.equals(activeAdmin.getPackageName())) {
+                    packageActiveAdmins.add(activeAdmin);
+                    removeActiveAdmin(activeAdmin, userId);
+                }
             }
         }
-        mHandler.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                for (ComponentName activeAdmin : activeAdminsList) {
-                    removeAdminArtifacts(activeAdmin, userId);
+        if (packageActiveAdmins.size() == 0) {
+            startUninstallIntent(packageName, userId);
+        } else {
+            mHandler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    for (ComponentName activeAdmin : packageActiveAdmins) {
+                        removeAdminArtifacts(activeAdmin, userId);
+                    }
+                    startUninstallIntent(packageName, userId);
                 }
-                startUninstallIntent(packageName, userId);
-            }
-        }, DEVICE_ADMIN_DEACTIVATE_TIMEOUT); // Start uninstall after timeout anyway.
+            }, DEVICE_ADMIN_DEACTIVATE_TIMEOUT); // Start uninstall after timeout anyway.
+        }
     }
 
     private void removePackageIfRequired(final String packageName, final int userId) {
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 73cc4a5..3f32dbe 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -16,6 +16,8 @@
 
 package android.telecom;
 
+import android.os.AsyncTask;
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.IllegalFormatException;
@@ -38,8 +40,26 @@
     public static final boolean WARN = isLoggable(android.util.Log.WARN);
     public static final boolean ERROR = isLoggable(android.util.Log.ERROR);
 
+    private static MessageDigest sMessageDigest;
+
     private Log() {}
 
+    public static void initMd5Sum() {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            public Void doInBackground(Void... args) {
+                MessageDigest md;
+                try {
+                    md = MessageDigest.getInstance("SHA-1");
+                } catch (NoSuchAlgorithmException e) {
+                    md = null;
+                }
+                sMessageDigest = md;
+                return null;
+            }
+        }.execute();
+    }
+
     public static boolean isLoggable(int level) {
         return FORCE_LOGGING || android.util.Log.isLoggable(TAG, level);
     }
@@ -137,15 +157,14 @@
     }
 
     private static String secureHash(byte[] input) {
-        MessageDigest messageDigest;
-        try {
-            messageDigest = MessageDigest.getInstance("SHA-1");
-        } catch (NoSuchAlgorithmException e) {
-            return null;
+        if (sMessageDigest != null) {
+            sMessageDigest.reset();
+            sMessageDigest.update(input);
+            byte[] result = sMessageDigest.digest();
+            return encodeHex(result);
+        } else {
+            return "Uninitialized SHA1";
         }
-        messageDigest.update(input);
-        byte[] result = messageDigest.digest();
-        return encodeHex(result);
     }
 
     private static String encodeHex(byte[] bytes) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index f1cbb9a..9f478df 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -498,6 +498,7 @@
             mContext = context;
         }
         mTelecomServiceOverride = telecomServiceImpl;
+        android.telecom.Log.initMd5Sum();
     }
 
     /**
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index d0dd22f..a10ac00 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -388,21 +388,18 @@
     @LayoutlibDelegate
     /*package*/ static void native_addRoundRect(long nPath, float left, float top, float right,
             float bottom, float[] radii, int dir) {
-        // Java2D doesn't support different rounded corners in each corner, so just use the
-        // first value.
-        native_addRoundRect(nPath, left, top, right, bottom, radii[0], radii[1], dir);
 
-        // there can be a case where this API is used but with similar values for all corners, so
-        // in that case we don't warn.
-        // we only care if 2 corners are different so just compare to the next one.
-        for (int i = 0 ; i < 3 ; i++) {
-            if (radii[i * 2] != radii[(i + 1) * 2] || radii[i * 2 + 1] != radii[(i + 1) * 2 + 1]) {
-                Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
-                        "Different corner sizes are not supported in Path.addRoundRect.",
-                        null, null /*data*/);
-                break;
-            }
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
         }
+
+        float[] cornerDimensions = new float[radii.length];
+        for (int i = 0; i < radii.length; i++) {
+            cornerDimensions[i] = 2 * radii[i];
+        }
+        pathDelegate.mPath.append(new RoundRectangle(left, top, right - left, bottom - top,
+                cornerDimensions), false);
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java b/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java
new file mode 100644
index 0000000..edd36e5
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java
@@ -0,0 +1,370 @@
+/*
+ * 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;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RectangularShape;
+import java.awt.geom.RoundRectangle2D;
+import java.util.EnumSet;
+import java.util.NoSuchElementException;
+
+/**
+ * Defines a rectangle with rounded corners, where the sizes of the corners
+ * are potentially different.
+ */
+public class RoundRectangle extends RectangularShape {
+    public double x;
+    public double y;
+    public double width;
+    public double height;
+    public double ulWidth;
+    public double ulHeight;
+    public double urWidth;
+    public double urHeight;
+    public double lrWidth;
+    public double lrHeight;
+    public double llWidth;
+    public double llHeight;
+
+    private enum Zone {
+        CLOSE_OUTSIDE,
+        CLOSE_INSIDE,
+        MIDDLE,
+        FAR_INSIDE,
+        FAR_OUTSIDE
+    }
+
+    private final EnumSet<Zone> close = EnumSet.of(Zone.CLOSE_OUTSIDE, Zone.CLOSE_INSIDE);
+    private final EnumSet<Zone> far = EnumSet.of(Zone.FAR_OUTSIDE, Zone.FAR_INSIDE);
+
+    /**
+     * @param cornerDimensions array of 8 floating-point number corresponding to the width and
+     * the height of each corner in the following order: upper-left, upper-right, lower-right,
+     * lower-left. It assumes for the size the same convention as {@link RoundRectangle2D}, that
+     * is that the width and height of a corner correspond to the total width and height of the
+     * ellipse that corner is a quarter of.
+     */
+    public RoundRectangle(float x, float y, float width, float height, float[] cornerDimensions) {
+        if (cornerDimensions.length != 8) {
+            throw new IllegalArgumentException("The array of corner dimensions must have eight " +
+                    "elements");
+        }
+
+        this.x = x;
+        this.y = y;
+        this.width = width;
+        this.height = height;
+
+        float[] dimensions = cornerDimensions.clone();
+        // If a value is negative, the corresponding corner is squared
+        for (int i = 0; i < dimensions.length; i += 2) {
+            if (dimensions[i] < 0 || dimensions[i + 1] < 0) {
+                dimensions[i] = 0;
+                dimensions[i + 1] = 0;
+            }
+        }
+
+        double topCornerWidth = (dimensions[0] + dimensions[2]) / 2d;
+        double bottomCornerWidth = (dimensions[4] + dimensions[6]) / 2d;
+        double leftCornerHeight = (dimensions[1] + dimensions[7]) / 2d;
+        double rightCornerHeight = (dimensions[3] + dimensions[5]) / 2d;
+
+        // Rescale the corner dimensions if they are bigger than the rectangle
+        double scale = Math.min(1.0, width / topCornerWidth);
+        scale = Math.min(scale, width / bottomCornerWidth);
+        scale = Math.min(scale, height / leftCornerHeight);
+        scale = Math.min(scale, height / rightCornerHeight);
+
+        this.ulWidth = dimensions[0] * scale;
+        this.ulHeight = dimensions[1] * scale;
+        this.urWidth = dimensions[2] * scale;
+        this.urHeight = dimensions[3] * scale;
+        this.lrWidth = dimensions[4] * scale;
+        this.lrHeight = dimensions[5] * scale;
+        this.llWidth = dimensions[6] * scale;
+        this.llHeight = dimensions[7] * scale;
+    }
+
+    @Override
+    public double getX() {
+        return x;
+    }
+
+    @Override
+    public double getY() {
+        return y;
+    }
+
+    @Override
+    public double getWidth() {
+        return width;
+    }
+
+    @Override
+    public double getHeight() {
+        return height;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return (width <= 0d) || (height <= 0d);
+    }
+
+    @Override
+    public void setFrame(double x, double y, double w, double h) {
+        this.x = x;
+        this.y = y;
+        this.width = w;
+        this.height = h;
+    }
+
+    @Override
+    public Rectangle2D getBounds2D() {
+        return new Rectangle2D.Double(x, y, width, height);
+    }
+
+    @Override
+    public boolean contains(double x, double y) {
+        if (isEmpty()) {
+            return false;
+        }
+
+        double x0 = getX();
+        double y0 = getY();
+        double x1 = x0 + getWidth();
+        double y1 = y0 + getHeight();
+        // Check for trivial rejection - point is outside bounding rectangle
+        if (x < x0 || y < y0 || x >= x1 || y >= y1) {
+            return false;
+        }
+
+        double insideTopX0 = x0 + ulWidth / 2d;
+        double insideLeftY0 = y0 + ulHeight / 2d;
+        if (x < insideTopX0 && y < insideLeftY0) {
+            // In the upper-left corner
+            return isInsideCorner(x - insideTopX0, y - insideLeftY0, ulWidth / 2d, ulHeight / 2d);
+        }
+
+        double insideTopX1 = x1 - urWidth / 2d;
+        double insideRightY0 = y0 + urHeight / 2d;
+        if (x > insideTopX1 && y < insideRightY0) {
+            // In the upper-right corner
+            return isInsideCorner(x - insideTopX1, y - insideRightY0, urWidth / 2d, urHeight / 2d);
+        }
+
+        double insideBottomX1 = x1 - lrWidth / 2d;
+        double insideRightY1 = y1 - lrHeight / 2d;
+        if (x > insideBottomX1 && y > insideRightY1) {
+            // In the lower-right corner
+            return isInsideCorner(x - insideBottomX1, y - insideRightY1, lrWidth / 2d,
+                    lrHeight / 2d);
+        }
+
+        double insideBottomX0 = x0 + llWidth / 2d;
+        double insideLeftY1 = y1 - llHeight / 2d;
+        if (x < insideBottomX0 && y > insideLeftY1) {
+            // In the lower-left corner
+            return isInsideCorner(x - insideBottomX0, y - insideLeftY1, llWidth / 2d,
+                    llHeight / 2d);
+        }
+
+        // In the central part of the rectangle
+        return true;
+    }
+
+    private boolean isInsideCorner(double x, double y, double width, double height) {
+        double squareDist = height * height * x * x + width * width * y * y;
+        return squareDist <= width * width * height * height;
+    }
+
+    private Zone classify(double coord, double side1, double arcSize1, double side2,
+            double arcSize2) {
+        if (coord < side1) {
+            return Zone.CLOSE_OUTSIDE;
+        } else if (coord < side1 + arcSize1) {
+            return Zone.CLOSE_INSIDE;
+        } else if (coord < side2 - arcSize2) {
+            return Zone.MIDDLE;
+        } else if (coord < side2) {
+            return Zone.FAR_INSIDE;
+        } else {
+            return Zone.FAR_OUTSIDE;
+        }
+    }
+
+    public boolean intersects(double x, double y, double w, double h) {
+        if (isEmpty() || w <= 0 || h <= 0) {
+            return false;
+        }
+        double x0 = getX();
+        double y0 = getY();
+        double x1 = x0 + getWidth();
+        double y1 = y0 + getHeight();
+        // Check for trivial rejection - bounding rectangles do not intersect
+        if (x + w <= x0 || x >= x1 || y + h <= y0 || y >= y1) {
+            return false;
+        }
+
+        double maxLeftCornerWidth = Math.max(ulWidth, llWidth) / 2d;
+        double maxRightCornerWidth = Math.max(urWidth, lrWidth) / 2d;
+        double maxUpperCornerHeight = Math.max(ulHeight, urHeight) / 2d;
+        double maxLowerCornerHeight = Math.max(llHeight, lrHeight) / 2d;
+        Zone x0class = classify(x, x0, maxLeftCornerWidth, x1, maxRightCornerWidth);
+        Zone x1class = classify(x + w, x0, maxLeftCornerWidth, x1, maxRightCornerWidth);
+        Zone y0class = classify(y, y0, maxUpperCornerHeight, y1, maxLowerCornerHeight);
+        Zone y1class = classify(y + h, y0, maxUpperCornerHeight, y1, maxLowerCornerHeight);
+
+        // Trivially accept if any point is inside inner rectangle
+        if (x0class == Zone.MIDDLE || x1class == Zone.MIDDLE || y0class == Zone.MIDDLE || y1class == Zone.MIDDLE) {
+            return true;
+        }
+        // Trivially accept if either edge spans inner rectangle
+        if ((close.contains(x0class) && far.contains(x1class)) || (close.contains(y0class) &&
+                far.contains(y1class))) {
+            return true;
+        }
+
+        // Since neither edge spans the center, then one of the corners
+        // must be in one of the rounded edges.  We detect this case if
+        // a [xy]0class is 3 or a [xy]1class is 1.  One of those two cases
+        // must be true for each direction.
+        // We now find a "nearest point" to test for being inside a rounded
+        // corner.
+        if (x1class == Zone.CLOSE_INSIDE && y1class == Zone.CLOSE_INSIDE) {
+            // Potentially in upper-left corner
+            x = x + w - x0 - ulWidth / 2d;
+            y = y + h - y0 - ulHeight / 2d;
+            return x > 0 || y > 0 || isInsideCorner(x, y, ulWidth / 2d, ulHeight / 2d);
+        }
+        if (x1class == Zone.CLOSE_INSIDE) {
+            // Potentially in lower-left corner
+            x = x + w - x0 - llWidth / 2d;
+            y = y - y1 + llHeight / 2d;
+            return x > 0 || y < 0 || isInsideCorner(x, y, llWidth / 2d, llHeight / 2d);
+        }
+        if (y1class == Zone.CLOSE_INSIDE) {
+            //Potentially in the upper-right corner
+            x = x - x1 + urWidth / 2d;
+            y = y + h - y0 - urHeight / 2d;
+            return x < 0 || y > 0 || isInsideCorner(x, y, urWidth / 2d, urHeight / 2d);
+        }
+        // Potentially in the lower-right corner
+        x = x - x1 + lrWidth / 2d;
+        y = y - y1 + lrHeight / 2d;
+        return x < 0 || y < 0 || isInsideCorner(x, y, lrWidth / 2d, lrHeight / 2d);
+    }
+
+    @Override
+    public boolean contains(double x, double y, double w, double h) {
+        if (isEmpty() || w <= 0 || h <= 0) {
+            return false;
+        }
+        return (contains(x, y) &&
+                contains(x + w, y) &&
+                contains(x, y + h) &&
+                contains(x + w, y + h));
+    }
+
+    @Override
+    public PathIterator getPathIterator(final AffineTransform at) {
+        return new PathIterator() {
+            int index;
+
+            // ArcIterator.btan(Math.PI/2)
+            public static final double CtrlVal = 0.5522847498307933;
+            private final double ncv = 1.0 - CtrlVal;
+
+            // Coordinates of control points for Bezier curves approximating the straight lines
+            // and corners of the rounded rectangle.
+            private final double[][] ctrlpts = {
+                    {0.0, 0.0, 0.0, ulHeight},
+                    {0.0, 0.0, 1.0, -llHeight},
+                    {0.0, 0.0, 1.0, -llHeight * ncv, 0.0, ncv * llWidth, 1.0, 0.0, 0.0, llWidth,
+                            1.0, 0.0},
+                    {1.0, -lrWidth, 1.0, 0.0},
+                    {1.0, -lrWidth * ncv, 1.0, 0.0, 1.0, 0.0, 1.0, -lrHeight * ncv, 1.0, 0.0, 1.0,
+                            -lrHeight},
+                    {1.0, 0.0, 0.0, urHeight},
+                    {1.0, 0.0, 0.0, ncv * urHeight, 1.0, -urWidth * ncv, 0.0, 0.0, 1.0, -urWidth,
+                            0.0, 0.0},
+                    {0.0, ulWidth, 0.0, 0.0},
+                    {0.0, ncv * ulWidth, 0.0, 0.0, 0.0, 0.0, 0.0, ncv * ulHeight, 0.0, 0.0, 0.0,
+                            ulHeight},
+                    {}
+            };
+            private final int[] types = {
+                    SEG_MOVETO,
+                    SEG_LINETO, SEG_CUBICTO,
+                    SEG_LINETO, SEG_CUBICTO,
+                    SEG_LINETO, SEG_CUBICTO,
+                    SEG_LINETO, SEG_CUBICTO,
+                    SEG_CLOSE,
+            };
+
+            @Override
+            public int getWindingRule() {
+                return WIND_NON_ZERO;
+            }
+
+            @Override
+            public boolean isDone() {
+                return index >= ctrlpts.length;
+            }
+
+            @Override
+            public void next() {
+                index++;
+            }
+
+            @Override
+            public int currentSegment(float[] coords) {
+                if (isDone()) {
+                    throw new NoSuchElementException("roundrect iterator out of bounds");
+                }
+                int nc = 0;
+                double ctrls[] = ctrlpts[index];
+                for (int i = 0; i < ctrls.length; i += 4) {
+                    coords[nc++] = (float) (x + ctrls[i] * width + ctrls[i + 1] / 2d);
+                    coords[nc++] = (float) (y + ctrls[i + 2] * height + ctrls[i + 3] / 2d);
+                }
+                if (at != null) {
+                    at.transform(coords, 0, coords, 0, nc / 2);
+                }
+                return types[index];
+            }
+
+            @Override
+            public int currentSegment(double[] coords) {
+                if (isDone()) {
+                    throw new NoSuchElementException("roundrect iterator out of bounds");
+                }
+                int nc = 0;
+                double ctrls[] = ctrlpts[index];
+                for (int i = 0; i < ctrls.length; i += 4) {
+                    coords[nc++] = x + ctrls[i] * width + ctrls[i + 1] / 2d;
+                    coords[nc++] = y + ctrls[i + 2] * height + ctrls[i + 3] / 2d;
+                }
+                if (at != null) {
+                    at.transform(coords, 0, coords, 0, nc / 2);
+                }
+                return types[index];
+            }
+        };
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 2ad3c2e..4921073 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -44,6 +44,7 @@
 import com.android.internal.util.Protocol;
 
 import java.net.InetAddress;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 
@@ -892,6 +893,24 @@
     }
 
     /**
+     * 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.
@@ -1301,13 +1320,15 @@
      * @return the list of access points found in the most recent scan. An app must hold
      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
-     * in order to get valid results.
+     * in order to get valid results.  If there is a remote exception (e.g., either a communication
+     * problem with the system service or an exception within the framework) an empty list will be
+     * returned.
      */
     public List<ScanResult> getScanResults() {
         try {
             return mService.getScanResults(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            return null;
+            return new ArrayList<ScanResult>();
         }
     }