Merge "Minor clean-up in NetworkCapabilities"
diff --git a/Android.mk b/Android.mk
index 2517f6b..147d2cf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -173,6 +173,8 @@
     -knowntags ./frameworks/base/docs/knowntags.txt \
     -knowntags ./libcore/known_oj_tags.txt \
     -manifest ./frameworks/base/core/res/AndroidManifest.xml \
+    -hidePackage com.android.internal \
+    -hidePackage com.android.internal.util \
     -hidePackage com.android.okhttp \
     -hidePackage com.android.org.conscrypt \
     -hidePackage com.android.server \
diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk
index 200f92f..63867c9 100644
--- a/apct-tests/perftests/core/Android.mk
+++ b/apct-tests/perftests/core/Android.mk
@@ -12,6 +12,7 @@
     legacy-android-test
 
 LOCAL_PACKAGE_NAME := CorePerfTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_JNI_SHARED_LIBRARIES := libperftestscore_jni
 
diff --git a/apct-tests/perftests/multiuser/Android.mk b/apct-tests/perftests/multiuser/Android.mk
index e3f7775..4617af8 100644
--- a/apct-tests/perftests/multiuser/Android.mk
+++ b/apct-tests/perftests/multiuser/Android.mk
@@ -23,6 +23,7 @@
     android-support-test
 
 LOCAL_PACKAGE_NAME := MultiUserPerfTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/api/current.txt b/api/current.txt
index 8df028c..65dcae2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -33430,7 +33430,7 @@
     field public static final java.lang.String FEATURES = "features";
     field public static final int FEATURES_HD_CALL = 4; // 0x4
     field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
-    field public static final int FEATURES_RTT = 16; // 0x10
+    field public static final int FEATURES_RTT = 32; // 0x20
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final int FEATURES_WIFI = 8; // 0x8
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
@@ -35554,11 +35554,11 @@
     field public static final java.lang.String ADDRESS = "address";
   }
 
-  public static final class Telephony.CarrierIdentification implements android.provider.BaseColumns {
+  public static final class Telephony.CarrierId implements android.provider.BaseColumns {
     method public static android.net.Uri getUriForSubscriptionId(int);
-    field public static final java.lang.String CID = "carrier_id";
+    field public static final java.lang.String CARRIER_ID = "carrier_id";
+    field public static final java.lang.String CARRIER_NAME = "carrier_name";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String NAME = "carrier_name";
   }
 
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
@@ -39192,10 +39192,10 @@
     method public void onStateChanged(android.telecom.Call, int);
     method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
     field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
-    field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
-    field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
-    field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
-    field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5; // 0x5
+    field public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; // 0x2
+    field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4; // 0x4
+    field public static final int HANDOVER_FAILURE_UNKNOWN = 5; // 0x5
+    field public static final int HANDOVER_FAILURE_USER_REJECTED = 3; // 0x3
   }
 
   public static class Call.Details {
@@ -39952,11 +39952,9 @@
 package android.telephony {
 
   public final class AccessNetworkConstants {
-    ctor public AccessNetworkConstants();
   }
 
   public static final class AccessNetworkConstants.AccessNetworkType {
-    ctor public AccessNetworkConstants.AccessNetworkType();
     field public static final int CDMA2000 = 4; // 0x4
     field public static final int EUTRAN = 3; // 0x3
     field public static final int GERAN = 1; // 0x1
@@ -39966,7 +39964,6 @@
   }
 
   public static final class AccessNetworkConstants.EutranBand {
-    ctor public AccessNetworkConstants.EutranBand();
     field public static final int BAND_1 = 1; // 0x1
     field public static final int BAND_10 = 10; // 0xa
     field public static final int BAND_11 = 11; // 0xb
@@ -40018,7 +40015,6 @@
   }
 
   public static final class AccessNetworkConstants.GeranBand {
-    ctor public AccessNetworkConstants.GeranBand();
     field public static final int BAND_450 = 3; // 0x3
     field public static final int BAND_480 = 4; // 0x4
     field public static final int BAND_710 = 5; // 0x5
@@ -40036,7 +40032,6 @@
   }
 
   public static final class AccessNetworkConstants.UtranBand {
-    ctor public AccessNetworkConstants.UtranBand();
     field public static final int BAND_1 = 1; // 0x1
     field public static final int BAND_10 = 10; // 0xa
     field public static final int BAND_11 = 11; // 0xb
@@ -40089,6 +40084,8 @@
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING = "carrier_instant_lettering_escaped_chars_string";
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING = "carrier_instant_lettering_invalid_chars_string";
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT = "carrier_instant_lettering_length_limit_int";
+    field public static final java.lang.String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
+    field public static final java.lang.String KEY_CARRIER_NAME_STRING = "carrier_name_string";
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
@@ -40233,9 +40230,9 @@
     method public int getCid();
     method public int getLac();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -40249,9 +40246,9 @@
     method public int getCi();
     method public int getEarfcn();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -40265,8 +40262,8 @@
     method public int getCid();
     method public int getCpid();
     method public int getLac();
-    method public java.lang.String getMccStr();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMccString();
+    method public java.lang.String getMncString();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR;
   }
@@ -40275,9 +40272,9 @@
     method public int getCid();
     method public int getLac();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -40471,7 +40468,8 @@
   }
 
   public class NetworkScan {
-    method public void stop() throws android.os.RemoteException;
+    method public deprecated void stop() throws android.os.RemoteException;
+    method public void stopScan();
     field public static final int ERROR_INTERRUPTED = 10002; // 0x2712
     field public static final int ERROR_INVALID_SCAN = 2; // 0x2
     field public static final int ERROR_INVALID_SCANID = 10001; // 0x2711
@@ -40895,7 +40893,8 @@
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
     method public void listen(android.telephony.PhoneStateListener, int);
-    method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
+    method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
+    method public deprecated android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
     method public void sendDialerSpecialCode(java.lang.String);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
diff --git a/api/system-current.txt b/api/system-current.txt
index d3f7260..2f1b140 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4111,7 +4111,6 @@
 package android.telephony {
 
   public static final class AccessNetworkConstants.TransportType {
-    ctor public AccessNetworkConstants.TransportType();
     field public static final int WLAN = 2; // 0x2
     field public static final int WWAN = 1; // 0x1
   }
@@ -4505,6 +4504,7 @@
     field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
     field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
     field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+    field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
     field public static final int RESULT_OK = 0; // 0x0
     field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
   }
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index d33af4f..6ca2349 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -24,7 +24,6 @@
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.util.IntArray;
 import android.util.Log;
 
@@ -98,9 +97,8 @@
 
     /** @hide */
     NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp,
-            long endTimestamp) throws RemoteException, SecurityException {
-        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+            long endTimestamp, INetworkStatsService statsService)
+            throws RemoteException, SecurityException {
         // Open network stats session
         mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName());
         mCloseGuard.open("close");
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 5576e86..2357637 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -37,6 +37,8 @@
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * Provides access to network usage history and statistics. Usage data is collected in
  * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
@@ -107,9 +109,15 @@
      * {@hide}
      */
     public NetworkStatsManager(Context context) throws ServiceNotFoundException {
+        this(context, INetworkStatsService.Stub.asInterface(
+                ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public NetworkStatsManager(Context context, INetworkStatsService service) {
         mContext = context;
-        mService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
+        mService = service;
         setPollOnOpen(true);
     }
 
@@ -135,7 +143,8 @@
     public Bucket querySummaryForDevice(NetworkTemplate template,
             long startTime, long endTime) throws SecurityException, RemoteException {
         Bucket bucket = null;
-        NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
+                mService);
         bucket = stats.getDeviceSummaryForNetwork();
 
         stats.close();
@@ -208,7 +217,7 @@
         }
 
         NetworkStats stats;
-        stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
         stats.startSummaryEnumeration();
 
         stats.close();
@@ -245,7 +254,7 @@
         }
 
         NetworkStats result;
-        result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
         result.startSummaryEnumeration();
 
         return result;
@@ -295,7 +304,7 @@
 
         NetworkStats result;
         try {
-            result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+            result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
             result.startHistoryEnumeration(uid, tag);
         } catch (RemoteException e) {
             Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
@@ -341,7 +350,7 @@
         }
 
         NetworkStats result;
-        result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
         result.startUserUidEnumeration();
         return result;
     }
@@ -451,19 +460,20 @@
     }
 
     private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
-        NetworkTemplate template = null;
+        final NetworkTemplate template;
         switch (networkType) {
-            case ConnectivityManager.TYPE_MOBILE: {
-                template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
-                } break;
-            case ConnectivityManager.TYPE_WIFI: {
+            case ConnectivityManager.TYPE_MOBILE:
+                template = subscriberId == null
+                        ? NetworkTemplate.buildTemplateMobileWildcard()
+                        : NetworkTemplate.buildTemplateMobileAll(subscriberId);
+                break;
+            case ConnectivityManager.TYPE_WIFI:
                 template = NetworkTemplate.buildTemplateWifiWildcard();
-                } break;
-            default: {
+                break;
+            default:
                 throw new IllegalArgumentException("Cannot create template for network type "
                         + networkType + ", subscriberId '"
                         + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
-            }
         }
         return template;
     }
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index b255a43..419eda3 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -25,7 +25,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.media.AudioManager;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelUuid;
@@ -599,34 +598,6 @@
     }
 
     /**
-     * Tells remote device to adjust volume. Only if absolute volume is
-     * supported. Uses the following values:
-     * <ul>
-     * <li>{@link AudioManager#ADJUST_LOWER}</li>
-     * <li>{@link AudioManager#ADJUST_RAISE}</li>
-     * <li>{@link AudioManager#ADJUST_MUTE}</li>
-     * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
-     * </ul>
-     *
-     * @param direction One of the supported adjust values.
-     * @hide
-     */
-    public void adjustAvrcpAbsoluteVolume(int direction) {
-        if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null && isEnabled()) {
-                mService.adjustAvrcpAbsoluteVolume(direction);
-            }
-            if (mService == null) Log.w(TAG, "Proxy not attached to service");
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-    }
-
-    /**
      * Tells remote device to set an absolute volume. Only if absolute volume is supported
      *
      * @param volume Absolute volume to be set on AVRCP side
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index dc76152..be4e207 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -537,13 +537,14 @@
             "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
 
     /** The profile is in disconnected state */
-    public static final int STATE_DISCONNECTED = 0;
+    public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
     /** The profile is in connecting state */
-    public static final int STATE_CONNECTING = 1;
+    public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
     /** The profile is in connected state */
-    public static final int STATE_CONNECTED = 2;
+    public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
     /** The profile is in disconnecting state */
-    public static final int STATE_DISCONNECTING = 3;
+    public static final int STATE_DISCONNECTING =
+            BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
 
     /** @hide */
     public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
index 6e2654e..4631c56 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -25,6 +25,7 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
+import java.util.Comparator;
 
 /**
  * This class represents an IP prefix, i.e., a contiguous block of IP addresses aligned on a
@@ -187,6 +188,20 @@
     }
 
     /**
+     * Returns whether the specified prefix is entirely contained in this prefix.
+     *
+     * Note this is mathematical inclusion, so a prefix is always contained within itself.
+     * @param otherPrefix the prefix to test
+     * @hide
+     */
+    public boolean containsPrefix(IpPrefix otherPrefix) {
+        if (otherPrefix.getPrefixLength() < prefixLength) return false;
+        final byte[] otherAddress = otherPrefix.getRawAddress();
+        NetworkUtils.maskRawAddress(otherAddress, prefixLength);
+        return Arrays.equals(otherAddress, address);
+    }
+
+    /**
      * @hide
      */
     public boolean isIPv6() {
@@ -230,6 +245,38 @@
     }
 
     /**
+     * Returns a comparator ordering IpPrefixes by length, shorter to longer.
+     * Contents of the address will break ties.
+     * @hide
+     */
+    public static Comparator<IpPrefix> lengthComparator() {
+        return new Comparator<IpPrefix>() {
+            @Override
+            public int compare(IpPrefix prefix1, IpPrefix prefix2) {
+                if (prefix1.isIPv4()) {
+                    if (prefix2.isIPv6()) return -1;
+                } else {
+                    if (prefix2.isIPv4()) return 1;
+                }
+                final int p1len = prefix1.getPrefixLength();
+                final int p2len = prefix2.getPrefixLength();
+                if (p1len < p2len) return -1;
+                if (p2len < p1len) return 1;
+                final byte[] a1 = prefix1.address;
+                final byte[] a2 = prefix2.address;
+                final int len = a1.length < a2.length ? a1.length : a2.length;
+                for (int i = 0; i < len; ++i) {
+                    if (a1[i] < a2[i]) return -1;
+                    if (a1[i] > a2[i]) return 1;
+                }
+                if (a2.length < len) return 1;
+                if (a1.length < len) return -1;
+                return 0;
+            }
+        };
+    }
+
+    /**
      * Implement the Parcelable interface.
      */
     public static final Creator<IpPrefix> CREATOR =
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 768b6ee..2fc8c68 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -957,7 +957,16 @@
     /**
      * List of UIDs this network applies to. No restriction if null.
      * <p>
-     * This is typically (and at this time, only) used by VPN. This network is only available to
+     * For networks, mUids represent the list of network this applies to, and null means this
+     * network applies to all UIDs.
+     * For requests, mUids is the list of UIDs this network MUST apply to to match ; ALL UIDs
+     * must be included in a network so that they match. As an exception to the general rule,
+     * a null mUids field for requests mean "no requirements" rather than what the general rule
+     * would suggest ("must apply to all UIDs") : this is because this has shown to be what users
+     * of this API expect in practice. A network that must match all UIDs can still be
+     * expressed with a set ranging the entire set of possible UIDs.
+     * <p>
+     * mUids is typically (and at this time, only) used by VPN. This network is only available to
      * the UIDs in this list, and it is their default network. Apps in this list that wish to
      * bypass the VPN can do so iff the VPN app allows them to or if they are privileged. If this
      * member is null, then the network is not restricted by app UID. If it's an empty list, then
@@ -1079,8 +1088,7 @@
      * @hide
      */
     public boolean satisfiedByUids(NetworkCapabilities nc) {
-        if (null == nc.mUids) return true; // The network satisfies everything.
-        if (null == mUids) return false; // Not everything allowed but requires everything
+        if (null == nc.mUids || null == mUids) return true; // The network satisfies everything.
         for (UidRange requiredRange : mUids) {
             if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true;
             if (!nc.appliesToUidRange(requiredRange)) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index a3bf682..96826f8 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -131,12 +132,18 @@
      * needed in terms of {@link NetworkCapabilities} features
      */
     public static class Builder {
-        private final NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities();
+        private final NetworkCapabilities mNetworkCapabilities;
 
         /**
          * Default constructor for Builder.
          */
-        public Builder() {}
+        public Builder() {
+            // By default, restrict this request to networks available to this app.
+            // Apps can rescind this restriction, but ConnectivityService will enforce
+            // it for apps that do not have the NETWORK_SETTINGS permission.
+            mNetworkCapabilities = new NetworkCapabilities();
+            mNetworkCapabilities.setSingleUid(Process.myUid());
+        }
 
         /**
          * Build {@link NetworkRequest} give the current set of capabilities.
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index fe9563d..9a5d502 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,19 +16,20 @@
 
 package android.net;
 
-import java.io.FileDescriptor;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.Collection;
-import java.util.Locale;
-
 import android.os.Parcel;
 import android.util.Log;
 import android.util.Pair;
 
+import java.io.FileDescriptor;
+import java.math.BigInteger;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.TreeSet;
 
 /**
  * Native methods for managing network interfaces.
@@ -385,4 +386,72 @@
         result = builder.toString();
         return result;
     }
+
+    /**
+     * Returns a prefix set without overlaps.
+     *
+     * This expects the src set to be sorted from shorter to longer. Results are undefined
+     * failing this condition. The returned prefix set is sorted in the same order as the
+     * passed set, with the same comparator.
+     */
+    private static TreeSet<IpPrefix> deduplicatePrefixSet(final TreeSet<IpPrefix> src) {
+        final TreeSet<IpPrefix> dst = new TreeSet<>(src.comparator());
+        // Prefixes match addresses that share their upper part up to their length, therefore
+        // the only kind of possible overlap in two prefixes is strict inclusion of the longer
+        // (more restrictive) in the shorter (including equivalence if they have the same
+        // length).
+        // Because prefixes in the src set are sorted from shorter to longer, deduplicating
+        // is done by simply iterating in order, and not adding any longer prefix that is
+        // already covered by a shorter one.
+        newPrefixes:
+        for (IpPrefix newPrefix : src) {
+            for (IpPrefix existingPrefix : dst) {
+                if (existingPrefix.containsPrefix(newPrefix)) {
+                    continue newPrefixes;
+                }
+            }
+            dst.add(newPrefix);
+        }
+        return dst;
+    }
+
+    /**
+     * Returns how many IPv4 addresses match any of the prefixes in the passed ordered set.
+     *
+     * Obviously this returns an integral value between 0 and 2**32.
+     * The behavior is undefined if any of the prefixes is not an IPv4 prefix or if the
+     * set is not ordered smallest prefix to longer prefix.
+     *
+     * @param prefixes the set of prefixes, ordered by length
+     */
+    public static long routedIPv4AddressCount(final TreeSet<IpPrefix> prefixes) {
+        long routedIPCount = 0;
+        for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) {
+            if (!prefix.isIPv4()) {
+                Log.wtf(TAG, "Non-IPv4 prefix in routedIPv4AddressCount");
+            }
+            int rank = 32 - prefix.getPrefixLength();
+            routedIPCount += 1L << rank;
+        }
+        return routedIPCount;
+    }
+
+    /**
+     * Returns how many IPv6 addresses match any of the prefixes in the passed ordered set.
+     *
+     * This returns a BigInteger between 0 and 2**128.
+     * The behavior is undefined if any of the prefixes is not an IPv6 prefix or if the
+     * set is not ordered smallest prefix to longer prefix.
+     */
+    public static BigInteger routedIPv6AddressCount(final TreeSet<IpPrefix> prefixes) {
+        BigInteger routedIPCount = BigInteger.ZERO;
+        for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) {
+            if (!prefix.isIPv6()) {
+                Log.wtf(TAG, "Non-IPv6 prefix in routedIPv6AddressCount");
+            }
+            int rank = 128 - prefix.getPrefixLength();
+            routedIPCount = routedIPCount.add(BigInteger.ONE.shiftLeft(rank));
+        }
+        return routedIPCount;
+    }
 }
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index a94b928..f8a63ce 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -40,11 +40,12 @@
     public static final int ERROR_STARTING_IPV6                   = 5;
     public static final int ERROR_STARTING_IPREACHABILITYMONITOR  = 6;
     public static final int ERROR_INVALID_PROVISIONING            = 7;
+    public static final int ERROR_INTERFACE_NOT_FOUND             = 8;
 
     @IntDef(value = {
             PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
             ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
-            ERROR_INVALID_PROVISIONING,
+            ERROR_INVALID_PROVISIONING, ERROR_INTERFACE_NOT_FOUND,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface EventType {}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5e6f5f5..d693ee8 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -140,6 +140,12 @@
     public static final int CAMERASERVER_UID = 1047;
 
     /**
+     * Defines the UID/GID for the tethering DNS resolver (currently dnsmasq).
+     * @hide
+     */
+    public static final int DNS_TETHER_UID = 1052;
+
+    /**
      * Defines the UID/GID for the WebView zygote process.
      * @hide
      */
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.aidl b/core/java/android/os/connectivity/CellularBatteryStats.aidl
new file mode 100644
index 0000000..ca0a585
--- /dev/null
+++ b/core/java/android/os/connectivity/CellularBatteryStats.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.connectivity;
+
+/** {@hide} */
+parcelable CellularBatteryStats;
\ No newline at end of file
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
new file mode 100644
index 0000000..2593c85
--- /dev/null
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os.connectivity;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import android.telephony.ModemActivityInfo;
+import android.telephony.SignalStrength;
+
+import java.util.Arrays;
+
+/**
+ * API for Cellular power stats
+ *
+ * @hide
+ */
+public final class CellularBatteryStats implements Parcelable {
+
+  private long mLoggingDurationMs;
+  private long mKernelActiveTimeMs;
+  private long mNumPacketsTx;
+  private long mNumBytesTx;
+  private long mNumPacketsRx;
+  private long mNumBytesRx;
+  private long mSleepTimeMs;
+  private long mIdleTimeMs;
+  private long mRxTimeMs;
+  private long mEnergyConsumedMaMs;
+  private long[] mTimeInRatMs;
+  private long[] mTimeInRxSignalStrengthLevelMs;
+  private long[] mTxTimeMs;
+
+  public static final Parcelable.Creator<CellularBatteryStats> CREATOR = new
+      Parcelable.Creator<CellularBatteryStats>() {
+        public CellularBatteryStats createFromParcel(Parcel in) {
+          return new CellularBatteryStats(in);
+        }
+
+        public CellularBatteryStats[] newArray(int size) {
+          return new CellularBatteryStats[size];
+        }
+      };
+
+  public CellularBatteryStats() {
+    initialize();
+  }
+
+  public void writeToParcel(Parcel out, int flags) {
+    out.writeLong(mLoggingDurationMs);
+    out.writeLong(mKernelActiveTimeMs);
+    out.writeLong(mNumPacketsTx);
+    out.writeLong(mNumBytesTx);
+    out.writeLong(mNumPacketsRx);
+    out.writeLong(mNumBytesRx);
+    out.writeLong(mSleepTimeMs);
+    out.writeLong(mIdleTimeMs);
+    out.writeLong(mRxTimeMs);
+    out.writeLong(mEnergyConsumedMaMs);
+    out.writeLongArray(mTimeInRatMs);
+    out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
+    out.writeLongArray(mTxTimeMs);
+  }
+
+  public void readFromParcel(Parcel in) {
+    mLoggingDurationMs = in.readLong();
+    mKernelActiveTimeMs = in.readLong();
+    mNumPacketsTx = in.readLong();
+    mNumBytesTx = in.readLong();
+    mNumPacketsRx = in.readLong();
+    mNumBytesRx = in.readLong();
+    mSleepTimeMs = in.readLong();
+    mIdleTimeMs = in.readLong();
+    mRxTimeMs = in.readLong();
+    mEnergyConsumedMaMs = in.readLong();
+    in.readLongArray(mTimeInRatMs);
+    in.readLongArray(mTimeInRxSignalStrengthLevelMs);
+    in.readLongArray(mTxTimeMs);
+  }
+
+  public long getLoggingDurationMs() {
+    return mLoggingDurationMs;
+  }
+
+  public long getKernelActiveTimeMs() {
+    return mKernelActiveTimeMs;
+  }
+
+  public long getNumPacketsTx() {
+    return mNumPacketsTx;
+  }
+
+  public long getNumBytesTx() {
+    return mNumBytesTx;
+  }
+
+  public long getNumPacketsRx() {
+    return mNumPacketsRx;
+  }
+
+  public long getNumBytesRx() {
+    return mNumBytesRx;
+  }
+
+  public long getSleepTimeMs() {
+    return mSleepTimeMs;
+  }
+
+  public long getIdleTimeMs() {
+    return mIdleTimeMs;
+  }
+
+  public long getRxTimeMs() {
+    return mRxTimeMs;
+  }
+
+  public long getEnergyConsumedMaMs() {
+    return mEnergyConsumedMaMs;
+  }
+
+  public long[] getTimeInRatMs() {
+    return mTimeInRatMs;
+  }
+
+  public long[] getTimeInRxSignalStrengthLevelMs() {
+    return mTimeInRxSignalStrengthLevelMs;
+  }
+
+  public long[] getTxTimeMs() {
+    return mTxTimeMs;
+  }
+
+  public void setLoggingDurationMs(long t) {
+    mLoggingDurationMs = t;
+    return;
+  }
+
+  public void setKernelActiveTimeMs(long t) {
+    mKernelActiveTimeMs = t;
+    return;
+  }
+
+  public void setNumPacketsTx(long n) {
+    mNumPacketsTx = n;
+    return;
+  }
+
+  public void setNumBytesTx(long b) {
+    mNumBytesTx = b;
+    return;
+  }
+
+  public void setNumPacketsRx(long n) {
+    mNumPacketsRx = n;
+    return;
+  }
+
+  public void setNumBytesRx(long b) {
+    mNumBytesRx = b;
+    return;
+  }
+
+  public void setSleepTimeMs(long t) {
+    mSleepTimeMs = t;
+    return;
+  }
+
+  public void setIdleTimeMs(long t) {
+    mIdleTimeMs = t;
+    return;
+  }
+
+  public void setRxTimeMs(long t) {
+    mRxTimeMs = t;
+    return;
+  }
+
+  public void setEnergyConsumedMaMs(long e) {
+    mEnergyConsumedMaMs = e;
+    return;
+  }
+
+  public void setTimeInRatMs(long[] t) {
+    mTimeInRatMs = Arrays.copyOfRange(t, 0,
+        Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
+    return;
+  }
+
+  public void setTimeInRxSignalStrengthLevelMs(long[] t) {
+    mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
+        Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
+    return;
+  }
+
+  public void setTxTimeMs(long[] t) {
+    mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
+    return;
+  }
+
+  public int describeContents() {
+    return 0;
+  }
+
+  private CellularBatteryStats(Parcel in) {
+    initialize();
+    readFromParcel(in);
+  }
+
+  private void initialize() {
+    mLoggingDurationMs = 0;
+    mKernelActiveTimeMs = 0;
+    mNumPacketsTx = 0;
+    mNumBytesTx = 0;
+    mNumPacketsRx = 0;
+    mNumBytesRx = 0;
+    mSleepTimeMs = 0;
+    mIdleTimeMs = 0;
+    mRxTimeMs = 0;
+    mEnergyConsumedMaMs = 0;
+    mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
+    Arrays.fill(mTimeInRatMs, 0);
+    mTimeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+    Arrays.fill(mTimeInRxSignalStrengthLevelMs, 0);
+    mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
+    Arrays.fill(mTxTimeMs, 0);
+    return;
+  }
+}
\ No newline at end of file
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 60df467..70de09e 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -223,14 +223,14 @@
         /** Call was WIFI call. */
         public static final int FEATURES_WIFI = 1 << 3;
 
-        /** Call was on RTT at some point */
-        public static final int FEATURES_RTT = 1 << 4;
-
         /**
          * Indicates the call underwent Assisted Dialing.
          * @hide
          */
-        public static final Integer FEATURES_ASSISTED_DIALING_USED = 0x10;
+        public static final int FEATURES_ASSISTED_DIALING_USED = 1 << 4;
+
+        /** Call was on RTT at some point */
+        public static final int FEATURES_RTT = 1 << 5;
 
         /**
          * The phone number as the user entered it.
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index cb4f104..4bbee61 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -441,7 +441,7 @@
                 + ", state="
                 + mState
                 + ", CarrierIdentifier="
-                + mCarrierIdentifier.toString()
+                + mCarrierIdentifier
                 + ", policyRules="
                 + mPolicyRules
                 + ", accessRules="
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index b5a8aca..285a5f0 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -158,9 +158,9 @@
     private static Locale sIs24HourLocale;
     private static boolean sIs24Hour;
 
-
     /**
-     * Returns true if user preference is set to 24-hour format.
+     * Returns true if times should be formatted as 24 hour times, false if times should be
+     * formatted as 12 hour (AM/PM) times. Based on the user's chosen locale and other preferences.
      * @param context the context to use for the content resolver
      * @return true if 24 hour time format is selected, false otherwise.
      */
@@ -169,7 +169,8 @@
     }
 
     /**
-     * Returns true if user preference with the given user handle is set to 24-hour format.
+     * Returns true if times should be formatted as 24 hour times, false if times should be
+     * formatted as 12 hour (AM/PM) times. Based on the user's chosen locale and other preferences.
      * @param context the context to use for the content resolver
      * @param userHandle the user handle of the user to query.
      * @return true if 24 hour time format is selected, false otherwise.
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
new file mode 100644
index 0000000..6965dc0
--- /dev/null
+++ b/core/java/android/util/StatsLog.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+/**
+ * @hide
+ * Temporary dummy class for StatsLog. Will be removed.
+ */
+public final class StatsLog {
+    private static final String TAG = "StatsManager";
+
+    public static final int BLUETOOTH_ENABLED = 0;
+
+    public static final int BLUETOOTH_CONNECTION_STATE_CHANGED = 1;
+
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED = 2;
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__UNKNOWN = 0;
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__START = 1;
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__STOP = 2;
+
+    private StatsLog() {}
+
+    public static void write(int id, int field1) {}
+
+    public static void write(int id, int field1, int field2) {}
+
+    public static void write_non_chained(int id, int uid, String tag,
+            boolean field1, int field2, String field3) {}
+}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 4275e0b..f4f4317 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -22,6 +22,7 @@
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.os.ParcelFileDescriptor;
 import android.os.WorkSource;
+import android.os.connectivity.CellularBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
@@ -134,6 +135,9 @@
     void noteResetBleScan();
     void noteBleScanResults(in WorkSource ws, int numNewResults);
 
+    /** {@hide} */
+    CellularBatteryStats getCellularBatteryStats();
+
     HealthStatsParceler takeUidSnapshot(int uid);
     HealthStatsParceler[] takeUidSnapshots(in int[] uid);
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f26c0cd..10618d4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -30,6 +30,7 @@
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Build;
+import android.os.connectivity.CellularBatteryStats;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBatteryPropertiesRegistrar;
@@ -11262,6 +11263,51 @@
         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
     }
 
+    /*@hide */
+    public CellularBatteryStats getCellularBatteryStats() {
+        CellularBatteryStats s = new CellularBatteryStats();
+        final int which = STATS_SINCE_CHARGED;
+        final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
+        final ControllerActivityCounter counter = getModemControllerActivity();
+        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
+        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
+        final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
+        long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
+        for (int i = 0; i < timeInRatMs.length; i++) {
+           timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
+        }
+        long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+        for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
+           timeInRxSignalStrengthLevelMs[i]
+               = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
+        }
+        long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
+            counter.getTxTimeCounters().length)];
+        long totalTxTimeMs = 0;
+        for (int i = 0; i < txTimeMs.length; i++) {
+            txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
+            totalTxTimeMs += txTimeMs[i];
+        }
+        final long totalControllerActivityTimeMs
+            = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
+        final long sleepTimeMs
+            = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + totalTxTimeMs);
+        s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
+        s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
+        s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
+        s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
+        s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
+        s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
+        s.setSleepTimeMs(sleepTimeMs);
+        s.setIdleTimeMs(idleTimeMs);
+        s.setRxTimeMs(rxTimeMs);
+        s.setEnergyConsumedMaMs(energyConsumedMaMs);
+        s.setTimeInRatMs(timeInRatMs);
+        s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
+        s.setTxTimeMs(txTimeMs);
+        return s;
+    }
+
     @Override
     public LevelStepTracker getChargeLevelStepTracker() {
         return mChargeStepTracker;
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
new file mode 100644
index 0000000..06ae2d3
--- /dev/null
+++ b/core/proto/android/bluetooth/enums.proto
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 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.
+ */
+
+syntax = "proto2";
+package android.bluetooth;
+
+option java_outer_classname = "BluetoothProtoEnums";
+option java_multiple_files = true;
+
+// Bluetooth connection states.
+// Primarily used by android/bluetooth/BluetoothAdapter.java
+enum ConnectionStateEnum {
+  CONNECTION_STATE_DISCONNECTED = 0;
+  CONNECTION_STATE_CONNECTING = 1;
+  CONNECTION_STATE_CONNECTED = 2;
+  CONNECTION_STATE_DISCONNECTING = 3;
+}
\ No newline at end of file
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 23159f7..a49c6b1 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1579,7 +1579,7 @@
     <integer translatable="false" name="config_bluetooth_operating_voltage_mv">0</integer>
 
     <!-- Max number of connected audio devices supported by Bluetooth stack -->
-    <integer name="config_bluetooth_max_connected_audio_devices">1</integer>
+    <integer name="config_bluetooth_max_connected_audio_devices">5</integer>
 
     <!-- Whether supported profiles should be reloaded upon enabling bluetooth -->
     <bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool>
diff --git a/core/tests/BTtraffic/Android.mk b/core/tests/BTtraffic/Android.mk
index 7d83527..f826ae9 100644
--- a/core/tests/BTtraffic/Android.mk
+++ b/core/tests/BTtraffic/Android.mk
@@ -9,6 +9,7 @@
     $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := bttraffic
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/BroadcastRadioTests/Android.mk b/core/tests/BroadcastRadioTests/Android.mk
index c409e3a..69bae86 100644
--- a/core/tests/BroadcastRadioTests/Android.mk
+++ b/core/tests/BroadcastRadioTests/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_MODULE_TAGS := tests
 # TODO(b/13282254): uncomment when b/13282254 is fixed
 # LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test testng
 
diff --git a/core/tests/ConnectivityManagerTest/Android.mk b/core/tests/ConnectivityManagerTest/Android.mk
index 39cf4a4..93c53d2 100644
--- a/core/tests/ConnectivityManagerTest/Android.mk
+++ b/core/tests/ConnectivityManagerTest/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := ConnectivityManagerTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/core/tests/SvcMonitor/Android.mk b/core/tests/SvcMonitor/Android.mk
index 2b80455..94ddccb 100644
--- a/core/tests/SvcMonitor/Android.mk
+++ b/core/tests/SvcMonitor/Android.mk
@@ -9,6 +9,7 @@
     $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := svcmonitor
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/bandwidthtests/Android.mk b/core/tests/bandwidthtests/Android.mk
index 2af92df..56526bc 100644
--- a/core/tests/bandwidthtests/Android.mk
+++ b/core/tests/bandwidthtests/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 LOCAL_PACKAGE_NAME := BandwidthTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/core/tests/bluetoothtests/Android.mk b/core/tests/bluetoothtests/Android.mk
index f53419a..41582de 100644
--- a/core/tests/bluetoothtests/Android.mk
+++ b/core/tests/bluetoothtests/Android.mk
@@ -11,6 +11,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 LOCAL_PACKAGE_NAME := BluetoothTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index dbc9e5d..a802e75 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -40,6 +40,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy
 LOCAL_PACKAGE_NAME := FrameworksCoreTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_CERTIFICATE := platform
diff --git a/core/tests/coretests/DisabledTestApp/Android.mk b/core/tests/coretests/DisabledTestApp/Android.mk
index a5daedf..e4304f7 100644
--- a/core/tests/coretests/DisabledTestApp/Android.mk
+++ b/core/tests/coretests/DisabledTestApp/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := DisabledTestApp
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/EnabledTestApp/Android.mk b/core/tests/coretests/EnabledTestApp/Android.mk
index 4b986d3..cd37f08 100644
--- a/core/tests/coretests/EnabledTestApp/Android.mk
+++ b/core/tests/coretests/EnabledTestApp/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := EnabledTestApp
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/FrameworkCoreTests_apk.mk b/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
index 1e03270..8a7d72a5 100644
--- a/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
+++ b/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
@@ -6,6 +6,7 @@
 
 # Make sure every package name gets the FrameworkCoreTests_ prefix.
 LOCAL_PACKAGE_NAME := FrameworkCoreTests_$(LOCAL_PACKAGE_NAME)
+LOCAL_SDK_VERSION := current
 
 # Every package should have a native library
 LOCAL_JNI_SHARED_LIBRARIES := libframeworks_coretests_jni
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
index 47ee2cf..3261a1a 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := DownloadManagerTestApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 ifneq ($(TARGET_BUILD_VARIANT),user)
 # Need to run as system app to get access to Settings. This test won't work for user builds.
diff --git a/core/tests/notificationtests/Android.mk b/core/tests/notificationtests/Android.mk
index 0551eb6..910d5aa 100644
--- a/core/tests/notificationtests/Android.mk
+++ b/core/tests/notificationtests/Android.mk
@@ -10,6 +10,9 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := NotificationStressTests
+# Could build against SDK if it wasn't for the @RepetitiveTest annotation.
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     junit \
diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk
index 964348f..8f4b829 100644
--- a/core/tests/overlaytests/OverlayTest/Android.mk
+++ b/core/tests/overlaytests/OverlayTest/Android.mk
@@ -5,6 +5,8 @@
 
 LOCAL_PACKAGE_NAME := OverlayTest
 
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
 LOCAL_DEX_PREOPT := false
 
 LOCAL_JAVA_LIBRARIES += legacy-test
diff --git a/core/tests/packagemanagertests/Android.mk b/core/tests/packagemanagertests/Android.mk
index 5bfde78..f95231f 100644
--- a/core/tests/packagemanagertests/Android.mk
+++ b/core/tests/packagemanagertests/Android.mk
@@ -15,6 +15,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := FrameworksCorePackageManagerTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/core/tests/systemproperties/Android.mk b/core/tests/systemproperties/Android.mk
index 4c2e224..d58ed54 100644
--- a/core/tests/systemproperties/Android.mk
+++ b/core/tests/systemproperties/Android.mk
@@ -12,6 +12,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := FrameworksCoreSystemPropertiesTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
index 233d070..b142af0 100644
--- a/core/tests/utiltests/Android.mk
+++ b/core/tests/utiltests/Android.mk
@@ -22,6 +22,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := FrameworksUtilTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/location/tests/locationtests/Android.mk b/location/tests/locationtests/Android.mk
index 902cd96..c65f596 100644
--- a/location/tests/locationtests/Android.mk
+++ b/location/tests/locationtests/Android.mk
@@ -9,6 +9,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := FrameworksLocationTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/lowpan/tests/Android.mk b/lowpan/tests/Android.mk
index bb0a944..9043672 100644
--- a/lowpan/tests/Android.mk
+++ b/lowpan/tests/Android.mk
@@ -58,6 +58,7 @@
 	android.test.runner \
 
 LOCAL_PACKAGE_NAME := FrameworksLowpanApiTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_CERTIFICATE := platform
diff --git a/media/mca/samples/CameraEffectsRecordingSample/Android.mk b/media/mca/samples/CameraEffectsRecordingSample/Android.mk
index d3c4336..c81f2fc 100644
--- a/media/mca/samples/CameraEffectsRecordingSample/Android.mk
+++ b/media/mca/samples/CameraEffectsRecordingSample/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := CameraEffectsRecordingSample
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_PROGUARD_ENABLED := disabled
 
diff --git a/media/mca/tests/Android.mk b/media/mca/tests/Android.mk
index eb451f7..5da07c6 100644
--- a/media/mca/tests/Android.mk
+++ b/media/mca/tests/Android.mk
@@ -11,6 +11,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CameraEffectsTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_INSTRUMENTATION_FOR := CameraEffectsRecordingSample
 
diff --git a/media/packages/BluetoothMidiService/Android.mk b/media/packages/BluetoothMidiService/Android.mk
index 0565925..6f262bf 100644
--- a/media/packages/BluetoothMidiService/Android.mk
+++ b/media/packages/BluetoothMidiService/Android.mk
@@ -7,6 +7,7 @@
       $(call all-java-files-under,src)
 
 LOCAL_PACKAGE_NAME := BluetoothMidiService
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/media/tests/EffectsTest/Android.mk b/media/tests/EffectsTest/Android.mk
index 25b4fe4..a066950 100644
--- a/media/tests/EffectsTest/Android.mk
+++ b/media/tests/EffectsTest/Android.mk
@@ -6,5 +6,6 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := EffectsTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index 0d9f42b..3c6119e 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -14,5 +14,6 @@
     legacy-android-test
 
 LOCAL_PACKAGE_NAME := mediaframeworktest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/media/tests/NativeMidiDemo/Android.mk b/media/tests/NativeMidiDemo/Android.mk
index 6b08f6b..316858f 100644
--- a/media/tests/NativeMidiDemo/Android.mk
+++ b/media/tests/NativeMidiDemo/Android.mk
@@ -19,6 +19,7 @@
 LOCAL_PACKAGE_NAME := NativeMidiDemo
 
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_SRC_FILES := $(call all-java-files-under, java)
 
diff --git a/media/tests/ScoAudioTest/Android.mk b/media/tests/ScoAudioTest/Android.mk
index ab12865..2ad91a4 100644
--- a/media/tests/ScoAudioTest/Android.mk
+++ b/media/tests/ScoAudioTest/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 #LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/media/tests/SoundPoolTest/Android.mk b/media/tests/SoundPoolTest/Android.mk
index 7f947c0..9ca33c8 100644
--- a/media/tests/SoundPoolTest/Android.mk
+++ b/media/tests/SoundPoolTest/Android.mk
@@ -6,5 +6,6 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := SoundPoolTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/packages/BackupRestoreConfirmation/Android.mk b/packages/BackupRestoreConfirmation/Android.mk
index b84c07f..532d272 100644
--- a/packages/BackupRestoreConfirmation/Android.mk
+++ b/packages/BackupRestoreConfirmation/Android.mk
@@ -22,6 +22,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := BackupRestoreConfirmation
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk
index 576debc..e6e0ad3 100644
--- a/packages/CaptivePortalLogin/Android.mk
+++ b/packages/CaptivePortalLogin/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CaptivePortalLogin
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/packages/CarrierDefaultApp/Android.mk b/packages/CarrierDefaultApp/Android.mk
index 82be132..df88afd 100644
--- a/packages/CarrierDefaultApp/Android.mk
+++ b/packages/CarrierDefaultApp/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CarrierDefaultApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.mk b/packages/CarrierDefaultApp/tests/unit/Android.mk
index 63bd0b1..a95ccfe 100644
--- a/packages/CarrierDefaultApp/tests/unit/Android.mk
+++ b/packages/CarrierDefaultApp/tests/unit/Android.mk
@@ -27,6 +27,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CarrierDefaultAppUnitTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_INSTRUMENTATION_FOR := CarrierDefaultApp
 
diff --git a/packages/CompanionDeviceManager/Android.mk b/packages/CompanionDeviceManager/Android.mk
index f730356..7ec6e11 100644
--- a/packages/CompanionDeviceManager/Android.mk
+++ b/packages/CompanionDeviceManager/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CompanionDeviceManager
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/packages/DefaultContainerService/Android.mk b/packages/DefaultContainerService/Android.mk
index 0de2c1f..01c8768 100644
--- a/packages/DefaultContainerService/Android.mk
+++ b/packages/DefaultContainerService/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := DefaultContainerService
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_JNI_SHARED_LIBRARIES := libdefcontainer_jni
 
diff --git a/packages/EasterEgg/Android.mk b/packages/EasterEgg/Android.mk
index d4c1e70..dac3ed6 100644
--- a/packages/EasterEgg/Android.mk
+++ b/packages/EasterEgg/Android.mk
@@ -15,6 +15,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := EasterEgg
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/packages/ExtServices/Android.mk b/packages/ExtServices/Android.mk
index d0c2b9f..467d7ed 100644
--- a/packages/ExtServices/Android.mk
+++ b/packages/ExtServices/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := ExtServices
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/packages/ExtServices/tests/Android.mk b/packages/ExtServices/tests/Android.mk
index cb3c352..f18904d 100644
--- a/packages/ExtServices/tests/Android.mk
+++ b/packages/ExtServices/tests/Android.mk
@@ -18,6 +18,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := ExtServicesUnitTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_INSTRUMENTATION_FOR := ExtServices
 
diff --git a/packages/ExtShared/Android.mk b/packages/ExtShared/Android.mk
index d8052df..7dbf79f 100644
--- a/packages/ExtShared/Android.mk
+++ b/packages/ExtShared/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := ExtShared
+LOCAL_SDK_VERSION := current
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/packages/ExternalStorageProvider/Android.mk b/packages/ExternalStorageProvider/Android.mk
index db825ff4..9e99313 100644
--- a/packages/ExternalStorageProvider/Android.mk
+++ b/packages/ExternalStorageProvider/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := ExternalStorageProvider
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/FakeOemFeatures/Android.mk b/packages/FakeOemFeatures/Android.mk
index d96bb3d..43de8e5 100644
--- a/packages/FakeOemFeatures/Android.mk
+++ b/packages/FakeOemFeatures/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := FakeOemFeatures
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 LOCAL_PROGUARD_ENABLED := disabled
diff --git a/packages/FusedLocation/Android.mk b/packages/FusedLocation/Android.mk
index 7406eaf4..d795870 100644
--- a/packages/FusedLocation/Android.mk
+++ b/packages/FusedLocation/Android.mk
@@ -22,6 +22,7 @@
 LOCAL_JAVA_LIBRARIES := com.android.location.provider
 
 LOCAL_PACKAGE_NAME := FusedLocation
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/InputDevices/Android.mk b/packages/InputDevices/Android.mk
index e7190dc..6de1f1d 100644
--- a/packages/InputDevices/Android.mk
+++ b/packages/InputDevices/Android.mk
@@ -22,6 +22,7 @@
 LOCAL_JAVA_LIBRARIES := 
 
 LOCAL_PACKAGE_NAME := InputDevices
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/MtpDocumentsProvider/Android.mk b/packages/MtpDocumentsProvider/Android.mk
index a9e9b2e..2d62a07 100644
--- a/packages/MtpDocumentsProvider/Android.mk
+++ b/packages/MtpDocumentsProvider/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_PACKAGE_NAME := MtpDocumentsProvider
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := media
 LOCAL_PRIVILEGED_MODULE := true
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/packages/MtpDocumentsProvider/perf_tests/Android.mk b/packages/MtpDocumentsProvider/perf_tests/Android.mk
index f0d4878..6504af1 100644
--- a/packages/MtpDocumentsProvider/perf_tests/Android.mk
+++ b/packages/MtpDocumentsProvider/perf_tests/Android.mk
@@ -5,6 +5,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 LOCAL_PACKAGE_NAME := MtpDocumentsProviderPerfTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
 LOCAL_CERTIFICATE := media
 
diff --git a/packages/MtpDocumentsProvider/tests/Android.mk b/packages/MtpDocumentsProvider/tests/Android.mk
index 148cd0d..25b585f 100644
--- a/packages/MtpDocumentsProvider/tests/Android.mk
+++ b/packages/MtpDocumentsProvider/tests/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 LOCAL_PACKAGE_NAME := MtpDocumentsProviderTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_INSTRUMENTATION_FOR := MtpDocumentsProvider
 LOCAL_CERTIFICATE := media
 LOCAL_COMPATIBILITY_SUITE := device-tests
diff --git a/packages/Osu/Android.mk b/packages/Osu/Android.mk
index 1d45aa9..63c7578 100644
--- a/packages/Osu/Android.mk
+++ b/packages/Osu/Android.mk
@@ -14,6 +14,7 @@
 LOCAL_JAVA_LIBRARIES := telephony-common ims-common bouncycastle conscrypt
 
 LOCAL_PACKAGE_NAME := Osu
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/Osu2/Android.mk b/packages/Osu2/Android.mk
index 05586f0..063ac7e 100644
--- a/packages/Osu2/Android.mk
+++ b/packages/Osu2/Android.mk
@@ -9,6 +9,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := Osu2
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/Osu2/tests/Android.mk b/packages/Osu2/tests/Android.mk
index 4b6e0e6..8d5a3995 100644
--- a/packages/Osu2/tests/Android.mk
+++ b/packages/Osu2/tests/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_JACK_FLAGS := --multi-dex native
 
 LOCAL_PACKAGE_NAME := OsuTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_INSTRUMENTATION_FOR := Osu2
diff --git a/packages/PrintRecommendationService/Android.mk b/packages/PrintRecommendationService/Android.mk
index 66cb057..fa1eb0d 100644
--- a/packages/PrintRecommendationService/Android.mk
+++ b/packages/PrintRecommendationService/Android.mk
@@ -22,8 +22,8 @@
 
 LOCAL_PACKAGE_NAME := PrintRecommendationService
 
-include $(BUILD_PACKAGE)
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
-LOCAL_SDK_VERSION := system_current
+include $(BUILD_PACKAGE)
 
 include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
index 19e44e3..67ef6b4 100644
--- a/packages/PrintSpooler/Android.mk
+++ b/packages/PrintSpooler/Android.mk
@@ -26,6 +26,7 @@
         src/com/android/printspooler/renderer/IPdfEditor.aidl
 
 LOCAL_PACKAGE_NAME := PrintSpooler
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_JNI_SHARED_LIBRARIES := libprintspooler_jni
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v7-recyclerview
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.mk b/packages/PrintSpooler/tests/outofprocess/Android.mk
index 3c02453..56afd89 100644
--- a/packages/PrintSpooler/tests/outofprocess/Android.mk
+++ b/packages/PrintSpooler/tests/outofprocess/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4
 
 LOCAL_PACKAGE_NAME := PrintSpoolerOutOfProcessTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index e261570..4000226 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -73,4 +73,9 @@
          fraction of a pixel.-->
     <fraction name="battery_subpixel_smoothing_left">0%</fraction>
     <fraction name="battery_subpixel_smoothing_right">0%</fraction>
+
+    <!-- SignalDrawable -->
+    <dimen name="signal_icon_size">17dp</dimen>
+    <!-- How far to inset the rounded edges -->
+    <dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 3cda9c9..784c714 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -444,6 +444,7 @@
 
     private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
                                              int bluetoothProfile) {
+        mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
         synchronized (mCallbacks) {
             for (BluetoothCallback callback : mCallbacks) {
                 callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index e1ebbc4..f6ec6a8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -27,6 +27,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.bluetooth.BluetoothAdapter;
+import android.support.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
 
@@ -461,12 +462,12 @@
     }
 
     /**
-     * Set the device status as active or non-active per Bluetooth profile.
+     * Update the device status as active or non-active per Bluetooth profile.
      *
      * @param isActive true if the device is active
      * @param bluetoothProfile the Bluetooth profile
      */
-    public void setActiveDevice(boolean isActive, int bluetoothProfile) {
+    public void onActiveDeviceChanged(boolean isActive, int bluetoothProfile) {
         boolean changed = false;
         switch (bluetoothProfile) {
         case BluetoothProfile.A2DP:
@@ -478,7 +479,7 @@
             mIsActiveDeviceHeadset = isActive;
             break;
         default:
-            Log.w(TAG, "setActiveDevice: unknown profile " + bluetoothProfile +
+            Log.w(TAG, "onActiveDeviceChanged: unknown profile " + bluetoothProfile +
                     " isActive " + isActive);
             break;
         }
@@ -487,6 +488,26 @@
         }
     }
 
+    /**
+     * Get the device status as active or non-active per Bluetooth profile.
+     *
+     * @param bluetoothProfile the Bluetooth profile
+     * @return true if the device is active
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public boolean isActiveDevice(int bluetoothProfile) {
+        switch (bluetoothProfile) {
+            case BluetoothProfile.A2DP:
+                return mIsActiveDeviceA2dp;
+            case BluetoothProfile.HEADSET:
+                return mIsActiveDeviceHeadset;
+            default:
+                Log.w(TAG, "getActiveDevice: unknown profile " + bluetoothProfile);
+                break;
+        }
+        return false;
+    }
+
     void setRssi(short rssi) {
         if (mRssi != rssi) {
             mRssi = rssi;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index c3ff617..a8e0039 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -24,6 +24,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
@@ -167,6 +168,15 @@
             }
         }
     }
+
+    public synchronized void onActiveDeviceChanged(CachedBluetoothDevice activeDevice,
+                                                   int bluetoothProfile) {
+        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+            boolean isActive = Objects.equals(cachedDevice, activeDevice);
+            cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile);
+        }
+    }
+
     private void log(String msg) {
         if (DEBUG) {
             Log.d(TAG, msg);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
rename to packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
index 15ef742..846e30d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.settingslib.graph;
 
 import android.animation.ArgbEvaluator;
 import android.annotation.IntRange;
@@ -36,7 +36,6 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.Utils;
-import com.android.systemui.qs.SlashDrawable;
 
 public class SignalDrawable extends Drawable {
 
@@ -458,6 +457,7 @@
     }
 
     private final class SlashArtist {
+        private static final float CORNER_RADIUS = 1f;
         // These values are derived in un-rotated (vertical) orientation
         private static final float SLASH_WIDTH = 1.8384776f;
         private static final float SLASH_HEIGHT = 22f;
@@ -478,7 +478,7 @@
 
         void draw(int height, int width, @NonNull Canvas canvas, Paint paint) {
             Matrix m = new Matrix();
-            final float radius = scale(SlashDrawable.CORNER_RADIUS, width);
+            final float radius = scale(CORNER_RADIUS, width);
             updateRect(
                     scale(LEFT, width),
                     scale(TOP, height),
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 7ace048..5bd9e4c 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_JACK_FLAGS := --multi-dex native
 
 LOCAL_PACKAGE_NAME := SettingsLibTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index 55b635e..bc28863 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -21,6 +21,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := SettingsLibShell
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
new file mode 100644
index 0000000..d6b2006
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.Collection;
+
+@RunWith(RobolectricTestRunner.class)
+public class CachedBluetoothDeviceManagerTest {
+    private final static String DEVICE_NAME_1 = "TestName_1";
+    private final static String DEVICE_NAME_2 = "TestName_2";
+    private final static String DEVICE_ALIAS_1 = "TestAlias_1";
+    private final static String DEVICE_ALIAS_2 = "TestAlias_2";
+    private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
+    private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
+    private final BluetoothClass DEVICE_CLASS_1 =
+        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+    private final BluetoothClass DEVICE_CLASS_2 =
+        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+    @Mock
+    private LocalBluetoothAdapter mLocalAdapter;
+    @Mock
+    private LocalBluetoothProfileManager mLocalProfileManager;
+    @Mock
+    private LocalBluetoothManager mLocalBluetoothManager;
+    @Mock
+    private BluetoothEventManager mBluetoothEventManager;
+    @Mock
+    private HeadsetProfile mHfpProfile;
+    @Mock
+    private A2dpProfile mA2dpProfile;
+    @Mock
+    private PanProfile mPanProfile;
+    @Mock
+    private BluetoothDevice mDevice1;
+    @Mock
+    private BluetoothDevice mDevice2;
+    private CachedBluetoothDeviceManager mCachedDeviceManager;
+    private Context mContext;
+    private String[] mActiveDeviceStringsArray;
+    private String mActiveDeviceStringNone;
+    private String mActiveDeviceStringAll;
+    private String mActiveDeviceStringMedia;
+    private String mActiveDeviceStringPhone;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
+        when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
+        when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
+        when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
+        when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
+        when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
+        when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1);
+        when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
+
+        when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
+        when(mLocalAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+        when(mHfpProfile.isProfileReady()).thenReturn(true);
+        when(mA2dpProfile.isProfileReady()).thenReturn(true);
+        when(mPanProfile.isProfileReady()).thenReturn(true);
+        mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
+    }
+
+    /**
+     * Test to verify addDevice().
+     */
+    @Test
+    public void testAddDevice_validCachedDevices_devicesAdded() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+
+        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).contains(cachedDevice2);
+
+        assertThat(mCachedDeviceManager.findDevice(mDevice1)).isEqualTo(cachedDevice1);
+        assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2);
+    }
+
+    /**
+     * Test to verify getName().
+     */
+    @Test
+    public void testGetName_validCachedDevice_nameFound() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1);
+    }
+
+    /**
+     * Test to verify onDeviceNameUpdated().
+     */
+    @Test
+    public void testOnDeviceNameUpdated_validName_nameUpdated() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1);
+
+        final String newAliasName = "NewAliasName";
+        when(mDevice1.getAliasName()).thenReturn(newAliasName);
+        mCachedDeviceManager.onDeviceNameUpdated(mDevice1);
+        assertThat(cachedDevice1.getName()).isEqualTo(newAliasName);
+    }
+
+    /**
+     * Test to verify clearNonBondedDevices().
+     */
+    @Test
+    public void testClearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
+        mCachedDeviceManager.clearNonBondedDevices();
+        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).contains(cachedDevice2);
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        mCachedDeviceManager.clearNonBondedDevices();
+        devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).doesNotContain(cachedDevice2);
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        mCachedDeviceManager.clearNonBondedDevices();
+        devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).doesNotContain(cachedDevice1);
+        assertThat(devices).doesNotContain(cachedDevice2);
+    }
+
+    /**
+     * Test to verify onBtClassChanged().
+     */
+    @Test
+    public void testOnBtClassChanged_validBtClass_classChanged() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1);
+
+        final BluetoothClass newBluetoothClass = DEVICE_CLASS_2;
+        when(mDevice1.getBluetoothClass()).thenReturn(newBluetoothClass);
+        mCachedDeviceManager.onBtClassChanged(mDevice1);
+        assertThat(cachedDevice1.getBtClass()).isEqualTo(newBluetoothClass);
+    }
+
+    /**
+     * Test to verify onDeviceDisappeared().
+     */
+    @Test
+    public void testOnDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isFalse();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isTrue();
+    }
+
+    /**
+     * Test to verify onActiveDeviceChanged().
+     */
+    @Test
+    public void testOnActiveDeviceChanged_connectedDevices_activeDeviceChanged() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+
+        // Connect both devices for A2DP and HFP
+        cachedDevice1.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice2.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice1.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice2.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+
+        // Verify that both devices are connected and none is Active
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+
+        // The first device is active for A2DP, the second device is active for HFP
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.A2DP);
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+        // The first device is active for A2DP and HFP
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+
+        // The second device is active for A2DP and HFP
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.A2DP);
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+        // No active device for A2DP
+        mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.A2DP);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+        // No active device for HFP
+        mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 1481161..2c91d5a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -152,7 +152,7 @@
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for A2DP and test connection state summary
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
 
         // Test with battery level
@@ -168,7 +168,7 @@
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set A2DP profile to be connected, Active and test connection state summary
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
 
         // Set A2DP profile to be disconnected and test connection state summary
@@ -184,7 +184,7 @@
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for HFP and test connection state summary
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
 
         // Test with battery level
@@ -200,7 +200,7 @@
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set HFP profile to be connected, Active and test connection state summary
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
 
         // Set HFP profile to be disconnected and test connection state summary
@@ -217,8 +217,8 @@
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for A2DP and HFP and test connection state summary
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
 
         // Test with battery level
@@ -227,16 +227,16 @@
                 "Connected, battery 10%, active");
 
         // Disconnect A2DP only and test connection state summary
-        mCachedDevice.setActiveDevice(false, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "Connected (no media), battery 10%, active(phone)");
 
         // Disconnect HFP only and test connection state summary
-        mCachedDevice.setActiveDevice(false, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "Connected (no phone), battery 10%, active(media)");
 
@@ -245,8 +245,8 @@
         // Set A2DP and HFP profiles to be connected, Active and test connection state summary
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
 
         // Set A2DP and HFP profiles to be disconnected and test connection state summary
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
index 069e83a..74ce919 100644
--- a/packages/SettingsProvider/Android.mk
+++ b/packages/SettingsProvider/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 
 LOCAL_PACKAGE_NAME := SettingsProvider
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/SettingsProvider/test/Android.mk b/packages/SettingsProvider/test/Android.mk
index a9707d4..091ba90 100644
--- a/packages/SettingsProvider/test/Android.mk
+++ b/packages/SettingsProvider/test/Android.mk
@@ -15,6 +15,7 @@
 LOCAL_JAVA_LIBRARIES := legacy-android-test
 
 LOCAL_PACKAGE_NAME := SettingsProviderTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/packages/SharedStorageBackup/Android.mk b/packages/SharedStorageBackup/Android.mk
index a213965f..2e07ab1 100644
--- a/packages/SharedStorageBackup/Android.mk
+++ b/packages/SharedStorageBackup/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
 LOCAL_PACKAGE_NAME := SharedStorageBackup
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/Shell/Android.mk b/packages/Shell/Android.mk
index 935d09b..5713dc6 100644
--- a/packages/Shell/Android.mk
+++ b/packages/Shell/Android.mk
@@ -15,6 +15,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
 
 LOCAL_PACKAGE_NAME := Shell
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk
index 48b757c..cf60fb4 100644
--- a/packages/Shell/tests/Android.mk
+++ b/packages/Shell/tests/Android.mk
@@ -16,6 +16,7 @@
     legacy-android-test \
 
 LOCAL_PACKAGE_NAME := ShellTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_INSTRUMENTATION_FOR := Shell
 
diff --git a/packages/StatementService/Android.mk b/packages/StatementService/Android.mk
index 470d824..b9b29e7 100644
--- a/packages/StatementService/Android.mk
+++ b/packages/StatementService/Android.mk
@@ -22,6 +22,7 @@
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
 LOCAL_PACKAGE_NAME := StatementService
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_PRIVILEGED_MODULE := true
 
 LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 2fd7e87..2bfd3a5 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -48,6 +48,7 @@
 LOCAL_JAVA_LIBRARIES += android.car
 
 LOCAL_PACKAGE_NAME := SystemUI
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk
index e22dddb..8634684 100644
--- a/packages/SystemUI/plugin/Android.mk
+++ b/packages/SystemUI/plugin/Android.mk
@@ -32,6 +32,7 @@
 
 # Dummy to generate .toc files.
 LOCAL_PACKAGE_NAME := PluginDummyLib
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_JAVA_LIBRARIES := SystemUIPluginLib
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9901f6f..acc8b6d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -822,8 +822,6 @@
     <dimen name="default_gear_space">18dp</dimen>
     <dimen name="cell_overlay_padding">18dp</dimen>
 
-    <dimen name="signal_icon_size">17dp</dimen>
-
     <dimen name="hwui_edge_margin">16dp</dimen>
 
     <dimen name="global_actions_panel_width">120dp</dimen>
@@ -850,11 +848,6 @@
     <dimen name="rounded_corner_content_padding">0dp</dimen>
     <dimen name="nav_content_padding">0dp</dimen>
 
-    <!-- Intended corner radius when drawing the mobile signal -->
-    <dimen name="stat_sys_mobile_signal_corner_radius">0.75dp</dimen>
-    <!-- How far to inset the rounded edges -->
-    <dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
-
     <!-- Home button padding for sizing -->
     <dimen name="home_padding">15dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 5f260938..e7eefe8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -19,12 +19,12 @@
 import android.service.quicksettings.Tile;
 import android.widget.ImageView;
 
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile.Icon;
 import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 
 import java.util.Objects;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 274244e..ad6261b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -35,9 +35,9 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 677fa81..0304086 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -16,10 +16,10 @@
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.ImageView;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 8516278..f0854ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -35,8 +35,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 27c16d5..fce71b9 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
 
 LOCAL_PACKAGE_NAME := SystemUITests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index d14b23e..96d623e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -31,14 +31,15 @@
 import android.telephony.TelephonyManager;
 import android.util.Log;
 import com.android.internal.telephony.cdma.EriInfo;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.statusbar.phone.SignalDrawable;
+import com.android.systemui.SysuiTestCase;
+
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
-import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 173cc4c..d5294ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -28,9 +28,9 @@
 
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 
 import org.junit.Ignore;
 import org.junit.Test;
diff --git a/packages/VpnDialogs/Android.mk b/packages/VpnDialogs/Android.mk
index 4c80a26..8507646 100644
--- a/packages/VpnDialogs/Android.mk
+++ b/packages/VpnDialogs/Android.mk
@@ -27,5 +27,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := VpnDialogs
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/packages/WAPPushManager/Android.mk b/packages/WAPPushManager/Android.mk
index 60f093f..91526dd 100644
--- a/packages/WAPPushManager/Android.mk
+++ b/packages/WAPPushManager/Android.mk
@@ -9,6 +9,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := WAPPushManager
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_JAVA_LIBRARIES += telephony-common
 LOCAL_STATIC_JAVA_LIBRARIES += android-common
diff --git a/packages/WAPPushManager/tests/Android.mk b/packages/WAPPushManager/tests/Android.mk
index 1dea798..8ad0018 100644
--- a/packages/WAPPushManager/tests/Android.mk
+++ b/packages/WAPPushManager/tests/Android.mk
@@ -32,6 +32,7 @@
 # automatically get all of its classes loaded into our environment.
 
 LOCAL_PACKAGE_NAME := WAPPushManagerTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_INSTRUMENTATION_FOR := WAPPushManager
 
diff --git a/packages/WallpaperBackup/Android.mk b/packages/WallpaperBackup/Android.mk
index cf04249..a6426a6 100644
--- a/packages/WallpaperBackup/Android.mk
+++ b/packages/WallpaperBackup/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
 LOCAL_PACKAGE_NAME := WallpaperBackup
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := false
 
diff --git a/packages/WallpaperCropper/Android.mk b/packages/WallpaperCropper/Android.mk
index 0254673..e0a0ef41 100644
--- a/packages/WallpaperCropper/Android.mk
+++ b/packages/WallpaperCropper/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_PACKAGE_NAME := WallpaperCropper
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/overlays/SysuiDarkThemeOverlay/Android.mk b/packages/overlays/SysuiDarkThemeOverlay/Android.mk
index 4b83058..7b277bc 100644
--- a/packages/overlays/SysuiDarkThemeOverlay/Android.mk
+++ b/packages/overlays/SysuiDarkThemeOverlay/Android.mk
@@ -9,5 +9,6 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := SysuiDarkThemeOverlay
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_RRO_PACKAGE)
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
index 3c4e951..5be90c0 100644
--- a/packages/services/PacProcessor/Android.mk
+++ b/packages/services/PacProcessor/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := PacProcessor
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor
diff --git a/packages/services/Proxy/Android.mk b/packages/services/Proxy/Android.mk
index d5546b2..ce1715f 100644
--- a/packages/services/Proxy/Android.mk
+++ b/packages/services/Proxy/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := ProxyHandler
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/sax/tests/saxtests/Android.mk b/sax/tests/saxtests/Android.mk
index d3fbd05..f029498 100644
--- a/sax/tests/saxtests/Android.mk
+++ b/sax/tests/saxtests/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 LOCAL_PACKAGE_NAME := FrameworksSaxTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index fd2ef18..6c24e94 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.NETID_UNSET;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
@@ -1329,9 +1330,8 @@
         if (nai != null) {
             synchronized (nai) {
                 if (nai.networkCapabilities != null) {
-                    // TODO : don't remove the UIDs when communicating with processes
-                    // that have the NETWORK_SETTINGS permission.
-                    return networkCapabilitiesWithoutUids(nai.networkCapabilities);
+                    return networkCapabilitiesWithoutUidsUnlessAllowed(nai.networkCapabilities,
+                            Binder.getCallingPid(), Binder.getCallingUid());
                 }
             }
         }
@@ -1344,10 +1344,18 @@
         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
     }
 
-    private NetworkCapabilities networkCapabilitiesWithoutUids(NetworkCapabilities nc) {
+    private NetworkCapabilities networkCapabilitiesWithoutUidsUnlessAllowed(
+            NetworkCapabilities nc, int callerPid, int callerUid) {
+        if (checkSettingsPermission(callerPid, callerUid)) return new NetworkCapabilities(nc);
         return new NetworkCapabilities(nc).setUids(null);
     }
 
+    private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
+        if (!checkSettingsPermission()) {
+            nc.setSingleUid(Binder.getCallingUid());
+        }
+    }
+
     @Override
     public NetworkState[] getAllNetworkState() {
         // Require internal since we're handing out IMSI details
@@ -1546,6 +1554,16 @@
                 "ConnectivityService");
     }
 
+    private boolean checkSettingsPermission() {
+        return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.NETWORK_SETTINGS);
+    }
+
+    private boolean checkSettingsPermission(int pid, int uid) {
+        return PERMISSION_GRANTED == mContext.checkPermission(
+                android.Manifest.permission.NETWORK_SETTINGS, pid, uid);
+    }
+
     private void enforceTetherAccessPermission() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -4213,13 +4231,12 @@
             enforceMeteredApnPolicy(networkCapabilities);
         }
         ensureRequestableCapabilities(networkCapabilities);
-        // Set the UID range for this request to the single UID of the requester.
+        // Set the UID range for this request to the single UID of the requester, or to an empty
+        // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
         // This will overwrite any allowed UIDs in the requested capabilities. Though there
         // are no visible methods to set the UIDs, an app could use reflection to try and get
         // networks for other apps so it's essential that the UIDs are overwritten.
-        // TODO : don't forcefully set the UID when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        networkCapabilities.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(networkCapabilities);
 
         if (timeoutMs < 0) {
             throw new IllegalArgumentException("Bad timeout specified");
@@ -4293,9 +4310,7 @@
         enforceMeteredApnPolicy(networkCapabilities);
         ensureRequestableCapabilities(networkCapabilities);
         ensureValidNetworkSpecifier(networkCapabilities);
-        // TODO : don't forcefully set the UID when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        networkCapabilities.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
@@ -4349,9 +4364,7 @@
         }
 
         NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
-        // TODO : don't forcefully set the UIDs when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        nc.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(nc);
         if (!ConnectivityManager.checkChangePermission(mContext)) {
             // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
             // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
@@ -4381,9 +4394,7 @@
         ensureValidNetworkSpecifier(networkCapabilities);
 
         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
-        // TODO : don't forcefully set the UIDs when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        nc.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(nc);
 
         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
@@ -4947,8 +4958,8 @@
             }
             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
                 // networkAgent can't be null as it has been accessed a few lines above.
-                final NetworkCapabilities nc =
-                        networkCapabilitiesWithoutUids(networkAgent.networkCapabilities);
+                final NetworkCapabilities nc = networkCapabilitiesWithoutUidsUnlessAllowed(
+                        networkAgent.networkCapabilities, nri.mPid, nri.mUid);
                 putParcelable(bundle, nc);
                 break;
             }
@@ -5428,8 +5439,11 @@
         if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
             networkAgent.everConnected = true;
 
+            if (networkAgent.linkProperties == null) {
+                Slog.wtf(TAG, networkAgent.name() + " connected with null LinkProperties");
+            }
+
             updateLinkProperties(networkAgent, null);
-            notifyIfacesChangedForNetworkStats();
 
             networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
             scheduleUnvalidatedPrompt(networkAgent);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index e202618..3927ebd 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -203,6 +203,10 @@
     private PreciseDataConnectionState mPreciseDataConnectionState =
                 new PreciseDataConnectionState();
 
+    static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK =
+            PhoneStateListener.LISTEN_CELL_LOCATION
+                    | PhoneStateListener.LISTEN_CELL_INFO;
+
     static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
                 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
@@ -1721,16 +1725,13 @@
     }
 
     private boolean checkListenerPermission(int events, String callingPackage, String message) {
-        if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+        if ((events & ENFORCE_COARSE_LOCATION_PERMISSION_MASK) != 0) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-
-        }
-
-        if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-
+            if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
+                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
+                return false;
+            }
         }
 
         if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java
index be91f98..2af2f38 100644
--- a/services/core/java/com/android/server/accounts/TokenCache.java
+++ b/services/core/java/com/android/server/accounts/TokenCache.java
@@ -125,7 +125,7 @@
                  * This is recursive, but it won't spiral out of control because LruCache is
                  * thread safe and the Evictor can only be removed once.
                  */
-                Evictor evictor = mTokenEvictors.remove(oldVal.token);
+                Evictor evictor = mTokenEvictors.remove(new Pair<>(k.account.type, oldVal.token));
                 if (evictor != null) {
                     evictor.evict();
                 }
@@ -134,12 +134,13 @@
 
         public void putToken(Key k, Value v) {
             // Prepare for removal by token string.
-            Evictor tokenEvictor = mTokenEvictors.get(v.token);
+            Pair<String, String> mapKey = new Pair<>(k.account.type, v.token);
+            Evictor tokenEvictor = mTokenEvictors.get(mapKey);
             if (tokenEvictor == null) {
                 tokenEvictor = new Evictor();
             }
             tokenEvictor.add(k);
-            mTokenEvictors.put(new Pair<>(k.account.type, v.token), tokenEvictor);
+            mTokenEvictors.put(mapKey, tokenEvictor);
 
             // Prepare for removal by associated account.
             Evictor accountEvictor = mAccountEvictors.get(k.account);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index fae215f..3b89097 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -36,6 +36,7 @@
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.os.WorkSource;
+import android.os.connectivity.CellularBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.os.health.HealthStatsWriter;
 import android.os.health.UidHealthStats;
@@ -1335,6 +1336,16 @@
     }
 
     /**
+     * Gets a snapshot of cellular stats
+     * @hide
+     */
+    public CellularBatteryStats getCellularBatteryStats() {
+        synchronized (mStats) {
+            return mStats.getCellularBatteryStats();
+        }
+    }
+
+    /**
      * Gets a snapshot of the system health for a particular uid.
      */
     @Override
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index a1c54bd..557828a 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -187,7 +187,7 @@
         Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
         return (cfg != null)
                 ? mPrivateDnsMap.put(network.netId, cfg)
-                : mPrivateDnsMap.remove(network);
+                : mPrivateDnsMap.remove(network.netId);
     }
 
     public void setDnsConfigurationForNetwork(
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index bb46d5e..c9bdcf1 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -57,6 +57,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
+import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.Uri;
@@ -105,6 +106,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -113,6 +115,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
@@ -131,6 +134,24 @@
     // the device idle whitelist during service launch and VPN bootstrap.
     private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000;
 
+    // Settings for how much of the address space should be routed so that Vpn considers
+    // "most" of the address space is routed. This is used to determine whether this Vpn
+    // should be marked with the INTERNET capability.
+    private static final long MOST_IPV4_ADDRESSES_COUNT;
+    private static final BigInteger MOST_IPV6_ADDRESSES_COUNT;
+    static {
+        // 85% of the address space must be routed for Vpn to consider this VPN to provide
+        // INTERNET access.
+        final int howManyPercentIsMost = 85;
+
+        final long twoPower32 = 1L << 32;
+        MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100;
+        final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128);
+        MOST_IPV6_ADDRESSES_COUNT = twoPower128
+                .multiply(BigInteger.valueOf(howManyPercentIsMost))
+                .divide(BigInteger.valueOf(100));
+    }
+
     // TODO: create separate trackers for each unique VPN to support
     // automated reconnection
 
@@ -830,10 +851,39 @@
         return lp;
     }
 
+    /**
+     * Analyzes the passed LinkedProperties to figure out whether it routes to most of the IP space.
+     *
+     * This returns true if the passed LinkedProperties contains routes to either most of the IPv4
+     * space or to most of the IPv6 address space, where "most" is defined by the value of the
+     * MOST_IPV{4,6}_ADDRESSES_COUNT constants : if more than this number of addresses are matched
+     * by any of the routes, then it's decided that most of the space is routed.
+     * @hide
+     */
+    @VisibleForTesting
+    static boolean providesRoutesToMostDestinations(LinkProperties lp) {
+        final Comparator<IpPrefix> prefixLengthComparator = IpPrefix.lengthComparator();
+        TreeSet<IpPrefix> ipv4Prefixes = new TreeSet<>(prefixLengthComparator);
+        TreeSet<IpPrefix> ipv6Prefixes = new TreeSet<>(prefixLengthComparator);
+        for (final RouteInfo route : lp.getAllRoutes()) {
+            IpPrefix destination = route.getDestination();
+            if (destination.isIPv4()) {
+                ipv4Prefixes.add(destination);
+            } else {
+                ipv6Prefixes.add(destination);
+            }
+        }
+        if (NetworkUtils.routedIPv4AddressCount(ipv4Prefixes) > MOST_IPV4_ADDRESSES_COUNT) {
+            return true;
+        }
+        return NetworkUtils.routedIPv6AddressCount(ipv6Prefixes)
+                .compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0;
+    }
+
     private void agentConnect() {
         LinkProperties lp = makeLinkProperties();
 
-        if (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()) {
+        if (providesRoutesToMostDestinations(lp)) {
             mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
         } else {
             mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index bfc150e..8298127 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -153,8 +153,7 @@
     static final boolean LOGV = false;
 
     private static final int MSG_PERFORM_POLL = 1;
-    private static final int MSG_UPDATE_IFACES = 2;
-    private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
+    private static final int MSG_REGISTER_GLOBAL_ALERT = 2;
 
     /** Flags to control detail level of poll event. */
     private static final int FLAG_PERSIST_NETWORK = 0x1;
@@ -1533,10 +1532,6 @@
                     mService.performPoll(flags);
                     return true;
                 }
-                case MSG_UPDATE_IFACES: {
-                    mService.updateIfaces(null);
-                    return true;
-                }
                 case MSG_REGISTER_GLOBAL_ALERT: {
                     mService.registerGlobalAlert();
                     return true;
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ab3c999..168b10b 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -62,6 +62,8 @@
     public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
     /** Indicates that dexopt should restrict access to private APIs. */
     public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10;
+    /** Indicates that dexopt should convert to CompactDex. */
+    public static final int DEXOPT_GENERATE_COMPACT_DEX = 1 << 11;
 
     // NOTE: keep in sync with installd
     public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 51e035b..876589c 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -57,6 +57,7 @@
 import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
 import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB;
 import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+import static com.android.server.pm.Installer.DEXOPT_GENERATE_COMPACT_DEX;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
 
@@ -532,12 +533,22 @@
         // Some apps are executed with restrictions on hidden API usage. If this app is one
         // of them, pass a flag to dexopt to enable the same restrictions during compilation.
         int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+        // Enable CompactDex generation for modes that aren't latency critical.
+        final int compilationReason = options.getCompilationReason();
+        boolean generateCompactDex = true;
+        switch (compilationReason) {
+            case PackageManagerService.REASON_FIRST_BOOT:
+            case PackageManagerService.REASON_BOOT:
+            case PackageManagerService.REASON_INSTALL:
+                 generateCompactDex = false;
+        }
         int dexFlags =
                 (isPublic ? DEXOPT_PUBLIC : 0)
                 | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                 | profileFlag
                 | (options.isBootComplete() ? DEXOPT_BOOTCOMPLETE : 0)
                 | (options.isDexoptIdleBackgroundJob() ? DEXOPT_IDLE_BACKGROUND_JOB : 0)
+                | (generateCompactDex ? DEXOPT_GENERATE_COMPACT_DEX : 0)
                 | hiddenApiFlag;
         return adjustDexoptFlags(dexFlags);
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 900e188..d1abd63 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10206,6 +10206,17 @@
         mPackageUsage.writeNow(mPackages);
         mCompilerStats.writeNow();
         mDexManager.writePackageDexUsageNow();
+
+        // This is the last chance to write out pending restriction settings
+        synchronized (mPackages) {
+            if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
+                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+                for (int userId : mDirtyUsers) {
+                    mSettings.writePackageRestrictionsLPr(userId);
+                }
+                mDirtyUsers.clear();
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
index 0450816..a123304 100644
--- a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.provider.Telephony;
-import android.util.Log;
 
 public class CarrierIdInstallReceiver extends ConfigUpdateInstallReceiver {
 
@@ -33,7 +32,7 @@
     @Override
     protected void postInstall(Context context, Intent intent) {
         ContentResolver resolver = context.getContentResolver();
-        resolver.update(Uri.withAppendedPath(Telephony.CarrierIdentification.All.CONTENT_URI,
+        resolver.update(Uri.withAppendedPath(Telephony.CarrierId.All.CONTENT_URI,
                 "update_db"), new ContentValues(), null, null);
     }
 }
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 1f370a5..9863370 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -540,6 +540,8 @@
     // TODO: Revert this hack once IpClient and Nat464Xlat work in concert.
     private static final String CLAT_PREFIX = "v4-";
 
+    private static final int IMMEDIATE_FAILURE_DURATION = 0;
+
     private final State mStoppedState = new StoppedState();
     private final State mStoppingState = new StoppingState();
     private final State mStartedState = new StartedState();
@@ -551,6 +553,7 @@
     private final String mClatInterfaceName;
     @VisibleForTesting
     protected final Callback mCallback;
+    private final Dependencies mDependencies;
     private final CountDownLatch mShutdownLatch;
     private final INetworkManagementService mNwService;
     private final NetlinkTracker mNetlinkTracker;
@@ -579,10 +582,23 @@
     private boolean mMulticastFiltering;
     private long mStartTimeMillis;
 
+    public static class Dependencies {
+        public INetworkManagementService getNMS() {
+            return INetworkManagementService.Stub.asInterface(
+                    ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
+        }
+
+        public INetd getNetd() {
+            return NetdService.getInstance();
+        }
+
+        public InterfaceParams getInterfaceParams(String ifname) {
+            return InterfaceParams.getByName(ifname);
+        }
+    }
+
     public IpClient(Context context, String ifName, Callback callback) {
-        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)),
-                NetdService.getInstance());
+        this(context, ifName, callback, new Dependencies());
     }
 
     /**
@@ -591,27 +607,35 @@
      */
     public IpClient(Context context, String ifName, Callback callback,
             INetworkManagementService nwService) {
-        this(context, ifName, callback, nwService, NetdService.getInstance());
+        this(context, ifName, callback, new Dependencies() {
+            @Override
+            public INetworkManagementService getNMS() { return nwService; }
+        });
     }
 
     @VisibleForTesting
-    IpClient(Context context, String ifName, Callback callback,
-            INetworkManagementService nwService, INetd netd) {
+    IpClient(Context context, String ifName, Callback callback, Dependencies deps) {
         super(IpClient.class.getSimpleName() + "." + ifName);
+        Preconditions.checkNotNull(ifName);
+        Preconditions.checkNotNull(callback);
+
         mTag = getName();
 
         mContext = context;
         mInterfaceName = ifName;
         mClatInterfaceName = CLAT_PREFIX + ifName;
         mCallback = new LoggingCallbackWrapper(callback);
+        mDependencies = deps;
         mShutdownLatch = new CountDownLatch(1);
-        mNwService = nwService;
+        mNwService = deps.getNMS();
 
         mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
         mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
         mMsgStateLogger = new MessageHandlingLogger();
 
-        mInterfaceCtrl = new InterfaceController(mInterfaceName, mNwService, netd, mLog);
+        // TODO: Consider creating, constructing, and passing in some kind of
+        // InterfaceController.Dependencies class.
+        mInterfaceCtrl = new InterfaceController(mInterfaceName, mNwService, deps.getNetd(), mLog);
 
         mNetlinkTracker = new NetlinkTracker(
                 mInterfaceName,
@@ -742,11 +766,11 @@
             return;
         }
 
-        mInterfaceParams = InterfaceParams.getByName(mInterfaceName);
+        mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName);
         if (mInterfaceParams == null) {
             logError("Failed to find InterfaceParams for " + mInterfaceName);
-            // TODO: call doImmediateProvisioningFailure() with an error code
-            // indicating something like "interface not ready".
+            doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND);
+            return;
         }
 
         mCallback.setNeighborDiscoveryOffload(true);
@@ -930,8 +954,11 @@
     }
 
     private void recordMetric(final int type) {
-        if (mStartTimeMillis <= 0) { Log.wtf(mTag, "Start time undefined!"); }
-        final long duration = SystemClock.elapsedRealtime() - mStartTimeMillis;
+        // We may record error metrics prior to starting.
+        // Map this to IMMEDIATE_FAILURE_DURATION.
+        final long duration = (mStartTimeMillis > 0)
+                ? (SystemClock.elapsedRealtime() - mStartTimeMillis)
+                : IMMEDIATE_FAILURE_DURATION;
         mMetricsLog.log(mInterfaceName, new IpManagerEvent(type, duration));
     }
 
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 3898145..508a43d 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -144,20 +144,7 @@
     }
 
     public IpManager(Context context, String ifName, Callback callback) {
-        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)),
-                NetdService.getInstance());
-    }
-
-    public IpManager(Context context, String ifName, Callback callback,
-            INetworkManagementService nwService) {
-        this(context, ifName, callback, nwService, NetdService.getInstance());
-    }
-
-    @VisibleForTesting
-    public IpManager(Context context, String ifName, Callback callback,
-            INetworkManagementService nwService, INetd netd) {
-        super(context, ifName, callback, nwService, netd);
+        super(context, ifName, callback);
     }
 
     public void startProvisioning(ProvisioningConfiguration req) {
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index 597a584..1ccb872 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -31,6 +31,7 @@
 LOCAL_DX_FLAGS := --multi-dex
 
 LOCAL_PACKAGE_NAME := FrameworksNotificationTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_CERTIFICATE := platform
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 19396d4..9af0978 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -35,6 +35,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.mock legacy-android-test
 
 LOCAL_PACKAGE_NAME := FrameworksServicesTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_CERTIFICATE := platform
diff --git a/services/tests/servicestests/test-apps/ConnTestApp/Android.mk b/services/tests/servicestests/test-apps/ConnTestApp/Android.mk
index fbfa28a..18b8c2d 100644
--- a/services/tests/servicestests/test-apps/ConnTestApp/Android.mk
+++ b/services/tests/servicestests/test-apps/ConnTestApp/Android.mk
@@ -24,6 +24,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := ConnTestApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_DEX_PREOPT := false
 LOCAL_PROGUARD_ENABLED := disabled
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a79f2c9..73243d2 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -879,42 +879,76 @@
         /**
          * @hide
          */
-        @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
-                HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED,
-                HANDOVER_FAILURE_ONGOING_EMERG_CALL})
+        @IntDef(prefix = { "HANDOVER_" },
+                value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
+                HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERG_CALL,
+                HANDOVER_FAILURE_UNKNOWN})
         @Retention(RetentionPolicy.SOURCE)
         public @interface HandoverFailureErrors {}
 
         /**
          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
-         * to handover the call rejects handover.
+         * to handover the call to rejects the handover request.
+         * <p>
+         * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
+         * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
+         * {@code null} {@link Connection} from
+         * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+         * ConnectionRequest)}.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
         public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
 
         /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there is
-         * an error associated with unsupported handover.
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+         * is initiated but the source or destination app does not support handover.
+         * <p>
+         * Will be returned when a handover is requested via
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
+         * {@link PhoneAccountHandle} does not declare
+         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
+         * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
+         * {@link Details#getAccountHandle()}) does not declare
+         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2;
+        public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
 
         /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
-         * are some permission errors associated with APIs doing handover.
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
+         * user rejects the handover request.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3;
-
-        /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when user
-         * rejects handover.
-         */
-        public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
+        public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
 
         /**
          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
          * is ongoing emergency call.
+         * <p>
+         * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
+         * called on an emergency call, or if any other call is an emergency call.
+         * <p>
+         * Handovers are not permitted while there are ongoing emergency calls.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5;
+        public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 4;
 
+        /**
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+         * fails for an unknown reason.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
+         */
+        public static final int HANDOVER_FAILURE_UNKNOWN = 5;
 
         /**
          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
@@ -1055,6 +1089,10 @@
         /**
          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
          * has completed successfully.
+         * <p>
+         * For a full discussion of the handover process and the APIs involved, see
+         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+         *
          * @param call The call which had initiated handover.
          */
         public void onHandoverComplete(Call call) {}
@@ -1062,8 +1100,12 @@
         /**
          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
          * has failed.
+         * <p>
+         * For a full discussion of the handover process and the APIs involved, see
+         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+         *
          * @param call The call which had initiated handover.
-         * @param failureReason Error reason for failure
+         * @param failureReason Error reason for failure.
          */
         public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
     }
@@ -1260,7 +1302,7 @@
      * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
      * @param videoState The video state in which to answer the call.
      */
-    public void answer(int videoState) {
+    public void answer(@VideoProfile.VideoState int videoState) {
         mInCallAdapter.answerCall(mTelecomCallId, videoState);
     }
 
@@ -1474,16 +1516,65 @@
      * by {@code toHandle}.  The videoState specified indicates the desired video state after the
      * handover.
      * <p>
-     * A handover request is initiated by the user from one app to indicate a desire
-     * to handover a call to another.
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the device this method is called on is considered the
+     * <em>initiating</em> device (since the user initiates the handover from this device), and the
+     * other device is considered the <em>receiving</em> device.
+     * <p>
+     * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
+     * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
+     * and invoke
+     * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+     * ConnectionRequest)} to inform the destination app that a request has been made to handover a
+     * call to it.  The app returns an instance of {@link Connection} to represent the handover call
+     * At this point the app should display UI to indicate to the user that a call
+     * handover is in process.
+     * <p>
+     * The destination app is responsible for communicating the handover request from the
+     * <em>initiating</em> device to the <em>receiving</em> device.
+     * <p>
+     * When the app on the <em>receiving</em> device receives the handover request, it calls
+     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
+     * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
+     * the destination app on the <em>receiving</em> device should show UI to allow the user to
+     * choose whether they want to continue their call in the destination app.
+     * <p>
+     * When the destination app on the <em>receiving</em> device calls
+     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
+     * {@link ConnectionService} and call
+     * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
+     * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
+     * {@link Connection} to represent the handover call.
+     * <p>
+     * If the user of the <em>receiving</em> device accepts the handover, the app calls
+     * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
+     * original call.  If the user rejects the handover, the app calls
+     * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
+     * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
+     * <p>
+     * Telecom will only allow handovers from {@link PhoneAccount}s which declare
+     * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
+     * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
+     * <p>
+     * Errors in the handover process are reported to the {@link InCallService} via
+     * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
+     * the involved {@link ConnectionService}s via
+     * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
      *
      * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
      *                 this call to.
-     * @param videoState Indicates the video state desired after the handover.
+     * @param videoState Indicates the video state desired after the handover (see the
+     *               {@code STATE_*} constants defined in {@link VideoProfile}).
      * @param extras Bundle containing extra information to be passed to the
      *               {@link ConnectionService}
      */
-    public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
+    public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
+            Bundle extras) {
         mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
     }
 
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 593e12b..2fdbc71 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2218,12 +2218,50 @@
     }
 
     /**
-     * Called by Telecom on the initiating side of the handover to create an instance of a
-     * handover connection.
+     * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+     * outgoing handover {@link Connection}.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * This method is called on the destination {@link ConnectionService} on <em>initiating</em>
+     * device when the user initiates a handover request from one app to another.  The user request
+     * originates in the {@link InCallService} via
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * Implementations of this method should return an instance of {@link Connection} which
+     * represents the handover.  If your app does not wish to accept a handover to it at this time,
+     * you can return {@code null}.  The code below shows an example of how this is done.
+     * <pre>
+     * {@code
+     * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+     *     fromPhoneAccountHandle, ConnectionRequest request) {
+     *   if (!isHandoverAvailable()) {
+     *       return null;
+     *   }
+     *   MyConnection connection = new MyConnection();
+     *   connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+     *   connection.setVideoState(request.getVideoState());
+     *   return connection;
+     * }
+     * }
+     * </pre>
+     *
      * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
      *                               ConnectionService which needs to handover the call.
-     * @param request Details about the call which needs to be handover.
-     * @return Connection object corresponding to the handover call.
+     * @param request Details about the call to handover.
+     * @return {@link Connection} instance corresponding to the handover call.
      */
     public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
                                                          ConnectionRequest request) {
@@ -2231,12 +2269,46 @@
     }
 
     /**
-     * Called by Telecom on the receiving side of the handover to request the
-     * {@link ConnectionService} to create an instance of a handover connection.
+     * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+     * incoming handover {@link Connection}.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * This method is called on the destination app on the <em>receiving</em> device when the
+     * destination app calls {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to
+     * accept an incoming handover from the <em>initiating</em> device.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * Implementations of this method should return an instance of {@link Connection} which
+     * represents the handover.  The code below shows an example of how this is done.
+     * <pre>
+     * {@code
+     * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+     *     fromPhoneAccountHandle, ConnectionRequest request) {
+     *   // Given that your app requested to accept the handover, you should not return null here.
+     *   MyConnection connection = new MyConnection();
+     *   connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+     *   connection.setVideoState(request.getVideoState());
+     *   return connection;
+     * }
+     * }
+     * </pre>
+     *
      * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
      *                               ConnectionService which needs to handover the call.
      * @param request Details about the call which needs to be handover.
-     * @return {@link Connection} object corresponding to the handover call.
+     * @return {@link Connection} instance corresponding to the handover call.
      */
     public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
                                                          ConnectionRequest request) {
@@ -2246,11 +2318,15 @@
     /**
      * Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
      * invocation which failed.
-     * @param request Details about the call which needs to be handover.
-     * @param error Reason for handover failure as defined in
-     *              {@link android.telecom.Call.Callback#HANDOVER_FAILURE_DEST_INVALID_PERM}
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}
+     *
+     * @param request Details about the call which failed to handover.
+     * @param error Reason for handover failure.  Will be one of the
      */
-    public void onHandoverFailed(ConnectionRequest request, int error) {
+    public void onHandoverFailed(ConnectionRequest request,
+            @Call.Callback.HandoverFailureErrors int error) {
         return;
     }
 
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 4fc3385..2bda648 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -24,21 +24,20 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.IllegalFormatException;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.TimeZone;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.stream.Collectors;
 
 /**
  * A utility class that provides the ability to define Events that a subsystem deems important, and
@@ -53,7 +52,8 @@
     public static final String TAG = "Logging.Events";
     @VisibleForTesting
     public static final int DEFAULT_EVENTS_TO_CACHE = 10;  // Arbitrarily chosen.
-    private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+    public static final DateTimeFormatter DATE_TIME_FORMATTER =
+            DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
 
     public interface Loggable {
         /**
@@ -131,11 +131,17 @@
         public String sessionId;
         public long time;
         public Object data;
+        // String storing the date for display. This will be computed at the time/timezone when
+        // the event is recorded.
+        public final String timestampString;
 
         public Event(String eventId, String sessionId, long time, Object data) {
             this.eventId = eventId;
             this.sessionId = sessionId;
             this.time = time;
+            timestampString =
+                    ZonedDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault())
+                    .format(DATE_TIME_FORMATTER);
             this.data = data;
         }
     }
@@ -228,7 +234,7 @@
 
             pw.increaseIndent();
             for (Event event : mEvents) {
-                pw.print(sDateFormat.format(new Date(event.time)));
+                pw.print(event.timestampString);
                 pw.print(" - ");
                 pw.print(event.eventId);
                 if (event.data != null) {
@@ -269,7 +275,6 @@
 
     public EventManager(@NonNull SessionManager.ISessionIdQueryHandler l) {
         mSessionIdHandler = l;
-        sDateFormat.setTimeZone(TimeZone.getDefault());
     }
 
     public void event(Loggable recordEntry, String event, Object data) {
@@ -329,15 +334,15 @@
             }
         }
 
-        // Sort by event time.
-        Comparator<Pair<Loggable, Event>> byEventTime = (e1, e2) -> {
-          return Long.compare(e1.second.time, e2.second.time);
-        };
+        // Sort by event time. This might result in out-of-order seeming events if the timezone
+        // changes somewhere in the middle.
+        Comparator<Pair<Loggable, Event>> byEventTime =
+                Comparator.comparingLong(e -> e.second.time);
         events.sort(byEventTime);
 
         pw.increaseIndent();
         for (Pair<Loggable, Event> event : events) {
-            pw.print(sDateFormat.format(new Date(event.second.time)));
+            pw.print(event.second.timestampString);
             pw.print(",");
             pw.print(event.first.getId());
             pw.print(",");
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 59ce590..bb4b483 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -93,6 +93,10 @@
                     // failure on the providing end, so immediately mark it destroyed
                     connection.setDestroyed();
                 }
+                connection.setStatusHints(parcel.getStatusHints());
+                connection.setIsVoipAudioMode(parcel.getIsVoipAudioMode());
+                connection.setRingbackRequested(parcel.isRingbackRequested());
+                connection.putExtras(parcel.getExtras());
             }
         }
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index c848f77..4b1f0ad 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1786,8 +1786,25 @@
     }
 
     /**
-     * Called from the recipient side of a handover to indicate a desire to accept the handover
-     * of an ongoing call to another {@link ConnectionService} identified by
+     * Called by an app to indicate that it wishes to accept the handover of an ongoing call to a
+     * {@link PhoneAccountHandle} it defines.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * This method is called from the <em>receiving</em> side of a handover to indicate a desire to
+     * accept the handover of an ongoing call to another {@link ConnectionService} identified by
      * {@link PhoneAccountHandle} destAcct. For managed {@link ConnectionService}s, the specified
      * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
      * the user must have enabled the corresponding {@link PhoneAccount}.  This can be checked using
@@ -1811,7 +1828,8 @@
      * @param videoState Video state after the handover.
      * @param destAcct The {@link PhoneAccountHandle} registered to the calling package.
      */
-    public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+    public void acceptHandover(Uri srcAddr, @VideoProfile.VideoState int videoState,
+            PhoneAccountHandle destAcct) {
         try {
             if (isServiceConnected()) {
                 getTelecomService().acceptHandover(srcAddr, videoState, destAcct);
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index e0e3a08..90ed36f 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -62,6 +62,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(
             flag = true,
+            prefix = { "STATE_" },
             value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL,
                     STATE_PAUSED})
     public @interface VideoState {}
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 7cd16128..cac9f2b 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -30,6 +30,9 @@
         public static final int EUTRAN = 3;
         public static final int CDMA2000 = 4;
         public static final int IWLAN = 5;
+
+        /** @hide */
+        private AccessNetworkType() {};
     }
 
     /**
@@ -42,6 +45,9 @@
         public static final int WWAN = 1;
         /** Wireless Local Area Networks (i.e. Wifi) */
         public static final int WLAN = 2;
+
+        /** @hide */
+        private TransportType() {};
     }
 
     /**
@@ -63,6 +69,9 @@
         public static final int BAND_DCS1800 = 12;
         public static final int BAND_PCS1900 = 13;
         public static final int BAND_ER900 = 14;
+
+        /** @hide */
+        private GeranBand() {};
     }
 
     /**
@@ -92,6 +101,9 @@
         /** band 23, 24 are reserved */
         public static final int BAND_25 = 25;
         public static final int BAND_26 = 26;
+
+        /** @hide */
+        private UtranBand() {};
     }
 
     /**
@@ -147,6 +159,9 @@
         public static final int BAND_66 = 66;
         public static final int BAND_68 = 68;
         public static final int BAND_70 = 70;
+
+        /** @hide */
+        private EutranBand() {};
     }
 
     /**
@@ -179,5 +194,11 @@
         public static final int BAND_19 = 20;
         public static final int BAND_20 = 21;
         public static final int BAND_21 = 22;
+
+        /** @hide */
+        private CdmaBands() {};
     }
+
+    /** @hide */
+    private AccessNetworkConstants() {};
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e8b2fa7..8202d56 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -991,8 +991,13 @@
             "wfc_emergency_address_carrier_app_string";
 
     /**
-     * Boolean to decide whether to use #KEY_CARRIER_NAME_STRING from CarrierConfig app.
-     * @hide
+     * Unconditionally override the carrier name string using #KEY_CARRIER_NAME_STRING.
+     *
+     * If true, then the carrier display name will be #KEY_CARRIER_NAME_STRING, unconditionally.
+     *
+     * <p>If false, then the override will be performed conditionally and the
+     * #KEY_CARRIER_NAME_STRING will have the lowest-precedence; it will only be used in the event
+     * that the name string would otherwise be empty, allowing it to serve as a last-resort.
      */
     public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
 
@@ -1000,7 +1005,6 @@
      * String to identify carrier name in CarrierConfig app. This string overrides SPN if
      * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true; otherwise, it will be used if its value is provided
      * and SPN is unavailable
-     * @hide
      */
     public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
 
@@ -1569,6 +1573,14 @@
             "notify_international_call_on_wfc_bool";
 
     /**
+     * Flag specifying whether to show an alert dialog for video call charges.
+     * By default this value is {@code false}.
+     * @hide
+     */
+    public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL =
+            "show_video_call_charges_alert_dialog_bool";
+
+    /**
      * An array containing custom call forwarding number prefixes that will be blocked while the
      * device is reporting that it is roaming. By default, there are no custom call
      * forwarding prefixes and none of these numbers will be filtered. If one or more entries are
@@ -1829,6 +1841,33 @@
     public static final String KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING
             = "carrier_network_service_wwan_package_override_string";
 
+    /**
+     * A list of 4 LTE RSCP thresholds above which a signal level is considered POOR,
+     * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+     *
+     * Note that the min and max thresholds are fixed at -120 and -24, as set in 3GPP TS 27.007
+     * section 8.69.
+     * <p>
+     * See SignalStrength#MAX_WCDMA_RSCP and SignalStrength#MIN_WDCMA_RSCP. Any signal level outside
+     * these boundaries is considered invalid.
+     * @hide
+     */
+    public static final String KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY =
+            "wcdma_rscp_thresholds_int_array";
+
+    /**
+     * The default measurement to use for signal strength reporting. If this is not specified, the
+     * RSSI is used.
+     * <p>
+     * e.g.) To use RSCP by default, set the value to "rscp". The signal strength level will
+     * then be determined by #KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY
+     * <p>
+     * Currently this only supports the value "rscp"
+     * @hide
+     */
+    public static final String KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING =
+            "wcdma_default_signal_strength_measurement_string";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -2102,6 +2141,7 @@
         sDefaults.putBoolean(KEY_DISPLAY_VOICEMAIL_NUMBER_AS_DEFAULT_CALL_FORWARDING_NUMBER_BOOL,
                 false);
         sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
+        sDefaults.putBoolean(KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL, false);
         sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY,
                 null);
         sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
@@ -2130,6 +2170,14 @@
                         -108, /* SIGNAL_STRENGTH_GOOD */
                         -98,  /* SIGNAL_STRENGTH_GREAT */
                 });
+        sDefaults.putIntArray(KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY,
+                new int[] {
+                        -115,  /* SIGNAL_STRENGTH_POOR */
+                        -105, /* SIGNAL_STRENGTH_MODERATE */
+                        -95, /* SIGNAL_STRENGTH_GOOD */
+                        -85  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "");
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 2e1d1dc..105ddb0 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -103,8 +103,12 @@
         mNetworkId = nid;
         mSystemId = sid;
         mBasestationId = bid;
-        mLongitude = lon;
-        mLatitude = lat;
+        if (!isNullIsland(lat, lon)) {
+            mLongitude = lon;
+            mLatitude = lat;
+        } else {
+            mLongitude = mLatitude = Integer.MAX_VALUE;
+        }
         mAlphaLong = alphal;
         mAlphaShort = alphas;
     }
@@ -119,6 +123,18 @@
     }
 
     /**
+     * Take the latitude and longitude in 1/4 seconds and see if
+     * the reported location is on Null Island.
+     *
+     * @return whether the reported Lat/Long are for Null Island
+     *
+     * @hide
+     */
+    private boolean isNullIsland(int lat, int lon) {
+        return Math.abs(lat) <= 1 && Math.abs(lon) <= 1;
+    }
+
+    /**
      * @return Network Id 0..65535, Integer.MAX_VALUE if unknown
      */
     public int getNetworkId() {
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index f948f81..d35eb60 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -120,7 +120,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -129,7 +129,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -176,14 +176,14 @@
     /**
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 5f1f448..2b8eb5f 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -125,7 +125,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -134,7 +134,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -179,14 +179,14 @@
     /**
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 001d19f..992545d 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -86,7 +86,7 @@
      * Get Mobile Country Code in string format
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
@@ -94,7 +94,7 @@
      * Get Mobile Network Code in string format
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 1aa1715..a5fd7dd 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -118,7 +118,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -127,7 +127,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -160,14 +160,14 @@
     /**
      * @return Mobile Country Code in string version, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string version, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index ece1ee3..183f96d 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -41,14 +41,36 @@
         setDefaultValues();
     }
 
-    /** @hide */
+    /**
+     * SignalStrength constructor for input from the HAL.
+     *
+     * Note that values received from the HAL require coersion to be compatible here. All values
+     * reported through IRadio are the negative of the actual values (which results in a positive
+     * input to this method.
+     *
+     * <p>Note that this HAL is inconsistent with UMTS-based radio techs as the value indicating
+     * that a field is unreported is negative, rather than a large(r) positive number.
+     * <p>Also note that to keep the public-facing methods of this class consistent with others,
+     * unreported values are coerced to Integer.MAX_VALUE rather than left as -1, which is
+     * a departure from SignalStrength, which is stuck with the values it currently reports.
+     *
+     * @param cdmaDbm negative of the CDMA signal strength value or -1 if invalid.
+     * @param cdmaEcio negative of the CDMA pilot/noise ratio or -1 if invalid.
+     * @param evdoDbm negative of the EvDO signal strength value or -1 if invalid.
+     * @param evdoEcio negative of the EvDO pilot/noise ratio or -1 if invalid.
+     * @param evdoSnr an SNR value 0..8 or -1 if invalid.
+     * @hide
+     */
     public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
             int evdoSnr) {
-        mCdmaDbm = cdmaDbm;
-        mCdmaEcio = cdmaEcio;
-        mEvdoDbm = evdoDbm;
-        mEvdoEcio = evdoEcio;
-        mEvdoSnr = evdoSnr;
+        // The values here were lifted from SignalStrength.validateInput()
+        // FIXME: Combine all checking and setting logic between this and SignalStrength.
+        mCdmaDbm = ((cdmaDbm > 0) && (cdmaDbm < 120))  ? -cdmaDbm : Integer.MAX_VALUE;
+        mCdmaEcio = ((cdmaEcio > 0) && (cdmaEcio < 160)) ? -cdmaEcio : Integer.MAX_VALUE;
+
+        mEvdoDbm = ((evdoDbm > 0) && (evdoDbm < 120)) ? -evdoDbm : Integer.MAX_VALUE;
+        mEvdoEcio = ((evdoEcio > 0) && (evdoEcio < 160)) ? -evdoEcio : Integer.MAX_VALUE;
+        mEvdoSnr = ((evdoSnr > 0) && (evdoSnr <= 8)) ? evdoSnr : Integer.MAX_VALUE;
     }
 
     /** @hide */
@@ -303,13 +325,10 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        // Need to multiply CdmaDbm, CdmaEcio, EvdoDbm and EvdoEcio by -1
-        // to ensure consistency when reading values written here
-        // unless the value is invalid
-        dest.writeInt(mCdmaDbm * (mCdmaDbm != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mCdmaEcio * (mCdmaEcio != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mEvdoDbm * (mEvdoDbm != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mEvdoEcio * (mEvdoEcio != Integer.MAX_VALUE ? -1 : 1));
+        dest.writeInt(mCdmaDbm);
+        dest.writeInt(mCdmaEcio);
+        dest.writeInt(mEvdoDbm);
+        dest.writeInt(mEvdoEcio);
         dest.writeInt(mEvdoSnr);
     }
 
@@ -322,13 +341,9 @@
         // the parcel as positive values.
         // Need to convert into negative values unless the value is invalid
         mCdmaDbm = in.readInt();
-        if (mCdmaDbm != Integer.MAX_VALUE) mCdmaDbm *= -1;
         mCdmaEcio = in.readInt();
-        if (mCdmaEcio != Integer.MAX_VALUE) mCdmaEcio *= -1;
         mEvdoDbm = in.readInt();
-        if (mEvdoDbm != Integer.MAX_VALUE) mEvdoDbm *= -1;
         mEvdoEcio = in.readInt();
-        if (mEvdoEcio != Integer.MAX_VALUE) mEvdoEcio *= -1;
         mEvdoSnr = in.readInt();
         if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString());
     }
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index b362df9..26ffe32 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -82,8 +82,7 @@
                     .noteOpNoThrow(opCode, uid, pkgName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
-            if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))
-                    && !isLegacyForeground(context, pkgName, uid)) {
+            if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))) {
                 return false;
             }
             // If the user or profile is current, permission is granted.
@@ -101,35 +100,6 @@
                 && locationMode != Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
     }
 
-    private static boolean isLegacyForeground(@NonNull Context context, @NonNull String pkgName,
-            int uid) {
-        long token = Binder.clearCallingIdentity();
-        try {
-            return isLegacyVersion(context, pkgName) && isForegroundApp(context, uid);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    private static boolean isLegacyVersion(@NonNull Context context, @NonNull String pkgName) {
-        try {
-            if (context.getPackageManager().getApplicationInfo(pkgName, 0)
-                    .targetSdkVersion <= Build.VERSION_CODES.O) {
-                return true;
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // In case of exception, assume known app (more strict checking)
-            // Note: This case will never happen since checkPackage is
-            // called to verify validity before checking app's version.
-        }
-        return false;
-    }
-
-    private static boolean isForegroundApp(@NonNull Context context, int uid) {
-        final ActivityManager am = context.getSystemService(ActivityManager.class);
-        return am.getUidImportance(uid) <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
-    }
-
     private static boolean checkInteractAcrossUsersFull(@NonNull Context context) {
         return context.checkCallingOrSelfPermission(
                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index a277212..71a177a 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -29,9 +29,9 @@
 
 /**
  * The caller of
- * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)}
+ * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
  * will receive an instance of {@link NetworkScan}, which contains a callback method
- * {@link #stop()} for stopping the in-progress scan.
+ * {@link #stopScan()} for stopping the in-progress scan.
  */
 public class NetworkScan {
 
@@ -106,16 +106,26 @@
      * Use this method to stop an ongoing scan. When user requests a new scan, a {@link NetworkScan}
      * object will be returned, and the user can stop the scan by calling this method.
      */
-    public void stop() throws RemoteException {
+    public void stopScan() {
+        ITelephony telephony = getITelephony();
+        if (telephony == null) {
+            Rlog.e(TAG, "Failed to get the ITelephony instance.");
+            throw new RuntimeException("Failed to get the ITelephony instance.");
+        }
         try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                telephony.stopNetworkScan(mSubId, mScanId);
-            } else {
-                throw new RemoteException("Failed to get the ITelephony instance.");
-            }
+            telephony.stopNetworkScan(mSubId, mScanId);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "stopNetworkScan  RemoteException", ex);
+            ex.rethrowAsRuntimeException();
+        }
+    }
+
+    /** @deprecated Use {@link #stopScan()} */
+    @Deprecated
+    public void stop() throws RemoteException {
+        try {
+            stopScan();
+        } catch (RuntimeException ex) {
             throw new RemoteException("Failed to stop the network scan with id " + mScanId);
         }
     }
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index e508b19..2b11e90 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -25,6 +25,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Contains phone signal strength related information.
@@ -61,6 +62,13 @@
     private static final int MAX_LTE_RSRP = -44;
     private static final int MIN_LTE_RSRP = -140;
 
+    private static final int WCDMA_RSCP_THRESHOLDS_NUM = 4;
+    private static final int MAX_WCDMA_RSCP = -24;
+    private static final int MIN_WCDMA_RSCP = -120;
+
+    /* The type of signal measurement */
+    private static final String MEASUMENT_TYPE_RSCP = "rscp";
+
     /** Parameters reported by the Radio */
     private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
     private int mGsmBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
@@ -74,7 +82,10 @@
     private int mLteRsrq;
     private int mLteRssnr;
     private int mLteCqi;
-    private int mTdScdmaRscp;
+    private int mTdScdmaRscp; // Valid values are -24...-120dBm or INVALID if unknown
+    private int mWcdmaSignalStrength;
+    private int mWcdmaRscpAsu;  // the WCDMA RSCP in ASU as reported from the HAL
+    private int mWcdmaRscp;     // the WCDMA RSCP in dBm
 
     /** Parameters from the framework */
     private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
@@ -87,6 +98,13 @@
     // min and max are fixed at MIN_LTE_RSRP (-140) and MAX_LTE_RSRP (-44).
     private int mLteRsrpThresholds[] = new int[LTE_RSRP_THRESHOLDS_NUM];
 
+    // The type of default measurement for determining the display level of WCDMA signal bar.
+    private String mWcdmaDefaultSignalMeasurement;
+
+    // The threshold of WCDMA RSCP for determining the display level of WCDMA signal bar. Note that
+    // the min and max are fixed at MIN_WCDMA_RSCP (-120) and MAX_WCDMA_RSCP (-24).
+    private int mWcdmaRscpThresholds[] = new int[WCDMA_RSCP_THRESHOLDS_NUM];
+
     /**
      * Create a new SignalStrength from a intent notifier Bundle
      *
@@ -136,10 +154,14 @@
         mLteRssnr = INVALID;
         mLteCqi = INVALID;
         mTdScdmaRscp = INVALID;
+        mWcdmaSignalStrength = 99;
+        mWcdmaRscp = INVALID;
         mLteRsrpBoost = 0;
         mIsGsm = gsmFlag;
         mUseOnlyRsrpForLteLevel = false;
+        mWcdmaDefaultSignalMeasurement = "";
         setLteRsrpThresholds(getDefaultLteRsrpThresholds());
+        setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
     }
 
     /**
@@ -152,9 +174,10 @@
             int cdmaDbm, int cdmaEcio,
             int evdoDbm, int evdoEcio, int evdoSnr,
             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int tdScdmaRscp,
+            int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscpAsu,
             // values Added by config
-            int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp) {
+            int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp,
+            String wcdmaDefaultMeasurement) {
         mGsmSignalStrength = gsmSignalStrength;
         mGsmBitErrorRate = gsmBitErrorRate;
         mCdmaDbm = cdmaDbm;
@@ -168,15 +191,20 @@
         mLteRssnr = lteRssnr;
         mLteCqi = lteCqi;
         mTdScdmaRscp = INVALID;
+        mWcdmaSignalStrength = wcdmaSignalStrength;
+        mWcdmaRscpAsu = wcdmaRscpAsu;
+        mWcdmaRscp = wcdmaRscpAsu - 120;
         mLteRsrpBoost = lteRsrpBoost;
         mIsGsm = gsmFlag;
         mUseOnlyRsrpForLteLevel = lteLevelBaseOnRsrp;
+        mWcdmaDefaultSignalMeasurement = wcdmaDefaultMeasurement;
         setLteRsrpThresholds(getDefaultLteRsrpThresholds());
+        setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
         if (DBG) log("initialize: " + toString());
     }
 
     /**
-     * Constructor for only values provided by Radio HAL
+     * Constructor for only values provided by Radio HAL V1.0
      *
      * @hide
      */
@@ -187,7 +215,23 @@
             int tdScdmaRscp) {
         this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
                 evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 0, true, false);
+                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 99, INVALID, 0, true, false, "");
+    }
+
+    /**
+     * Constructor for only values provided by Radio HAL V1.2
+     *
+     * @hide
+     */
+    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+            int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscp) {
+        this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, wcdmaSignalStrength, wcdmaRscp, 0, true,
+                false, "");
     }
 
     /**
@@ -218,10 +262,15 @@
         mLteRssnr = s.mLteRssnr;
         mLteCqi = s.mLteCqi;
         mTdScdmaRscp = s.mTdScdmaRscp;
+        mWcdmaSignalStrength = s.mWcdmaSignalStrength;
+        mWcdmaRscpAsu = s.mWcdmaRscpAsu;
+        mWcdmaRscp = s.mWcdmaRscp;
         mLteRsrpBoost = s.mLteRsrpBoost;
         mIsGsm = s.mIsGsm;
         mUseOnlyRsrpForLteLevel = s.mUseOnlyRsrpForLteLevel;
+        mWcdmaDefaultSignalMeasurement = s.mWcdmaDefaultSignalMeasurement;
         setLteRsrpThresholds(s.mLteRsrpThresholds);
+        setWcdmaRscpThresholds(s.mWcdmaRscpThresholds);
     }
 
     /**
@@ -245,10 +294,15 @@
         mLteRssnr = in.readInt();
         mLteCqi = in.readInt();
         mTdScdmaRscp = in.readInt();
+        mWcdmaSignalStrength = in.readInt();
+        mWcdmaRscpAsu = in.readInt();
+        mWcdmaRscp = in.readInt();
         mLteRsrpBoost = in.readInt();
         mIsGsm = in.readBoolean();
         mUseOnlyRsrpForLteLevel = in.readBoolean();
+        mWcdmaDefaultSignalMeasurement = in.readString();
         in.readIntArray(mLteRsrpThresholds);
+        in.readIntArray(mWcdmaRscpThresholds);
     }
 
     /**
@@ -268,10 +322,15 @@
         out.writeInt(mLteRssnr);
         out.writeInt(mLteCqi);
         out.writeInt(mTdScdmaRscp);
+        out.writeInt(mWcdmaSignalStrength);
+        out.writeInt(mWcdmaRscpAsu);
+        out.writeInt(mWcdmaRscp);
         out.writeInt(mLteRsrpBoost);
         out.writeBoolean(mIsGsm);
         out.writeBoolean(mUseOnlyRsrpForLteLevel);
+        out.writeString(mWcdmaDefaultSignalMeasurement);
         out.writeIntArray(mLteRsrpThresholds);
+        out.writeIntArray(mWcdmaRscpThresholds);
     }
 
     /**
@@ -311,25 +370,34 @@
         if (DBG) log("Signal before validate=" + this);
         // TS 27.007 8.5
         mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99;
+        mWcdmaSignalStrength = (mWcdmaSignalStrength >= 0) ? mWcdmaSignalStrength : 99;
+        mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
         // BER no change;
 
+        // WCDMA RSCP valid values are -120 through -24 as defined in TS 27.007 8.69
+        // but are reported in ASU which is 0 through 96, so we do the conversion here
+        mWcdmaRscpAsu =
+                ((mWcdmaRscpAsu - 120 >= MIN_WCDMA_RSCP) && (mWcdmaRscpAsu - 120 <= MAX_WCDMA_RSCP))
+                ? mWcdmaRscpAsu : INVALID;
+        mWcdmaRscp = ((mWcdmaRscp >= MIN_WCDMA_RSCP) && (mWcdmaRscp <= MAX_WCDMA_RSCP))
+                ? mWcdmaRscp : INVALID;
+
         mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
-        mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
+        mCdmaEcio = (mCdmaEcio >= 0) ? -mCdmaEcio : -160;
 
         mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
-        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1;
-        mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
+        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -160;
+        mEvdoSnr = ((mEvdoSnr >= 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
 
         // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
-        mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
         mLteRsrp = ((-mLteRsrp >= MIN_LTE_RSRP) && (-mLteRsrp <= MAX_LTE_RSRP)) ? -mLteRsrp
                 : SignalStrength.INVALID;
         mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
         mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
                 : SignalStrength.INVALID;
 
-        mTdScdmaRscp = ((mTdScdmaRscp >= 25) && (mTdScdmaRscp <= 120))
-                ? -mTdScdmaRscp : SignalStrength.INVALID;
+        mTdScdmaRscp = ((mTdScdmaRscp >= 0) && (mTdScdmaRscp <= 96))
+                ? (mTdScdmaRscp - 120) : SignalStrength.INVALID;
         // Cqi no change
         if (DBG) log("Signal after validate=" + this);
     }
@@ -367,6 +435,16 @@
     }
 
     /**
+     * @param defaultMeasurement sets the type of WCDMA default signal measurement
+     *
+     * Used by phone to determine default measurement type for calculation WCDMA signal level.
+     * @hide
+     */
+    public void setWcdmaDefaultSignalMeasurement(String defaultMeasurement) {
+        mWcdmaDefaultSignalMeasurement = defaultMeasurement;
+    }
+
+    /**
      * @param lteRsrpBoost - signal strength offset
      *
      * Used by phone to set the lte signal strength offset which will be
@@ -410,6 +488,23 @@
     }
 
     /**
+     * Sets the threshold array for determining the display level of WCDMA signal bar.
+     *
+     * @param wcdmaRscpThresholds int array for determining the display level.
+     *
+     * @hide
+     */
+    public void setWcdmaRscpThresholds(int[] wcdmaRscpThresholds) {
+        if ((wcdmaRscpThresholds == null)
+                || (wcdmaRscpThresholds.length != WCDMA_RSCP_THRESHOLDS_NUM)) {
+            Log.wtf(LOG_TAG, "setWcdmaRscpThresholds - wcdmaRscpThresholds is invalid.");
+            return;
+        }
+        System.arraycopy(wcdmaRscpThresholds, 0, mWcdmaRscpThresholds, 0,
+                WCDMA_RSCP_THRESHOLDS_NUM);
+    }
+
+    /**
      * Get the CDMA RSSI value in dBm
      */
     public int getCdmaDbm() {
@@ -500,6 +595,8 @@
                 asuLevel = getLteAsuLevel();
             } else if (mTdScdmaRscp != SignalStrength.INVALID) {
                 asuLevel = getTdScdmaAsuLevel();
+            } else if (mWcdmaRscp != SignalStrength.INVALID) {
+                asuLevel = getWcdmaAsuLevel();
             } else {
                 asuLevel = getGsmAsuLevel();
             }
@@ -533,7 +630,11 @@
             dBm = getLteDbm();
             if (dBm == INVALID) {
                 if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                    dBm = getGsmDbm();
+                    if (getWcdmaDbm() == INVALID) {
+                        dBm = getGsmDbm();
+                    } else {
+                        dBm = getWcdmaDbm();
+                    }
                 } else {
                     dBm = getTdScdmaDbm();
                 }
@@ -805,17 +906,21 @@
         if (rsrpIconLevel != -1) return rsrpIconLevel;
 
         /* Valid values are (0-63, 99) as defined in TS 36.331 */
+        // TODO the range here is probably supposed to be (0..31, 99). It's unclear if anyone relies
+        // on the current incorrect range check, so this will be fixed in a future release with more
+        // soak time
         if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
         else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
         else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
         else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
 
-        if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
+        if (DBG) log("getLteLevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
                 + rssiIconLevel);
         return rssiIconLevel;
 
     }
+
     /**
      * Get the LTE signal level as an asu value between 0..97, 99 is unknown
      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
@@ -908,6 +1013,105 @@
         return tdScdmaAsuLevel;
     }
 
+    /**
+     * Gets WCDMA RSCP as a dbm value between -120 and -24, as defined in TS 27.007 8.69.
+     *
+     * @hide
+     */
+    public int getWcdmaRscp() {
+        return mWcdmaRscp;
+    }
+
+    /**
+     * Get the WCDMA signal level as an ASU value between 0-96, 255 is unknown
+     *
+     * @hide
+     */
+    public int getWcdmaAsuLevel() {
+        /*
+         * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+         * 0      -120 dBm or less
+         * 1      -119 dBm
+         * 2...95 -118... -25 dBm
+         * 96     -24 dBm or greater
+         * 255    not known or not detectable
+         */
+        final int wcdmaDbm = getWcdmaDbm();
+        int wcdmaAsuLevel = 255;
+        // validateInput will always give a valid range between -120 to -24 as per ril.h. so RSCP
+        // outside range is already set to INVALID
+        if (wcdmaDbm == SignalStrength.INVALID) wcdmaAsuLevel =  255;
+        else wcdmaAsuLevel = wcdmaDbm + 120;
+        if (DBG) log("Wcdma Asu level: " + wcdmaAsuLevel);
+        return wcdmaAsuLevel;
+    }
+
+    /**
+     * Gets WCDMA signal strength as a dbm value between -120 and -24, as defined in TS 27.007 8.69.
+     *
+     * @hide
+     */
+    public int getWcdmaDbm() {
+        return mWcdmaRscp;
+    }
+
+    /**
+     * Get WCDMA as level 0..4
+     *
+     * @hide
+     */
+    public int getWcdmaLevel() {
+        int level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        if (mWcdmaDefaultSignalMeasurement == null) {
+            Log.wtf(LOG_TAG, "getWcdmaLevel - WCDMA default signal measurement is invalid.");
+            return level;
+        }
+
+        switch (mWcdmaDefaultSignalMeasurement) {
+            case MEASUMENT_TYPE_RSCP:
+                // RSCP valid values are (-120 through -24) as defined in TS 27.007 8.69
+                if (mWcdmaRscp < MIN_WCDMA_RSCP || mWcdmaRscp > MAX_WCDMA_RSCP) {
+                    if (mWcdmaRscp != INVALID) {
+                        Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSCP: mWcdmaRscp="
+                                + mWcdmaRscp);
+                    }
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[3]) {
+                    level = SIGNAL_STRENGTH_GREAT;
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[2]) {
+                    level = SIGNAL_STRENGTH_GOOD;
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[1]) {
+                    level = SIGNAL_STRENGTH_MODERATE;
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[0]) {
+                    level = SIGNAL_STRENGTH_POOR;
+                }
+                if (DBG) log("getWcdmaLevel=" + level + " WcdmaRscp=" + mWcdmaRscp);
+                break;
+
+            default:
+                // RSSI valid values are (0..31) as defined in TS 27.007 8.5
+                if (mWcdmaSignalStrength < 0 || mWcdmaSignalStrength > 31) {
+                    if (mWcdmaSignalStrength != 99) {
+                        Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSSI: mWcdmaSignalStrength="
+                                + mWcdmaSignalStrength);
+                    }
+                } else if (mWcdmaSignalStrength >= 18) {
+                    level = SIGNAL_STRENGTH_GREAT;
+                } else if (mWcdmaSignalStrength >= 13) {
+                    level = SIGNAL_STRENGTH_GOOD;
+                } else if (mWcdmaSignalStrength >= 8) {
+                    level = SIGNAL_STRENGTH_MODERATE;
+                } else if (mWcdmaSignalStrength >= 3) {
+                    level = SIGNAL_STRENGTH_POOR;
+                }
+                if (DBG) log("getWcdmaLevel=" + level + " WcdmaSignalStrength=" +
+                        mWcdmaSignalStrength);
+                break;
+
+        }
+        return level;
+    }
+
    /**
      * @return hash code
      */
@@ -920,8 +1124,11 @@
                 + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
                 + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
                 + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
-                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (mIsGsm ? 1 : 0)
-                + (mUseOnlyRsrpForLteLevel ? 1 : 0) + (Arrays.hashCode(mLteRsrpThresholds)));
+                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum)
+                + (mWcdmaSignalStrength * primeNum) + (mWcdmaRscpAsu * primeNum)
+                + (mWcdmaRscp * primeNum) + (mIsGsm ? 1 : 0) + (mUseOnlyRsrpForLteLevel ? 1 : 0)
+                + (Objects.hashCode(mWcdmaDefaultSignalMeasurement))
+                + (Arrays.hashCode(mLteRsrpThresholds)) + (Arrays.hashCode(mWcdmaRscpThresholds)));
     }
 
     /**
@@ -955,9 +1162,14 @@
                 && mLteCqi == s.mLteCqi
                 && mLteRsrpBoost == s.mLteRsrpBoost
                 && mTdScdmaRscp == s.mTdScdmaRscp
+                && mWcdmaSignalStrength == s.mWcdmaSignalStrength
+                && mWcdmaRscpAsu == s.mWcdmaRscpAsu
+                && mWcdmaRscp == s.mWcdmaRscp
                 && mIsGsm == s.mIsGsm
                 && mUseOnlyRsrpForLteLevel == s.mUseOnlyRsrpForLteLevel
-                && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds));
+                && Objects.equals(mWcdmaDefaultSignalMeasurement, s.mWcdmaDefaultSignalMeasurement)
+                && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds)
+                && Arrays.equals(mWcdmaRscpThresholds, s.mWcdmaRscpThresholds));
     }
 
     /**
@@ -980,10 +1192,15 @@
                 + " " + mLteCqi
                 + " " + mLteRsrpBoost
                 + " " + mTdScdmaRscp
+                + " " + mWcdmaSignalStrength
+                + " " + mWcdmaRscpAsu
+                + " " + mWcdmaRscp
                 + " " + (mIsGsm ? "gsm|lte" : "cdma")
                 + " " + (mUseOnlyRsrpForLteLevel ? "use_only_rsrp_for_lte_level" :
                          "use_rsrp_and_rssnr_for_lte_level")
-                + " " + (Arrays.toString(mLteRsrpThresholds)));
+                + " " + mWcdmaDefaultSignalMeasurement
+                + " " + (Arrays.toString(mLteRsrpThresholds))
+                + " " + (Arrays.toString(mWcdmaRscpThresholds)));
     }
 
     /** Returns the signal strength related to GSM. */
@@ -992,7 +1209,10 @@
         if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
             level = getTdScdmaLevel();
             if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                level = getGsmLevel();
+                level = getWcdmaLevel();
+                if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+                    level = getGsmLevel();
+                }
             }
         }
         return level;
@@ -1037,12 +1257,20 @@
         mLteCqi = m.getInt("LteCqi");
         mLteRsrpBoost = m.getInt("LteRsrpBoost");
         mTdScdmaRscp = m.getInt("TdScdma");
+        mWcdmaSignalStrength = m.getInt("WcdmaSignalStrength");
+        mWcdmaRscpAsu = m.getInt("WcdmaRscpAsu");
+        mWcdmaRscp = m.getInt("WcdmaRscp");
         mIsGsm = m.getBoolean("IsGsm");
         mUseOnlyRsrpForLteLevel = m.getBoolean("UseOnlyRsrpForLteLevel");
+        mWcdmaDefaultSignalMeasurement = m.getString("WcdmaDefaultSignalMeasurement");
         ArrayList<Integer> lteRsrpThresholds = m.getIntegerArrayList("lteRsrpThresholds");
         for (int i = 0; i < lteRsrpThresholds.size(); i++) {
             mLteRsrpThresholds[i] = lteRsrpThresholds.get(i);
         }
+        ArrayList<Integer> wcdmaRscpThresholds = m.getIntegerArrayList("wcdmaRscpThresholds");
+        for (int i = 0; i < wcdmaRscpThresholds.size(); i++) {
+            mWcdmaRscpThresholds[i] = wcdmaRscpThresholds.get(i);
+        }
     }
 
     /**
@@ -1066,13 +1294,22 @@
         m.putInt("LteCqi", mLteCqi);
         m.putInt("LteRsrpBoost", mLteRsrpBoost);
         m.putInt("TdScdma", mTdScdmaRscp);
+        m.putInt("WcdmaSignalStrength", mWcdmaSignalStrength);
+        m.putInt("WcdmaRscpAsu", mWcdmaRscpAsu);
+        m.putInt("WcdmaRscp", mWcdmaRscp);
         m.putBoolean("IsGsm", mIsGsm);
         m.putBoolean("UseOnlyRsrpForLteLevel", mUseOnlyRsrpForLteLevel);
+        m.putString("WcdmaDefaultSignalMeasurement", mWcdmaDefaultSignalMeasurement);
         ArrayList<Integer> lteRsrpThresholds = new ArrayList<Integer>();
         for (int value : mLteRsrpThresholds) {
             lteRsrpThresholds.add(value);
         }
         m.putIntegerArrayList("lteRsrpThresholds", lteRsrpThresholds);
+        ArrayList<Integer> wcdmaRscpThresholds = new ArrayList<Integer>();
+        for (int value : mWcdmaRscpThresholds) {
+            wcdmaRscpThresholds.add(value);
+        }
+        m.putIntegerArrayList("wcdmaRscpThresholds", wcdmaRscpThresholds);
     }
 
     /**
@@ -1086,6 +1323,16 @@
     }
 
     /**
+     * Gets the default threshold array for determining the display level of WCDMA signal bar.
+     *
+     * @return int array for determining the display level.
+     */
+    private int[] getDefaultWcdmaRscpThresholds() {
+        return CarrierConfigManager.getDefaultConfig().getIntArray(
+                CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
+    }
+
+    /**
      * log
      */
     private static void log(String s) {
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index cb87d1f..fb52ff7 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -3356,23 +3356,23 @@
      * Contains carrier identification information for the current subscriptions.
      * @see SubscriptionManager#getActiveSubscriptionIdList()
      */
-    public static final class CarrierIdentification implements BaseColumns {
+    public static final class CarrierId implements BaseColumns {
         /**
          * Not instantiable.
          * @hide
          */
-        private CarrierIdentification() {}
+        private CarrierId() {}
 
         /**
          * The {@code content://} style URI for this provider.
          */
-        public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification");
+        public static final Uri CONTENT_URI = Uri.parse("content://carrier_id");
 
         /**
-         * The authority string for the CarrierIdentification Provider
+         * The authority string for the CarrierId Provider
          * @hide
          */
-        public static final String AUTHORITY = "carrier_identification";
+        public static final String AUTHORITY = "carrier_id";
 
 
         /**
@@ -3399,14 +3399,14 @@
          * @see TelephonyManager#getAndroidCarrierNameForSubscription()
          * <P>Type: TEXT </P>
          */
-        public static final String NAME = "carrier_name";
+        public static final String CARRIER_NAME = "carrier_name";
 
         /**
          * A unique carrier id
          * @see TelephonyManager#getAndroidCarrierIdForSubscription()
          * <P>Type: INTEGER </P>
          */
-        public static final String CID = "carrier_id";
+        public static final String CARRIER_ID = "carrier_id";
 
         /**
          * Contains mappings between matching rules with carrier id for all carriers.
@@ -3464,7 +3464,7 @@
             /**
              * The {@code content://} URI for this table.
              */
-            public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification/all");
+            public static final Uri CONTENT_URI = Uri.parse("content://carrier_id/all");
         }
     }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fdb31eb..4d48ed0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -34,6 +34,7 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkStats;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.Handler;
@@ -73,6 +74,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.Executor;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -5220,21 +5222,35 @@
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges()
      *
      * @param request Contains all the RAT with bands/channels that need to be scanned.
+     * @param executor The executor through which the callback should be invoked.
      * @param callback Returns network scan results or errors.
      * @return A NetworkScan obj which contains a callback which can be used to stop the scan.
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public NetworkScan requestNetworkScan(
-            NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+            NetworkScanRequest request, Executor executor,
+            TelephonyScanManager.NetworkScanCallback callback) {
         synchronized (this) {
             if (mTelephonyScanManager == null) {
                 mTelephonyScanManager = new TelephonyScanManager();
             }
         }
-        return mTelephonyScanManager.requestNetworkScan(getSubId(), request, callback);
+        return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback);
+    }
+
+    /**
+     * @deprecated
+     * Use {@link
+     * #requestNetworkScan(NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+     */
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public NetworkScan requestNetworkScan(
+        NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+        return requestNetworkScan(request, AsyncTask.THREAD_POOL_EXECUTOR, callback);
     }
 
     /**
@@ -7465,4 +7481,83 @@
             Log.e(TAG, "Error calling ITelephony#setUserDataEnabled", e);
         }
     }
+
+    /**
+     * In this mode, modem will not send specified indications when screen is off.
+     * @hide
+     */
+    public static final int INDICATION_UPDATE_MODE_NORMAL                   = 1;
+
+    /**
+     * In this mode, modem will still send specified indications when screen is off.
+     * @hide
+     */
+    public static final int INDICATION_UPDATE_MODE_IGNORE_SCREEN_OFF        = 2;
+
+    /** @hide */
+    @IntDef(prefix = { "INDICATION_UPDATE_MODE_" }, value = {
+            INDICATION_UPDATE_MODE_NORMAL,
+            INDICATION_UPDATE_MODE_IGNORE_SCREEN_OFF
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface IndicationUpdateMode{}
+
+    /**
+     * The indication for signal strength update.
+     * @hide
+     */
+    public static final int INDICATION_FILTER_SIGNAL_STRENGTH               = 0x1;
+
+    /**
+     * The indication for full network state update.
+     * @hide
+     */
+    public static final int INDICATION_FILTER_FULL_NETWORK_STATE            = 0x2;
+
+    /**
+     * The indication for data call dormancy changed update.
+     * @hide
+     */
+    public static final int INDICATION_FILTER_DATA_CALL_DORMANCY_CHANGED    = 0x4;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = { "INDICATION_FILTER_" }, value = {
+            INDICATION_FILTER_SIGNAL_STRENGTH,
+            INDICATION_FILTER_FULL_NETWORK_STATE,
+            INDICATION_FILTER_DATA_CALL_DORMANCY_CHANGED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface IndicationFilters{}
+
+    /**
+     * Sets radio indication update mode. This can be used to control the behavior of indication
+     * update from modem to Android frameworks. For example, by default several indication updates
+     * are turned off when screen is off, but in some special cases (e.g. carkit is connected but
+     * screen is off) we want to turn on those indications even when the screen is off.
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @param filters Indication filters. Should be a bitmask of INDICATION_FILTER_XXX.
+     * @see #INDICATION_FILTER_SIGNAL_STRENGTH
+     * @see #INDICATION_FILTER_FULL_NETWORK_STATE
+     * @see #INDICATION_FILTER_DATA_CALL_DORMANCY_CHANGED
+     * @param updateMode The voice activation state
+     * @see #INDICATION_UPDATE_MODE_NORMAL
+     * @see #INDICATION_UPDATE_MODE_IGNORE_SCREEN_OFF
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setRadioIndicationUpdateMode(@IndicationFilters int filters,
+                                             @IndicationUpdateMode int updateMode) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.setRadioIndicationUpdateMode(getSubId(), filters, updateMode);
+            }
+        } catch (RemoteException ex) {
+            // This could happen if binder process crashes.
+            ex.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index c182e34..946cecf 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -33,6 +33,7 @@
 import android.util.SparseArray;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 import com.android.internal.telephony.ITelephony;
 
@@ -55,8 +56,10 @@
 
     /**
      * The caller of
-     * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} should
-     * implement and provide this callback so that the scan results or errors can be returned.
+     * {@link
+     * TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
+     * should implement and provide this callback so that the scan results or errors can be
+     * returned.
      */
     public static abstract class NetworkScanCallback {
         /** Returns the scan results to the user, this callback will be called multiple times. */
@@ -83,10 +86,13 @@
 
     private static class NetworkScanInfo {
         private final NetworkScanRequest mRequest;
+        private final Executor mExecutor;
         private final NetworkScanCallback mCallback;
 
-        NetworkScanInfo(NetworkScanRequest request, NetworkScanCallback callback) {
+        NetworkScanInfo(
+                NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
             mRequest = request;
+            mExecutor = executor;
             mCallback = callback;
         }
     }
@@ -112,10 +118,15 @@
                         "Failed to find NetworkScanInfo with id " + message.arg2);
                 }
                 NetworkScanCallback callback = nsi.mCallback;
+                Executor executor = nsi.mExecutor;
                 if (callback == null) {
                     throw new RuntimeException(
                         "Failed to find NetworkScanCallback with id " + message.arg2);
                 }
+                if (executor == null) {
+                    throw new RuntimeException(
+                        "Failed to find Executor with id " + message.arg2);
+                }
 
                 switch (message.what) {
                     case CALLBACK_SCAN_RESULTS:
@@ -126,21 +137,22 @@
                             for (int i = 0; i < parcelables.length; i++) {
                                 ci[i] = (CellInfo) parcelables[i];
                             }
-                            callback.onResults((List<CellInfo>) Arrays.asList(ci));
+                            executor.execute(() ->
+                                    callback.onResults((List<CellInfo>) Arrays.asList(ci)));
                         } catch (Exception e) {
                             Rlog.e(TAG, "Exception in networkscan callback onResults", e);
                         }
                         break;
                     case CALLBACK_SCAN_ERROR:
                         try {
-                            callback.onError(message.arg1);
+                            executor.execute(() -> callback.onError(message.arg1));
                         } catch (Exception e) {
                             Rlog.e(TAG, "Exception in networkscan callback onError", e);
                         }
                         break;
                     case CALLBACK_SCAN_COMPLETE:
                         try {
-                            callback.onComplete();
+                            executor.execute(() -> callback.onComplete());
                             mScanInfo.remove(message.arg2);
                         } catch (Exception e) {
                             Rlog.e(TAG, "Exception in networkscan callback onComplete", e);
@@ -171,12 +183,12 @@
      * @hide
      */
     public NetworkScan requestNetworkScan(int subId,
-            NetworkScanRequest request, NetworkScanCallback callback) {
+            NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 int scanId = telephony.requestNetworkScan(subId, request, mMessenger, new Binder());
-                saveScanInfo(scanId, request, callback);
+                saveScanInfo(scanId, request, executor, callback);
                 return new NetworkScan(scanId, subId);
             }
         } catch (RemoteException ex) {
@@ -187,9 +199,10 @@
         return null;
     }
 
-    private void saveScanInfo(int id, NetworkScanRequest request, NetworkScanCallback callback) {
+    private void saveScanInfo(
+            int id, NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
         synchronized (mScanInfo) {
-            mScanInfo.put(id, new NetworkScanInfo(request, callback));
+            mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
         }
     }
 
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index 6be7725..cc0d1c6 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -115,6 +115,9 @@
     /** Result code of an unknown error. */
     public static final int RESULT_UNKNOWN_ERROR = -1;
 
+    /** Result code when the eUICC card with the given card Id is not found. */
+    public static final int RESULT_EUICC_NOT_FOUND = -2;
+
     /**
      * Callback to receive the result of an eUICC card API.
      *
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index d96f926..a941a56 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1479,4 +1479,12 @@
      * @return boolean Return true if the switch succeeds, false if the switch fails.
      */
     boolean switchSlots(in int[] physicalSlots);
+
+    /**
+     * Sets radio indication update mode. This can be used to control the behavior of indication
+     * update from modem to Android frameworks. For example, by default several indication updates
+     * are turned off when screen is off, but in some special cases (e.g. carkit is connected but
+     * screen is off) we want to turn on those indications even when the screen is off.
+     */
+    void setRadioIndicationUpdateMode(int subId, int filters, int mode);
 }
diff --git a/test-runner/tests/Android.mk b/test-runner/tests/Android.mk
index 7ee047e4..7b9e9a4 100644
--- a/test-runner/tests/Android.mk
+++ b/test-runner/tests/Android.mk
@@ -32,6 +32,8 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := FrameworkTestRunnerTests
+# Because of android.test.mock.
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/AccessibilityEventsLogger/Android.mk b/tests/AccessibilityEventsLogger/Android.mk
index 52bc579..4224017 100644
--- a/tests/AccessibilityEventsLogger/Android.mk
+++ b/tests/AccessibilityEventsLogger/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := AccessibilityEventsLogger
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 LOCAL_PROGUARD_ENABLED := disabled
diff --git a/tests/ActivityTests/Android.mk b/tests/ActivityTests/Android.mk
index f3c6b5a..274fc5f 100644
--- a/tests/ActivityTests/Android.mk
+++ b/tests/ActivityTests/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := ActivityTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
index d01b1f9..9cbb4ed 100644
--- a/tests/AppLaunch/Android.mk
+++ b/tests/AppLaunch/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := AppLaunch
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_JAVA_LIBRARIES := legacy-android-test
diff --git a/tests/Assist/Android.mk b/tests/Assist/Android.mk
index f31c4dd..d0d3eca 100644
--- a/tests/Assist/Android.mk
+++ b/tests/Assist/Android.mk
@@ -6,5 +6,6 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := Assist
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/BandwidthTests/Android.mk b/tests/BandwidthTests/Android.mk
index 7bc5f857..d00fdc6 100644
--- a/tests/BandwidthTests/Android.mk
+++ b/tests/BandwidthTests/Android.mk
@@ -19,6 +19,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_PACKAGE_NAME := BandwidthEnforcementTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 include $(BUILD_PACKAGE)
diff --git a/tests/BatteryWaster/Android.mk b/tests/BatteryWaster/Android.mk
index 6db34a7..fb244a8 100644
--- a/tests/BatteryWaster/Android.mk
+++ b/tests/BatteryWaster/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := BatteryWaster
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/tests/BiDiTests/Android.mk b/tests/BiDiTests/Android.mk
index ae29fc2..78cf4be 100644
--- a/tests/BiDiTests/Android.mk
+++ b/tests/BiDiTests/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := BiDiTests
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
diff --git a/tests/BrowserPowerTest/Android.mk b/tests/BrowserPowerTest/Android.mk
index 59bc729..50f1d10 100644
--- a/tests/BrowserPowerTest/Android.mk
+++ b/tests/BrowserPowerTest/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := BrowserPowerTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 #LOCAL_INSTRUMENTATION_FOR := browserpowertest
 
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java
index 55ed277..9a4348e 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java
@@ -354,7 +354,7 @@
         assertNotRunning();
         FrameSlot slot = getSlot(name);
         slot.releaseFrame();
-        mFrameSlots.remove(slot);
+        mFrameSlots.remove(name);
     }
 
     /**
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk
index 527d1bbf..541bddc 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk
@@ -19,6 +19,7 @@
 LOCAL_MODULE_TAGS := tests
 
 # LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_PACKAGE_NAME := SmartCamera-tests
 
diff --git a/tests/CameraPrewarmTest/Android.mk b/tests/CameraPrewarmTest/Android.mk
index b6316f0..e128504 100644
--- a/tests/CameraPrewarmTest/Android.mk
+++ b/tests/CameraPrewarmTest/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := CameraPrewarmTest
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
diff --git a/tests/CanvasCompare/Android.mk b/tests/CanvasCompare/Android.mk
index 90de503..6b850a9 100644
--- a/tests/CanvasCompare/Android.mk
+++ b/tests/CanvasCompare/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
 LOCAL_PACKAGE_NAME := CanvasCompare
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/Compatibility/Android.mk b/tests/Compatibility/Android.mk
index 82e2126..9c47a26 100644
--- a/tests/Compatibility/Android.mk
+++ b/tests/Compatibility/Android.mk
@@ -24,6 +24,7 @@
 
 
 LOCAL_PACKAGE_NAME := AppCompatibilityTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 include $(BUILD_PACKAGE)
 
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
index c9f1161..e568264 100644
--- a/tests/CoreTests/android/Android.mk
+++ b/tests/CoreTests/android/Android.mk
@@ -10,5 +10,6 @@
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 
 LOCAL_PACKAGE_NAME := CoreTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/DataIdleTest/Android.mk b/tests/DataIdleTest/Android.mk
index 4e15729..17ba75f 100644
--- a/tests/DataIdleTest/Android.mk
+++ b/tests/DataIdleTest/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_PACKAGE_NAME := DataIdleTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/DozeTest/Android.mk b/tests/DozeTest/Android.mk
index 01f10e5..ec250ff 100644
--- a/tests/DozeTest/Android.mk
+++ b/tests/DozeTest/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := DozeTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/DpiTest/Android.mk b/tests/DpiTest/Android.mk
index f55ce6e..e69d082 100644
--- a/tests/DpiTest/Android.mk
+++ b/tests/DpiTest/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := DensityTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/FeatureSplit/base/Android.mk b/tests/FeatureSplit/base/Android.mk
index 93f6d7a..5ddceda 100644
--- a/tests/FeatureSplit/base/Android.mk
+++ b/tests/FeatureSplit/base/Android.mk
@@ -19,6 +19,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := FeatureSplitBase
+LOCAL_SDK_VERSION := current
 LOCAL_EXPORT_PACKAGE_RESOURCES := true
 
 LOCAL_MODULE_TAGS := tests
diff --git a/tests/FeatureSplit/feature1/Android.mk b/tests/FeatureSplit/feature1/Android.mk
index e6ba5c2..d4d2589 100644
--- a/tests/FeatureSplit/feature1/Android.mk
+++ b/tests/FeatureSplit/feature1/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := FeatureSplit1
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_APK_LIBRARIES := FeatureSplitBase
diff --git a/tests/FeatureSplit/feature2/Android.mk b/tests/FeatureSplit/feature2/Android.mk
index c8e8609..5e5e78b 100644
--- a/tests/FeatureSplit/feature2/Android.mk
+++ b/tests/FeatureSplit/feature2/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_USE_AAPT2 := true
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := FeatureSplit2
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_APK_LIBRARIES := FeatureSplitBase
diff --git a/tests/FixVibrateSetting/Android.mk b/tests/FixVibrateSetting/Android.mk
index 2a88e5a..86db09e 100644
--- a/tests/FixVibrateSetting/Android.mk
+++ b/tests/FixVibrateSetting/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := FixVibrateSetting
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
index d2ec753..b083c12 100644
--- a/tests/FrameworkPerf/Android.mk
+++ b/tests/FrameworkPerf/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := FrameworkPerf
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
diff --git a/tests/GridLayoutTest/Android.mk b/tests/GridLayoutTest/Android.mk
index a02918b..e7e3ccd 100644
--- a/tests/GridLayoutTest/Android.mk
+++ b/tests/GridLayoutTest/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := GridLayoutTest
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/HierarchyViewerTest/Android.mk b/tests/HierarchyViewerTest/Android.mk
index f8c8656..cf1a512 100644
--- a/tests/HierarchyViewerTest/Android.mk
+++ b/tests/HierarchyViewerTest/Android.mk
@@ -6,8 +6,9 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := HierarchyViewerTest
+LOCAL_SDK_VERSION := current
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
+LOCAL_STATIC_JAVA_LIBRARIES := junit
 
 include $(BUILD_PACKAGE)
diff --git a/tests/HwAccelerationTest/Android.mk b/tests/HwAccelerationTest/Android.mk
index d4743f9..11ea954 100644
--- a/tests/HwAccelerationTest/Android.mk
+++ b/tests/HwAccelerationTest/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := HwAccelerationTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/ImfTest/Android.mk b/tests/ImfTest/Android.mk
index eb5327b..a8f5b08 100644
--- a/tests/ImfTest/Android.mk
+++ b/tests/ImfTest/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := ImfTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/ImfTest/tests/Android.mk b/tests/ImfTest/tests/Android.mk
index 6042471..2a49998 100644
--- a/tests/ImfTest/tests/Android.mk
+++ b/tests/ImfTest/tests/Android.mk
@@ -11,6 +11,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 
 LOCAL_PACKAGE_NAME := ImfTestTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_INSTRUMENTATION_FOR := ImfTest
 
diff --git a/tests/Internal/Android.mk b/tests/Internal/Android.mk
index fc001e9..a8fb395 100644
--- a/tests/Internal/Android.mk
+++ b/tests/Internal/Android.mk
@@ -18,6 +18,7 @@
 LOCAL_CERTIFICATE := platform
 
 LOCAL_PACKAGE_NAME := InternalTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 include $(BUILD_PACKAGE)
diff --git a/tests/JobSchedulerTestApp/Android.mk b/tests/JobSchedulerTestApp/Android.mk
index 7336d8c..48ee1f6 100644
--- a/tests/JobSchedulerTestApp/Android.mk
+++ b/tests/JobSchedulerTestApp/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := JobSchedulerTestApp
+LOCAL_SDK_VERSION := current
 
 LOCAL_PROGUARD_ENABLED := disabled
 
diff --git a/tests/LargeAssetTest/Android.mk b/tests/LargeAssetTest/Android.mk
index cb7f01b..f6d98bf 100644
--- a/tests/LargeAssetTest/Android.mk
+++ b/tests/LargeAssetTest/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := LargeAssetTest
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/tests/LegacyAssistant/Android.mk b/tests/LegacyAssistant/Android.mk
index 0ad48d1..a583369 100644
--- a/tests/LegacyAssistant/Android.mk
+++ b/tests/LegacyAssistant/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := LegacyAssistant
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
diff --git a/tests/LocationTracker/Android.mk b/tests/LocationTracker/Android.mk
index b142d22..0d51b3b 100644
--- a/tests/LocationTracker/Android.mk
+++ b/tests/LocationTracker/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := LocationTracker
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/LockTaskTests/Android.mk b/tests/LockTaskTests/Android.mk
index ed58643..a693eaa 100644
--- a/tests/LockTaskTests/Android.mk
+++ b/tests/LockTaskTests/Android.mk
@@ -5,6 +5,7 @@
 LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/priv-app
 
 LOCAL_PACKAGE_NAME := LockTaskTests
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 LOCAL_SRC_FILES := $(call all-Iaidl-files-under, src) $(call all-java-files-under, src)
diff --git a/tests/LotsOfApps/Android.mk b/tests/LotsOfApps/Android.mk
index 0ef9550..bee3bcc 100644
--- a/tests/LotsOfApps/Android.mk
+++ b/tests/LotsOfApps/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := LotsOfApps
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 LOCAL_PROGUARD_ENABLED := disabled
diff --git a/tests/LowStorageTest/Android.mk b/tests/LowStorageTest/Android.mk
index ab5b9e9..bdde6bd 100644
--- a/tests/LowStorageTest/Android.mk
+++ b/tests/LowStorageTest/Android.mk
@@ -21,5 +21,6 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := lowstoragetest
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_PACKAGE)
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
index 578e628..bab6a70 100644
--- a/tests/MemoryUsage/Android.mk
+++ b/tests/MemoryUsage/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := MemoryUsage
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
index dd9ff11..e29090b 100644
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ b/tests/NetworkSecurityConfigTest/Android.mk
@@ -12,5 +12,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := NetworkSecurityConfigTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
index 9fc6403..41f3f64 100644
--- a/tests/OneMedia/Android.mk
+++ b/tests/OneMedia/Android.mk
@@ -7,6 +7,7 @@
         $(call all-Iaidl-files-under, src)
 
 LOCAL_PACKAGE_NAME := OneMedia
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
diff --git a/tests/RenderThreadTest/Android.mk b/tests/RenderThreadTest/Android.mk
index e07e943..4e5f35b 100644
--- a/tests/RenderThreadTest/Android.mk
+++ b/tests/RenderThreadTest/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := RenderThreadTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES += android-common
 
diff --git a/tests/SerialChat/Android.mk b/tests/SerialChat/Android.mk
index a534e1a..ed6ca999 100644
--- a/tests/SerialChat/Android.mk
+++ b/tests/SerialChat/Android.mk
@@ -22,5 +22,6 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := SerialChat
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/ServiceCrashTest/Android.mk b/tests/ServiceCrashTest/Android.mk
index d1f8456..3aa7132 100644
--- a/tests/ServiceCrashTest/Android.mk
+++ b/tests/ServiceCrashTest/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := ServiceCrashTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_JAVA_LIBRARIES := legacy-android-test
diff --git a/tests/SharedLibrary/client/Android.mk b/tests/SharedLibrary/client/Android.mk
index a04fb05..9e76c40 100644
--- a/tests/SharedLibrary/client/Android.mk
+++ b/tests/SharedLibrary/client/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_RES_LIBRARIES := SharedLibrary
 
 LOCAL_PACKAGE_NAME := SharedLibraryClient
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk
index 78fcb8b..3c1ca87 100644
--- a/tests/SharedLibrary/lib/Android.mk
+++ b/tests/SharedLibrary/lib/Android.mk
@@ -6,6 +6,7 @@
 
 LOCAL_AAPT_FLAGS := --shared-lib
 LOCAL_PACKAGE_NAME := SharedLibrary
+LOCAL_SDK_VERSION := current
 
 LOCAL_EXPORT_PACKAGE_RESOURCES := true
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/tests/ShowWhenLockedApp/Android.mk b/tests/ShowWhenLockedApp/Android.mk
index 0064167..41e0ac4 100644
--- a/tests/ShowWhenLockedApp/Android.mk
+++ b/tests/ShowWhenLockedApp/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := ShowWhenLocked
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/SmokeTestApps/Android.mk b/tests/SmokeTestApps/Android.mk
index 3f5f011..1f564e0 100644
--- a/tests/SmokeTestApps/Android.mk
+++ b/tests/SmokeTestApps/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := SmokeTestTriggerApps
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/SoundTriggerTestApp/Android.mk b/tests/SoundTriggerTestApp/Android.mk
index c327b09..73fb5e8 100644
--- a/tests/SoundTriggerTestApp/Android.mk
+++ b/tests/SoundTriggerTestApp/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := SoundTriggerTestApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index 359484e..774fc85 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -31,5 +31,6 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := SoundTriggerTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/Split/Android.mk b/tests/Split/Android.mk
index b068bef..4d15b2d 100644
--- a/tests/Split/Android.mk
+++ b/tests/Split/Android.mk
@@ -19,6 +19,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := Split
+LOCAL_SDK_VERSION := current
 
 LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4
 
diff --git a/tests/StatusBar/Android.mk b/tests/StatusBar/Android.mk
index 502657f..e845335 100644
--- a/tests/StatusBar/Android.mk
+++ b/tests/StatusBar/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := StatusBarTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 LOCAL_PROGUARD_ENABLED := disabled
diff --git a/tests/SystemUIDemoModeController/Android.mk b/tests/SystemUIDemoModeController/Android.mk
index 64ea63c..cc6fa8d 100644
--- a/tests/SystemUIDemoModeController/Android.mk
+++ b/tests/SystemUIDemoModeController/Android.mk
@@ -6,5 +6,6 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := DemoModeController
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_PACKAGE)
diff --git a/tests/TouchLatency/Android.mk b/tests/TouchLatency/Android.mk
index 969283d..2334bd8 100644
--- a/tests/TouchLatency/Android.mk
+++ b/tests/TouchLatency/Android.mk
@@ -15,6 +15,7 @@
     --auto-add-overlay
 
 LOCAL_PACKAGE_NAME := TouchLatency
+LOCAL_SDK_VERSION := current
 
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
diff --git a/tests/TransformTest/Android.mk b/tests/TransformTest/Android.mk
index 2d3637d..5340cdd 100644
--- a/tests/TransformTest/Android.mk
+++ b/tests/TransformTest/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := TransformTest
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/TransitionTests/Android.mk b/tests/TransitionTests/Android.mk
index 22fa638..a696156 100644
--- a/tests/TransitionTests/Android.mk
+++ b/tests/TransitionTests/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := TransitionTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES += android-common
 
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
index 3c3cd77..4fee739 100644
--- a/tests/TtsTests/Android.mk
+++ b/tests/TtsTests/Android.mk
@@ -24,5 +24,6 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := TtsTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
index 6b5c999..6735c7c 100644
--- a/tests/UsageStatsTest/Android.mk
+++ b/tests/UsageStatsTest/Android.mk
@@ -11,5 +11,6 @@
 LOCAL_CERTIFICATE := platform
 
 LOCAL_PACKAGE_NAME := UsageStatsTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.mk b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.mk
index 3137a73..cd7aaed 100644
--- a/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.mk
+++ b/tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := AoapTestDeviceApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.mk b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.mk
index 354e8c9..bd8a51b 100644
--- a/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.mk
+++ b/tests/UsbHostExternalManagmentTest/AoapTestHost/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := AoapTestHostApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
diff --git a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.mk b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.mk
index 2d6d6ea8..fed454e 100644
--- a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.mk
+++ b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := UsbHostExternalManagementTestApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_PRIVILEGED_MODULE := true
 # TODO remove tests tag
diff --git a/tests/UsesFeature2Test/Android.mk b/tests/UsesFeature2Test/Android.mk
index cc784d7..4cba4ff 100644
--- a/tests/UsesFeature2Test/Android.mk
+++ b/tests/UsesFeature2Test/Android.mk
@@ -19,6 +19,7 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 LOCAL_PACKAGE_NAME := UsesFeature2Test
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/VectorDrawableTest/Android.mk b/tests/VectorDrawableTest/Android.mk
index dd8a4d4..155b2bc 100644
--- a/tests/VectorDrawableTest/Android.mk
+++ b/tests/VectorDrawableTest/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := VectorDrawableTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/VoiceEnrollment/Android.mk b/tests/VoiceEnrollment/Android.mk
index 2ab3d02..725e2bd 100644
--- a/tests/VoiceEnrollment/Android.mk
+++ b/tests/VoiceEnrollment/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := VoiceEnrollment
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/tests/VoiceInteraction/Android.mk b/tests/VoiceInteraction/Android.mk
index 8decca7..aa48b42 100644
--- a/tests/VoiceInteraction/Android.mk
+++ b/tests/VoiceInteraction/Android.mk
@@ -6,5 +6,6 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := VoiceInteraction
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
diff --git a/tests/WallpaperTest/Android.mk b/tests/WallpaperTest/Android.mk
index b4259cd..4815500 100644
--- a/tests/WallpaperTest/Android.mk
+++ b/tests/WallpaperTest/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_PACKAGE_NAME := WallpaperTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_PROGUARD_ENABLED := disabled
 
diff --git a/tests/WindowManagerStressTest/Android.mk b/tests/WindowManagerStressTest/Android.mk
index e4cbe93..6f4403f 100644
--- a/tests/WindowManagerStressTest/Android.mk
+++ b/tests/WindowManagerStressTest/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := WindowManagerStressTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.mk b/tests/appwidgets/AppWidgetHostTest/Android.mk
index 4d0c704..c9e6c6b 100644
--- a/tests/appwidgets/AppWidgetHostTest/Android.mk
+++ b/tests/appwidgets/AppWidgetHostTest/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := AppWidgetHostTest
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.mk b/tests/appwidgets/AppWidgetProviderTest/Android.mk
index 6084fb9..b26c60b 100644
--- a/tests/appwidgets/AppWidgetProviderTest/Android.mk
+++ b/tests/appwidgets/AppWidgetProviderTest/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := AppWidgetProvider
+LOCAL_SDK_VERSION := current
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/tests/backup/Android.mk b/tests/backup/Android.mk
index 202a699..e9618300 100644
--- a/tests/backup/Android.mk
+++ b/tests/backup/Android.mk
@@ -40,6 +40,7 @@
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := BackupTest
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_PROGUARD_ENABLED := disabled
 
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 4907894..a6559e7 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -24,6 +24,7 @@
     android.test.runner
 
 LOCAL_PACKAGE_NAME := FrameworksNetTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_CERTIFICATE := platform
diff --git a/tests/net/java/android/app/usage/NetworkStatsManagerTest.java b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
new file mode 100644
index 0000000..25e1474
--- /dev/null
+++ b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2018 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.app.usage;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.net.ConnectivityManager;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats.Entry;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkStatsManagerTest {
+
+    private @Mock INetworkStatsService mService;
+    private @Mock INetworkStatsSession mStatsSession;
+
+    private NetworkStatsManager mManager;
+
+    // TODO: change to NetworkTemplate.MATCH_MOBILE once internal constant rename is merged to aosp.
+    private static final int MATCH_MOBILE_ALL = 1;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mManager = new NetworkStatsManager(InstrumentationRegistry.getContext(), mService);
+    }
+
+    @Test
+    public void testQueryDetails() throws RemoteException {
+        final String subscriberId = "subid";
+        final long startTime = 1;
+        final long endTime = 100;
+        final int uid1 = 10001;
+        final int uid2 = 10002;
+        final int uid3 = 10003;
+
+        Entry uid1Entry1 = new Entry("if1", uid1,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                100, 10, 200, 20, 0);
+
+        Entry uid1Entry2 = new Entry(
+                "if2", uid1,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                100, 10, 200, 20, 0);
+
+        Entry uid2Entry1 = new Entry("if1", uid2,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                150, 10, 250, 20, 0);
+
+        Entry uid2Entry2 = new Entry(
+                "if2", uid2,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                150, 10, 250, 20, 0);
+
+        NetworkStatsHistory history1 = new NetworkStatsHistory(10, 2);
+        history1.recordData(10, 20, uid1Entry1);
+        history1.recordData(20, 30, uid1Entry2);
+
+        NetworkStatsHistory history2 = new NetworkStatsHistory(10, 2);
+        history1.recordData(30, 40, uid2Entry1);
+        history1.recordData(35, 45, uid2Entry2);
+
+
+        when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession);
+        when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2, uid3 });
+
+        when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
+                eq(uid1), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)))
+                .then((InvocationOnMock inv) -> {
+                    NetworkTemplate template = inv.getArgument(0);
+                    assertEquals(MATCH_MOBILE_ALL, template.getMatchRule());
+                    assertEquals(subscriberId, template.getSubscriberId());
+                    return history1;
+                });
+
+        when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
+                eq(uid2), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)))
+                .then((InvocationOnMock inv) -> {
+                    NetworkTemplate template = inv.getArgument(0);
+                    assertEquals(MATCH_MOBILE_ALL, template.getMatchRule());
+                    assertEquals(subscriberId, template.getSubscriberId());
+                    return history2;
+                });
+
+
+        NetworkStats stats = mManager.queryDetails(
+                ConnectivityManager.TYPE_MOBILE, subscriberId, startTime, endTime);
+
+        NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+
+        // First 2 buckets exactly match entry timings
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(10, bucket.getStartTimeStamp());
+        assertEquals(20, bucket.getEndTimeStamp());
+        assertBucketMatches(uid1Entry1, bucket);
+
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(20, bucket.getStartTimeStamp());
+        assertEquals(30, bucket.getEndTimeStamp());
+        assertBucketMatches(uid1Entry2, bucket);
+
+        // 30 -> 40: contains uid2Entry1 and half of uid2Entry2
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(30, bucket.getStartTimeStamp());
+        assertEquals(40, bucket.getEndTimeStamp());
+        assertEquals(225, bucket.getRxBytes());
+        assertEquals(15, bucket.getRxPackets());
+        assertEquals(375, bucket.getTxBytes());
+        assertEquals(30, bucket.getTxPackets());
+
+        // 40 -> 50: contains half of uid2Entry2
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(40, bucket.getStartTimeStamp());
+        assertEquals(50, bucket.getEndTimeStamp());
+        assertEquals(75, bucket.getRxBytes());
+        assertEquals(5, bucket.getRxPackets());
+        assertEquals(125, bucket.getTxBytes());
+        assertEquals(10, bucket.getTxPackets());
+
+        assertFalse(stats.hasNextBucket());
+    }
+
+    @Test
+    public void testQueryDetails_NoSubscriberId() throws RemoteException {
+        final long startTime = 1;
+        final long endTime = 100;
+        final int uid1 = 10001;
+        final int uid2 = 10002;
+
+        when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession);
+        when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2 });
+
+        NetworkStats stats = mManager.queryDetails(
+                ConnectivityManager.TYPE_MOBILE, null, startTime, endTime);
+
+        when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
+                anyInt(), anyInt(), anyInt(), anyInt(), anyLong(), anyLong()))
+                .thenReturn(new NetworkStatsHistory(10, 0));
+
+        verify(mStatsSession, times(1)).getHistoryIntervalForUid(
+                argThat((NetworkTemplate t) ->
+                        // No subscriberId: MATCH_MOBILE_WILDCARD template
+                        t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD),
+                eq(uid1), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime));
+
+        verify(mStatsSession, times(1)).getHistoryIntervalForUid(
+                argThat((NetworkTemplate t) ->
+                        // No subscriberId: MATCH_MOBILE_WILDCARD template
+                        t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD),
+                eq(uid2), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime));
+
+        assertFalse(stats.hasNextBucket());
+    }
+
+    private void assertBucketMatches(Entry expected,
+            NetworkStats.Bucket actual) {
+        assertEquals(expected.uid, actual.getUid());
+        assertEquals(expected.rxBytes, actual.getRxBytes());
+        assertEquals(expected.rxPackets, actual.getRxPackets());
+        assertEquals(expected.txBytes, actual.getTxBytes());
+        assertEquals(expected.txPackets, actual.getTxPackets());
+    }
+}
diff --git a/tests/net/java/android/net/IpPrefixTest.java b/tests/net/java/android/net/IpPrefixTest.java
index b5b2c07..1f1ba2e 100644
--- a/tests/net/java/android/net/IpPrefixTest.java
+++ b/tests/net/java/android/net/IpPrefixTest.java
@@ -223,14 +223,14 @@
     }
 
     @Test
-    public void testContains() {
+    public void testContainsInetAddress() {
         IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
         assertTrue(p.contains(Address("2001:db8:f00::ace:d00c")));
         assertTrue(p.contains(Address("2001:db8:f00::ace:d00d")));
         assertFalse(p.contains(Address("2001:db8:f00::ace:d00e")));
         assertFalse(p.contains(Address("2001:db8:f00::bad:d00d")));
         assertFalse(p.contains(Address("2001:4868:4860::8888")));
-        assertFalse(p.contains(null));
+        assertFalse(p.contains((InetAddress)null));
         assertFalse(p.contains(Address("8.8.8.8")));
 
         p = new IpPrefix("192.0.2.0/23");
@@ -251,6 +251,53 @@
     }
 
     @Test
+    public void testContainsIpPrefix() {
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("0.0.0.0/0")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/0")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/8")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/24")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/23")));
+
+        assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.2.3.4/8")));
+        assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.254.12.9/8")));
+        assertTrue(new IpPrefix("1.2.3.4/21").containsPrefix(new IpPrefix("1.2.3.4/21")));
+        assertTrue(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.4/32")));
+
+        assertTrue(new IpPrefix("1.2.3.4/20").containsPrefix(new IpPrefix("1.2.3.0/24")));
+
+        assertFalse(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.5/32")));
+        assertFalse(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("2.2.3.4/8")));
+        assertFalse(new IpPrefix("0.0.0.0/16").containsPrefix(new IpPrefix("0.0.0.0/15")));
+        assertFalse(new IpPrefix("100.0.0.0/8").containsPrefix(new IpPrefix("99.0.0.0/8")));
+
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("::/0")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/1")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("3d8a:661:a0::770/8")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/8")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/64")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/113")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/128")));
+
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/64")));
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/120")));
+        assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/32")));
+        assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2006:db8:f00::ace:d00d/96")));
+
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/128")));
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/100").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:ccaf/110")));
+
+        assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00e/128")));
+        assertFalse(new IpPrefix("::/30").containsPrefix(new IpPrefix("::/29")));
+    }
+
+    @Test
     public void testHashCode() {
         IpPrefix p = new IpPrefix(new byte[4], 0);
         Random random = new Random();
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index 0ef976c..17932a4 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -229,7 +229,9 @@
         assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400)));
 
         NetworkCapabilities netCap2 = new NetworkCapabilities();
-        assertFalse(netCap2.satisfiedByUids(netCap));
+        // A new netcap object has null UIDs, so anything will satisfy it.
+        assertTrue(netCap2.satisfiedByUids(netCap));
+        // Still not equal though.
         assertFalse(netCap2.equalsUids(netCap));
         netCap2.setUids(uids);
         assertTrue(netCap2.satisfiedByUids(netCap));
@@ -246,7 +248,7 @@
         assertTrue(netCap.appliesToUid(650));
         assertFalse(netCap.appliesToUid(500));
 
-        assertFalse(new NetworkCapabilities().satisfiedByUids(netCap));
+        assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
         netCap.combineCapabilities(new NetworkCapabilities());
         assertTrue(netCap.appliesToUid(500));
         assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000)));
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index 8d51c3b..a5ee8e3 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -19,8 +19,10 @@
 import android.net.NetworkUtils;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.util.TreeSet;
 
 import junit.framework.TestCase;
 
@@ -67,4 +69,101 @@
         assertInvalidNetworkMask(IPv4Address("255.255.255.253"));
         assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
     }
+
+    @SmallTest
+    public void testRoutedIPv4AddressCount() {
+        final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
+        // No routes routes to no addresses.
+        assertEquals(0, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("0.0.0.0/0"));
+        assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("20.18.0.0/16"));
+        set.add(new IpPrefix("20.18.0.0/24"));
+        set.add(new IpPrefix("20.18.0.0/8"));
+        // There is a default route, still covers everything
+        assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("20.18.0.0/24"));
+        set.add(new IpPrefix("20.18.0.0/8"));
+        // The 8-length includes the 24-length prefix
+        assertEquals(1l << 24, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("10.10.10.126/25"));
+        // The 8-length does not include this 25-length prefix
+        assertEquals((1l << 24) + (1 << 7), NetworkUtils.routedIPv4AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("1.2.3.4/32"));
+        set.add(new IpPrefix("1.2.3.4/32"));
+        set.add(new IpPrefix("1.2.3.4/32"));
+        set.add(new IpPrefix("1.2.3.4/32"));
+        assertEquals(1l, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("1.2.3.5/32"));
+        set.add(new IpPrefix("1.2.3.6/32"));
+
+        set.add(new IpPrefix("1.2.3.7/32"));
+        set.add(new IpPrefix("1.2.3.8/32"));
+        set.add(new IpPrefix("1.2.3.9/32"));
+        set.add(new IpPrefix("1.2.3.0/32"));
+        assertEquals(7l, NetworkUtils.routedIPv4AddressCount(set));
+
+        // 1.2.3.4/30 eats 1.2.3.{4-7}/32
+        set.add(new IpPrefix("1.2.3.4/30"));
+        set.add(new IpPrefix("6.2.3.4/28"));
+        set.add(new IpPrefix("120.2.3.4/16"));
+        assertEquals(7l - 4 + 4 + 16 + 65536, NetworkUtils.routedIPv4AddressCount(set));
+    }
+
+    @SmallTest
+    public void testRoutedIPv6AddressCount() {
+        final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
+        // No routes routes to no addresses.
+        assertEquals(BigInteger.ZERO, NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("::/0"));
+        assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("1234:622a::18/64"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8"));
+        // There is a default route, still covers everything
+        assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8"));
+        // The 8-length includes the 96-length prefix
+        assertEquals(BigInteger.ONE.shiftLeft(120), NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("10::26/64"));
+        // The 8-length does not include this 64-length prefix
+        assertEquals(BigInteger.ONE.shiftLeft(120).add(BigInteger.ONE.shiftLeft(64)),
+                NetworkUtils.routedIPv6AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        assertEquals(BigInteger.ONE, NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad5/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad6/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad7/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad8/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad9/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad0/128"));
+        assertEquals(BigInteger.valueOf(7), NetworkUtils.routedIPv6AddressCount(set));
+
+        // add4:f00:80:f7:1111::6ad4/126 eats add4:f00:8[:f7:1111::6ad{4-7}/128
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/126"));
+        set.add(new IpPrefix("d00d:f00:80:f7:1111::6ade/124"));
+        set.add(new IpPrefix("f00b:a33::/112"));
+        assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
+                NetworkUtils.routedIPv6AddressCount(set));
+    }
 }
diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpClientTest.java
similarity index 80%
rename from tests/net/java/android/net/ip/IpManagerTest.java
rename to tests/net/java/android/net/ip/IpClientTest.java
index 22d88fb..e9e880d 100644
--- a/tests/net/java/android/net/ip/IpManagerTest.java
+++ b/tests/net/java/android/net/ip/IpClientTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -38,10 +39,12 @@
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.MacAddress;
 import android.net.RouteInfo;
-import android.net.ip.IpManager.Callback;
-import android.net.ip.IpManager.InitialConfiguration;
-import android.net.ip.IpManager.ProvisioningConfiguration;
+import android.net.ip.IpClient.Callback;
+import android.net.ip.IpClient.InitialConfiguration;
+import android.net.ip.IpClient.ProvisioningConfiguration;
+import android.net.util.InterfaceParams;
 import android.os.INetworkManagementService;
 import android.provider.Settings;
 import android.support.test.filters.SmallTest;
@@ -68,15 +71,19 @@
 import java.util.Set;
 
 /**
- * Tests for IpManager.
+ * Tests for IpClient.
  */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
-public class IpManagerTest {
+public class IpClientTest {
     private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
 
     private static final String VALID = "VALID";
     private static final String INVALID = "INVALID";
+    private static final String TEST_IFNAME = "test_wlan0";
+    private static final int TEST_IFINDEX = 1001;
+    // See RFC 7042#section-2.1.2 for EUI-48 documentation values.
+    private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");
 
     @Mock private Context mContext;
     @Mock private INetworkManagementService mNMService;
@@ -84,9 +91,11 @@
     @Mock private Resources mResources;
     @Mock private Callback mCb;
     @Mock private AlarmManager mAlarm;
+    @Mock private IpClient.Dependencies mDependecies;
     private MockContentResolver mContentResolver;
 
-    BaseNetworkObserver mObserver;
+    private BaseNetworkObserver mObserver;
+    private InterfaceParams mIfParams;
 
     @Before
     public void setUp() throws Exception {
@@ -100,10 +109,23 @@
         mContentResolver = new MockContentResolver();
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
+
+        mIfParams = null;
+
+        when(mDependecies.getNMS()).thenReturn(mNMService);
+        when(mDependecies.getNetd()).thenReturn(mNetd);
     }
 
-    private IpManager makeIpManager(String ifname) throws Exception {
-        final IpManager ipm = new IpManager(mContext, ifname, mCb, mNMService, mNetd);
+    private void setTestInterfaceParams(String ifname) {
+        mIfParams = (ifname != null)
+                ? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC)
+                : null;
+        when(mDependecies.getInterfaceParams(anyString())).thenReturn(mIfParams);
+    }
+
+    private IpClient makeIpClient(String ifname) throws Exception {
+        setTestInterfaceParams(ifname);
+        final IpClient ipc = new IpClient(mContext, ifname, mCb, mDependecies);
         verify(mNMService, timeout(100).times(1)).disableIpv6(ifname);
         verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(ifname);
         ArgumentCaptor<BaseNetworkObserver> arg =
@@ -111,23 +133,54 @@
         verify(mNMService, times(1)).registerObserver(arg.capture());
         mObserver = arg.getValue();
         reset(mNMService);
-        return ipm;
+        return ipc;
     }
 
     @Test
-    public void testNullCallbackDoesNotThrow() throws Exception {
-        final IpManager ipm = new IpManager(mContext, "lo", null, mNMService);
+    public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
+        setTestInterfaceParams(null);
+        try {
+            final IpClient ipc = new IpClient(mContext, null, mCb, mDependecies);
+            ipc.shutdown();
+            fail();
+        } catch (NullPointerException npe) {
+            // Phew; null interface names not allowed.
+        }
+    }
+
+    @Test
+    public void testNullCallbackMostDefinitelyThrows() throws Exception {
+        final String ifname = "lo";
+        setTestInterfaceParams(ifname);
+        try {
+            final IpClient ipc = new IpClient(mContext, ifname, null, mDependecies);
+            ipc.shutdown();
+            fail();
+        } catch (NullPointerException npe) {
+            // Phew; null callbacks not allowed.
+        }
     }
 
     @Test
     public void testInvalidInterfaceDoesNotThrow() throws Exception {
-        final IpManager ipm = new IpManager(mContext, "test_wlan0", mCb, mNMService);
+        setTestInterfaceParams(TEST_IFNAME);
+        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
+        ipc.shutdown();
+    }
+
+    @Test
+    public void testInterfaceNotFoundFailsImmediately() throws Exception {
+        setTestInterfaceParams(null);
+        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
+        ipc.startProvisioning(new IpClient.ProvisioningConfiguration());
+        verify(mCb, times(1)).onProvisioningFailure(any());
+        ipc.shutdown();
     }
 
     @Test
     public void testDefaultProvisioningConfiguration() throws Exception {
-        final String iface = "test_wlan0";
-        final IpManager ipm = makeIpManager(iface);
+        final String iface = TEST_IFNAME;
+        final IpClient ipc = makeIpClient(iface);
 
         ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
                 .withoutIPv4()
@@ -136,20 +189,20 @@
                 .withoutIpReachabilityMonitor()
                 .build();
 
-        ipm.startProvisioning(config);
+        ipc.startProvisioning(config);
         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
         verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
         verify(mCb, never()).onProvisioningFailure(any());
 
-        ipm.stop();
+        ipc.shutdown();
         verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
         verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
     }
 
     @Test
     public void testProvisioningWithInitialConfiguration() throws Exception {
-        final String iface = "test_wlan0";
-        final IpManager ipm = makeIpManager(iface);
+        final String iface = TEST_IFNAME;
+        final IpClient ipc = makeIpClient(iface);
 
         String[] addresses = {
             "fe80::a4be:f92:e1f7:22d1/64",
@@ -164,7 +217,7 @@
                 .withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips()))
                 .build();
 
-        ipm.startProvisioning(config);
+        ipc.startProvisioning(config);
         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
         verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
         verify(mCb, never()).onProvisioningFailure(any());
@@ -190,7 +243,7 @@
         want.setInterfaceName(iface);
         verify(mCb, timeout(100).times(1)).onProvisioningSuccess(eq(want));
 
-        ipm.stop();
+        ipc.shutdown();
         verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
         verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
     }
@@ -228,7 +281,7 @@
         };
 
         for (IsProvisionedTestCase testcase : testcases) {
-            if (IpManager.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
+            if (IpClient.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
                 fail(testcase.errorMessage());
             }
         }
@@ -424,11 +477,11 @@
         List<String> list3 = Arrays.asList("bar", "baz");
         List<String> list4 = Arrays.asList("foo", "bar", "baz");
 
-        assertTrue(IpManager.all(list1, (x) -> false));
-        assertFalse(IpManager.all(list2, (x) -> false));
-        assertTrue(IpManager.all(list3, (x) -> true));
-        assertTrue(IpManager.all(list2, (x) -> x.charAt(0) == 'f'));
-        assertFalse(IpManager.all(list4, (x) -> x.charAt(0) == 'f'));
+        assertTrue(IpClient.all(list1, (x) -> false));
+        assertFalse(IpClient.all(list2, (x) -> false));
+        assertTrue(IpClient.all(list3, (x) -> true));
+        assertTrue(IpClient.all(list2, (x) -> x.charAt(0) == 'f'));
+        assertFalse(IpClient.all(list4, (x) -> x.charAt(0) == 'f'));
     }
 
     @Test
@@ -438,11 +491,11 @@
         List<String> list3 = Arrays.asList("bar", "baz");
         List<String> list4 = Arrays.asList("foo", "bar", "baz");
 
-        assertFalse(IpManager.any(list1, (x) -> true));
-        assertTrue(IpManager.any(list2, (x) -> true));
-        assertTrue(IpManager.any(list2, (x) -> x.charAt(0) == 'f'));
-        assertFalse(IpManager.any(list3, (x) -> x.charAt(0) == 'f'));
-        assertTrue(IpManager.any(list4, (x) -> x.charAt(0) == 'f'));
+        assertFalse(IpClient.any(list1, (x) -> true));
+        assertTrue(IpClient.any(list2, (x) -> true));
+        assertTrue(IpClient.any(list2, (x) -> x.charAt(0) == 'f'));
+        assertFalse(IpClient.any(list3, (x) -> x.charAt(0) == 'f'));
+        assertTrue(IpClient.any(list4, (x) -> x.charAt(0) == 'f'));
     }
 
     @Test
@@ -451,9 +504,9 @@
         List<String> list2 = Arrays.asList("foo");
         List<String> list3 = Arrays.asList("foo", "bar", "baz");
 
-        assertEquals(list1, IpManager.findAll(list1, (x) -> true));
-        assertEquals(list1, IpManager.findAll(list3, (x) -> false));
-        assertEquals(list3, IpManager.findAll(list3, (x) -> true));
-        assertEquals(list2, IpManager.findAll(list3, (x) -> x.charAt(0) == 'f'));
+        assertEquals(list1, IpClient.findAll(list1, (x) -> true));
+        assertEquals(list1, IpClient.findAll(list3, (x) -> false));
+        assertEquals(list3, IpClient.findAll(list3, (x) -> true));
+        assertEquals(list2, IpClient.findAll(list3, (x) -> x.charAt(0) == 'f'));
     }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 28f8122..5ea21ea 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -387,6 +387,7 @@
                     mScore = 20;
                     break;
                 case TRANSPORT_VPN:
+                    mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
                     mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
                     break;
                 default:
@@ -3744,14 +3745,19 @@
         final int uid = Process.myUid();
 
         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+        final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
-        final NetworkRequest genericRequest = new NetworkRequest.Builder().build();
+        final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
+        final NetworkRequest genericRequest = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN).build();
         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI).build();
         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
                 .addTransportType(TRANSPORT_VPN).build();
         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+        mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
 
@@ -3759,6 +3765,7 @@
         mWiFiNetworkAgent.connect(false);
 
         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         vpnNetworkCallback.assertNoCallback();
 
@@ -3773,16 +3780,19 @@
         vpnNetworkAgent.connect(false);
 
         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
 
         genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
 
         ranges.clear();
         vpnNetworkAgent.setUids(ranges);
 
         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
 
@@ -3790,18 +3800,21 @@
         vpnNetworkAgent.setUids(ranges);
 
         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
 
         mWiFiNetworkAgent.disconnect();
 
         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         vpnNetworkCallback.assertNoCallback();
 
         vpnNetworkAgent.disconnect();
 
         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
 
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 1dbf9b2..f59850d 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -57,9 +57,13 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.net.IpPrefix;
+import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.VpnService;
 import android.os.Build.VERSION_CODES;
@@ -90,7 +94,8 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Tests for {@link Vpn}.
@@ -563,4 +568,75 @@
             return networks.get(network);
         }).when(mConnectivityManager).getNetworkCapabilities(any());
     }
+
+    // Need multiple copies of this, but Java's Stream objects can't be reused or
+    // duplicated.
+    private Stream<String> publicIpV4Routes() {
+        return Stream.of(
+                "0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4",
+                "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6",
+                "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9",
+                "173.0.0.0/8", "174.0.0.0/7", "176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11",
+                "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15", "192.172.0.0/14",
+                "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8", "194.0.0.0/7",
+                "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4");
+    }
+
+    private Stream<String> publicIpV6Routes() {
+        return Stream.of(
+                "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6",
+                "fe00::/8", "2605:ef80:e:af1d::/64");
+    }
+
+    @Test
+    public void testProvidesRoutesToMostDestinations() {
+        final LinkProperties lp = new LinkProperties();
+
+        // Default route provides routes to all IPv4 destinations.
+        lp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // Empty LP provides routes to no destination
+        lp.clear();
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        // All IPv4 routes except for local networks. This is the case most relevant
+        // to this function. It provides routes to almost the entire space.
+        // (clone the stream so that we can reuse it later)
+        publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // Removing a 16-bit prefix, which is 65536 addresses. This is still enough to
+        // provide routes to "most" destinations.
+        lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // Remove the /2 route, which represent a quarter of the available routing space.
+        // This LP does not provides routes to "most" destinations any more.
+        lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2")));
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        lp.clear();
+        publicIpV6Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        lp.removeRoute(new RouteInfo(new IpPrefix("::/1")));
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V6 does not provide sufficient coverage but v4 does
+        publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V4 still does
+        lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V4 does not any more
+        lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2")));
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V4 does not, but V6 has sufficient coverage again
+        lp.addRoute(new RouteInfo(new IpPrefix("::/1")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+    }
 }
diff --git a/tests/permission/Android.mk b/tests/permission/Android.mk
index 54688c8..fb84bcf 100644
--- a/tests/permission/Android.mk
+++ b/tests/permission/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
 LOCAL_STATIC_JAVA_LIBRARIES := junit legacy-android-test
 LOCAL_PACKAGE_NAME := FrameworkPermissionTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
index 16fe535..4ec1b0f 100644
--- a/tests/testables/tests/Android.mk
+++ b/tests/testables/tests/Android.mk
@@ -19,6 +19,7 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_PACKAGE_NAME := TestablesTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     $(call all-Iaidl-files-under, src)
diff --git a/tests/utils/DummyIME/Android.mk b/tests/utils/DummyIME/Android.mk
index c8d9f87..0f6c988 100644
--- a/tests/utils/DummyIME/Android.mk
+++ b/tests/utils/DummyIME/Android.mk
@@ -22,5 +22,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := DummyIME
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/AppOne/Android.mk b/tools/aapt2/integration-tests/AppOne/Android.mk
index 38bd5b5..7b30c4e 100644
--- a/tools/aapt2/integration-tests/AppOne/Android.mk
+++ b/tools/aapt2/integration-tests/AppOne/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_PACKAGE_NAME := AaptTestAppOne
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets $(LOCAL_PATH)/assets2
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
index 012728f..03cce35 100644
--- a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
+++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
@@ -19,5 +19,6 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_PACKAGE_NAME := AaptAutoVersionTest
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/StaticLibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
index 0b7129a..ec4f052 100644
--- a/tools/aapt2/integration-tests/StaticLibOne/Android.mk
+++ b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := AaptTestStaticLibOne
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
index 8b6eb41..40f91af 100644
--- a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
+++ b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := AaptTestStaticLibTwo
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
index 902fc65..8da1141 100644
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.mk
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
@@ -19,5 +19,6 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_PACKAGE_NAME := AaptSymlinkTest
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_PACKAGE)
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
index c98e40a..8804c8a 100644
--- a/wifi/tests/Android.mk
+++ b/wifi/tests/Android.mk
@@ -60,6 +60,7 @@
     android.test.runner \
 
 LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 include $(BUILD_PACKAGE)