Merge "Update OWNER files for connectivity"
diff --git a/Android.bp b/Android.bp
index 69fb459..0cd985d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -460,8 +460,8 @@
         "telecomm/java/com/android/internal/telecom/IInCallService.aidl",
         "telecomm/java/com/android/internal/telecom/ITelecomService.aidl",
         "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
-	"telephony/java/android/telephony/data/IDataService.aidl",
-	"telephony/java/android/telephony/data/IDataServiceCallback.aidl",
+        "telephony/java/android/telephony/data/IDataService.aidl",
+        "telephony/java/android/telephony/data/IDataServiceCallback.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsCallSessionListener.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsCapabilityCallback.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsConfig.aidl",
@@ -471,8 +471,7 @@
         "telephony/java/android/telephony/ims/internal/aidl/IImsRcsFeature.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsServiceController.aidl",
         "telephony/java/android/telephony/ims/internal/aidl/IImsServiceControllerListener.aidl",
-	"telephony/java/android/telephony/ims/internal/aidl/IImsSmsListener.aidl",
-        "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
+	"telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl",
         "telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
@@ -496,6 +495,7 @@
         "telephony/java/com/android/ims/internal/IImsService.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceController.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl",
+	"telephony/java/com/android/ims/internal/IImsSmsListener.aidl",
         "telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl",
         "telephony/java/com/android/ims/internal/IImsUt.aidl",
         "telephony/java/com/android/ims/internal/IImsUtListener.aidl",
diff --git a/api/current.txt b/api/current.txt
index a9bf7d1..e047bdc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27545,10 +27545,14 @@
     field public static final java.lang.String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
     field public static final java.lang.String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
     field public static final java.lang.String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
+    field public static final java.lang.String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED";
     field public static final java.lang.String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
+    field public static final java.lang.String EXTRA_AID = "android.nfc.extra.AID";
+    field public static final java.lang.String EXTRA_DATA = "android.nfc.extra.DATA";
     field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID";
     field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
     field public static final java.lang.String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
+    field public static final java.lang.String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
     field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG";
     field public static final int FLAG_READER_NFC_A = 1; // 0x1
     field public static final int FLAG_READER_NFC_B = 2; // 0x2
@@ -40394,10 +40398,10 @@
     method public static android.telephony.MbmsDownloadSession create(android.content.Context, android.telephony.mbms.MbmsDownloadSessionCallback, android.os.Handler);
     method public static android.telephony.MbmsDownloadSession create(android.content.Context, android.telephony.mbms.MbmsDownloadSessionCallback, int, android.os.Handler);
     method public int download(android.telephony.mbms.DownloadRequest);
-    method public int getDownloadStatus(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo);
     method public java.io.File getTempFileRootDirectory();
     method public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads();
     method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback, android.os.Handler);
+    method public void requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo);
     method public void requestUpdateFileServices(java.util.List<java.lang.String>);
     method public void resetDownloadKnowledge(android.telephony.mbms.DownloadRequest);
     method public void setTempFileRootDirectory(java.io.File);
@@ -41280,6 +41284,7 @@
   public static class MbmsErrors.DownloadErrors {
     field public static final int ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT = 401; // 0x191
     field public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402; // 0x192
+    field public static final int ERROR_UNKNOWN_FILE_INFO = 403; // 0x193
   }
 
   public static class MbmsErrors.GeneralErrors {
@@ -44088,6 +44093,7 @@
     field public static final int DENSITY_360 = 360; // 0x168
     field public static final int DENSITY_400 = 400; // 0x190
     field public static final int DENSITY_420 = 420; // 0x1a4
+    field public static final int DENSITY_440 = 440; // 0x1b8
     field public static final int DENSITY_560 = 560; // 0x230
     field public static final int DENSITY_DEFAULT = 160; // 0xa0
     field public static final int DENSITY_DEVICE_STABLE;
diff --git a/api/system-current.txt b/api/system-current.txt
index 041c213..0371f91 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -28,6 +28,7 @@
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
     field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
     field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
+    field public static final java.lang.String BIND_TELEPHONY_DATA_SERVICE = "android.permission.BIND_TELEPHONY_DATA_SERVICE";
     field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
     field public static final java.lang.String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
     field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
@@ -4044,6 +4045,24 @@
   public final class SmsManager {
     method public void sendMultipartTextMessageWithoutPersisting(java.lang.String, java.lang.String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
     method public void sendTextMessageWithoutPersisting(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
+    field public static final int RESULT_CANCELLED = 23; // 0x17
+    field public static final int RESULT_ENCODING_ERROR = 18; // 0x12
+    field public static final int RESULT_ERROR_FDN_CHECK_FAILURE = 6; // 0x6
+    field public static final int RESULT_ERROR_NONE = 0; // 0x0
+    field public static final int RESULT_INTERNAL_ERROR = 21; // 0x15
+    field public static final int RESULT_INVALID_ARGUMENTS = 11; // 0xb
+    field public static final int RESULT_INVALID_SMSC_ADDRESS = 19; // 0x13
+    field public static final int RESULT_INVALID_SMS_FORMAT = 14; // 0xe
+    field public static final int RESULT_INVALID_STATE = 12; // 0xc
+    field public static final int RESULT_MODEM_ERROR = 16; // 0x10
+    field public static final int RESULT_NETWORK_ERROR = 17; // 0x11
+    field public static final int RESULT_NETWORK_REJECT = 10; // 0xa
+    field public static final int RESULT_NO_MEMORY = 13; // 0xd
+    field public static final int RESULT_NO_RESOURCES = 22; // 0x16
+    field public static final int RESULT_OPERATION_NOT_ALLOWED = 20; // 0x14
+    field public static final int RESULT_RADIO_NOT_AVAILABLE = 9; // 0x9
+    field public static final int RESULT_REQUEST_NOT_SUPPORTED = 24; // 0x18
+    field public static final int RESULT_SYSTEM_ERROR = 15; // 0xf
   }
 
   public class SubscriptionManager {
@@ -4287,6 +4306,30 @@
 
 }
 
+package android.telephony.ims.internal.stub {
+
+  public class SmsImplBase {
+    ctor public SmsImplBase();
+    method public void acknowledgeSms(int, int, int);
+    method public void acknowledgeSmsReport(int, int, int);
+    method public java.lang.String getSmsFormat();
+    method public void onReady();
+    method public final void onSendSmsResult(int, int, int, int) throws java.lang.RuntimeException;
+    method public final void onSmsReceived(int, java.lang.String, byte[]) throws java.lang.RuntimeException;
+    method public final void onSmsStatusReportReceived(int, int, java.lang.String, byte[]) throws java.lang.RuntimeException;
+    method public void sendSms(int, int, java.lang.String, java.lang.String, boolean, byte[]);
+    field public static final int DELIVER_STATUS_ERROR = 2; // 0x2
+    field public static final int DELIVER_STATUS_OK = 1; // 0x1
+    field public static final int SEND_STATUS_ERROR = 2; // 0x2
+    field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
+    field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
+    field public static final int SEND_STATUS_OK = 1; // 0x1
+    field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2
+    field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
+  }
+
+}
+
 package android.telephony.mbms {
 
   public final class DownloadRequest implements android.os.Parcelable {
@@ -4337,11 +4380,11 @@
     method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
     method public void dispose(int) throws android.os.RemoteException;
     method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
-    method public int getDownloadStatus(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
     method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
     method public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
     method public void onAppCallbackDied(int, int);
     method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException;
+    method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
     method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
     method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
     method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
diff --git a/api/test-current.txt b/api/test-current.txt
index 75ff437..93de1c2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -495,11 +495,11 @@
     method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
     method public void dispose(int) throws android.os.RemoteException;
     method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
-    method public int getDownloadStatus(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
     method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
     method public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
     method public void onAppCallbackDied(int, int);
     method public int registerStateCallback(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStateCallback) throws android.os.RemoteException;
+    method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
     method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
     method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
     method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index a2af342..3df4336 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -1507,6 +1507,38 @@
     }
 
     /**
+     * Request an LE connection parameter update.
+     *
+     * <p>This function will send an LE connection parameters update request to the remote device.
+     *
+     * @return true, if the request is send to the Bluetooth stack.
+     * @hide
+     */
+    public boolean requestLeConnectionUpdate(int minConnectionInterval,
+                                                 int maxConnectionInterval,
+                                                 int slaveLatency, int supervisionTimeout) {
+        if (DBG) {
+            Log.d(TAG, "requestLeConnectionUpdate() - min=(" + minConnectionInterval
+                       + ")" + (1.25 * minConnectionInterval)
+                       + "msec, max=(" + maxConnectionInterval + ")"
+                        + (1.25 * maxConnectionInterval) + "msec, latency=" + slaveLatency
+                       + ", timeout=" + supervisionTimeout + "msec");
+        }
+        if (mService == null || mClientIf == 0) return false;
+
+        try {
+            mService.leConnectionUpdate(mClientIf, mDevice.getAddress(),
+                                               minConnectionInterval, maxConnectionInterval,
+                                               slaveLatency, supervisionTimeout);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
      * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
      * with {@link BluetoothProfile#GATT} as argument
      *
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 31a3096..ecccda5 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -18,9 +18,6 @@
 
 import android.annotation.SystemService;
 import android.content.Context;
-import android.net.IEthernetManager;
-import android.net.IEthernetServiceListener;
-import android.net.IpConfiguration;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
@@ -45,18 +42,18 @@
             if (msg.what == MSG_AVAILABILITY_CHANGED) {
                 boolean isAvailable = (msg.arg1 == 1);
                 for (Listener listener : mListeners) {
-                    listener.onAvailabilityChanged(isAvailable);
+                    listener.onAvailabilityChanged((String) msg.obj, isAvailable);
                 }
             }
         }
     };
-    private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
+    private final ArrayList<Listener> mListeners = new ArrayList<>();
     private final IEthernetServiceListener.Stub mServiceListener =
             new IEthernetServiceListener.Stub() {
                 @Override
-                public void onAvailabilityChanged(boolean isAvailable) {
+                public void onAvailabilityChanged(String iface, boolean isAvailable) {
                     mHandler.obtainMessage(
-                            MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, null).sendToTarget();
+                            MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, iface).sendToTarget();
                 }
             };
 
@@ -66,9 +63,10 @@
     public interface Listener {
         /**
          * Called when Ethernet port's availability is changed.
-         * @param isAvailable {@code true} if one or more Ethernet port exists.
+         * @param iface Ethernet interface name
+         * @param isAvailable {@code true} if Ethernet port exists.
          */
-        public void onAvailabilityChanged(boolean isAvailable);
+        void onAvailabilityChanged(String iface, boolean isAvailable);
     }
 
     /**
@@ -86,9 +84,9 @@
      * Get Ethernet configuration.
      * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
      */
-    public IpConfiguration getConfiguration() {
+    public IpConfiguration getConfiguration(String iface) {
         try {
-            return mService.getConfiguration();
+            return mService.getConfiguration(iface);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -97,21 +95,29 @@
     /**
      * Set Ethernet configuration.
      */
-    public void setConfiguration(IpConfiguration config) {
+    public void setConfiguration(String iface, IpConfiguration config) {
         try {
-            mService.setConfiguration(config);
+            mService.setConfiguration(iface, config);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Indicates whether the system currently has one or more
-     * Ethernet interfaces.
+     * Indicates whether the system currently has one or more Ethernet interfaces.
      */
     public boolean isAvailable() {
+        return getAvailableInterfaces().length > 0;
+    }
+
+    /**
+     * Indicates whether the system has given interface.
+     *
+     * @param iface Ethernet interface name
+     */
+    public boolean isAvailable(String iface) {
         try {
-            return mService.isAvailable();
+            return mService.isAvailable(iface);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -137,6 +143,17 @@
     }
 
     /**
+     * Returns an array of available Ethernet interface names.
+     */
+    public String[] getAvailableInterfaces() {
+        try {
+            return mService.getAvailableInterfaces();
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
      * Removes a listener.
      * @param listener A {@link Listener} to remove.
      * @throws IllegalArgumentException If the listener is null.
diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl
index 7a92eb9..94960b5 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/core/java/android/net/IEthernetManager.aidl
@@ -26,9 +26,10 @@
 /** {@hide} */
 interface IEthernetManager
 {
-    IpConfiguration getConfiguration();
-    void setConfiguration(in IpConfiguration config);
-    boolean isAvailable();
+    String[] getAvailableInterfaces();
+    IpConfiguration getConfiguration(String iface);
+    void setConfiguration(String iface, in IpConfiguration config);
+    boolean isAvailable(String iface);
     void addListener(in IEthernetServiceListener listener);
     void removeListener(in IEthernetServiceListener listener);
 }
diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/core/java/android/net/IEthernetServiceListener.aidl
index 356690e8..782fa19 100644
--- a/core/java/android/net/IEthernetServiceListener.aidl
+++ b/core/java/android/net/IEthernetServiceListener.aidl
@@ -19,5 +19,5 @@
 /** @hide */
 oneway interface IEthernetServiceListener
 {
-    void onAvailabilityChanged(boolean isAvailable);
+    void onAvailabilityChanged(String iface, boolean isAvailable);
 }
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 196a3bc..fa4624e 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -433,6 +433,10 @@
         }
     }
 
+    private static long addIfSupported(long stat) {
+        return (stat == UNSUPPORTED) ? 0 : stat;
+    }
+
     /**
      * Return number of packets transmitted across mobile networks since device
      * boot. Counts packets across all mobile network interfaces, and always
@@ -445,7 +449,7 @@
     public static long getMobileTxPackets() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
-            total += getTxPackets(iface);
+            total += addIfSupported(getTxPackets(iface));
         }
         return total;
     }
@@ -462,7 +466,7 @@
     public static long getMobileRxPackets() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
-            total += getRxPackets(iface);
+            total += addIfSupported(getRxPackets(iface));
         }
         return total;
     }
@@ -479,7 +483,7 @@
     public static long getMobileTxBytes() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
-            total += getTxBytes(iface);
+            total += addIfSupported(getTxBytes(iface));
         }
         return total;
     }
@@ -496,7 +500,7 @@
     public static long getMobileRxBytes() {
         long total = 0;
         for (String iface : getMobileIfaces()) {
-            total += getRxBytes(iface);
+            total += addIfSupported(getRxBytes(iface));
         }
         return total;
     }
@@ -511,9 +515,7 @@
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
-            if (stat != UNSUPPORTED) {
-                total += stat;
-            }
+            total += addIfSupported(stat);
         }
         return total;
     }
@@ -528,9 +530,7 @@
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
-            if (stat != UNSUPPORTED) {
-                total += stat;
-            }
+            total += addIfSupported(stat);
         }
         return total;
     }
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index debef63..b02d48d 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -147,6 +147,19 @@
     public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
 
     /**
+     * Broadcast Action: Intent to notify an application that an transaction event has occurred
+     * on the Secure Element.
+     *
+     * <p>This intent will only be sent if the application has requested permission for
+     * {@link android.Manifest.permission#NFC_TRANSACTION_EVENT} and if the application has the
+     * necessary access to Secure Element which witnessed the particular event.
+     */
+    @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT)
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_TRANSACTION_DETECTED =
+            "android.nfc.action.TRANSACTION_DETECTED";
+
+    /**
      * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED
      * @hide
      */
@@ -197,6 +210,23 @@
      */
     public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
 
+    /**
+     * Mandatory byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED}
+     */
+    public static final String EXTRA_AID = "android.nfc.extra.AID";
+
+    /**
+     * Optional byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED}
+     */
+    public static final String EXTRA_DATA = "android.nfc.extra.DATA";
+
+    /**
+     * Mandatory String extra field in {@link #ACTION_TRANSACTION_DETECTED}
+     * Indicates the Secure Element on which the transaction occurred.
+     * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc.
+     */
+    public static final String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
+
     public static final int STATE_OFF = 1;
     public static final int STATE_TURNING_ON = 2;
     public static final int STATE_ON = 3;
diff --git a/core/java/android/se/omapi/Channel.java b/core/java/android/se/omapi/Channel.java
index f0b9fa2d..65ce67f 100644
--- a/core/java/android/se/omapi/Channel.java
+++ b/core/java/android/se/omapi/Channel.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 
 import java.io.IOException;
@@ -168,8 +169,10 @@
                     throw new IOException("Error in communicating with Secure Element");
                 }
                 return response;
-            } catch (RemoteException e) {
+            } catch (ServiceSpecificException e) {
                 throw new IOException(e.getMessage());
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e.getMessage());
             }
         }
     }
@@ -244,8 +247,10 @@
             synchronized (mLock) {
                 return mChannel.selectNext();
             }
-        } catch (RemoteException e) {
+        } catch (ServiceSpecificException e) {
             throw new IOException(e.getMessage());
+        } catch (RemoteException e) {
+            throw new IllegalStateException(e.getMessage());
         }
     }
 }
diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java
index 9f15739..3dec976 100644
--- a/core/java/android/se/omapi/Reader.java
+++ b/core/java/android/se/omapi/Reader.java
@@ -24,6 +24,7 @@
 
 import android.annotation.NonNull;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 
 import java.io.IOException;
@@ -45,8 +46,7 @@
     private final Object mLock = new Object();
 
 
-    Reader(SEService service, String name, ISecureElementReader reader) throws
-            IOException {
+    Reader(SEService service, String name, ISecureElementReader reader) {
         if (reader == null || service == null || name == null) {
             throw new IllegalArgumentException("Parameters cannot be null");
         }
@@ -96,8 +96,10 @@
             ISecureElementSession session;
             try {
                 session = mReader.openSession();
-            } catch (RemoteException e) {
+            } catch (ServiceSpecificException e) {
                 throw new IOException(e.getMessage());
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e.getMessage());
             }
             if (session == null) {
                 throw new IOException("service session is null.");
diff --git a/core/java/android/se/omapi/SEService.java b/core/java/android/se/omapi/SEService.java
index 1e37277d..b8937e6 100644
--- a/core/java/android/se/omapi/SEService.java
+++ b/core/java/android/se/omapi/SEService.java
@@ -42,6 +42,23 @@
  */
 public class SEService {
 
+    /**
+     * Error code used with ServiceSpecificException.
+     * Thrown if there was an error communicating with the Secure Element.
+     *
+     * @hide
+     */
+    public static final int IO_ERROR = 1;
+
+    /**
+     * Error code used with ServiceSpecificException.
+     * Thrown if AID cannot be selected or is not available when opening
+     * a logical channel.
+     *
+     * @hide
+     */
+    public static final int NO_SUCH_ELEMENT_ERROR = 2;
+
     private static final String TAG = "OMAPI.SEService";
 
     private final Object mLock = new Object();
diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java
index bb2a032..19a018e 100644
--- a/core/java/android/se/omapi/Session.java
+++ b/core/java/android/se/omapi/Session.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
 import android.util.Log;
 
 import java.io.IOException;
@@ -207,8 +208,16 @@
                     return null;
                 }
                 return new Channel(mService, this, channel);
+            } catch (ServiceSpecificException e) {
+                if (e.errorCode == SEService.IO_ERROR) {
+                    throw new IOException(e.getMessage());
+                } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) {
+                    throw new NoSuchElementException(e.getMessage());
+                } else {
+                    throw new IllegalStateException(e.getMessage());
+                }
             } catch (RemoteException e) {
-                throw new IOException(e.getMessage());
+                throw new IllegalStateException(e.getMessage());
             }
         }
     }
@@ -311,8 +320,16 @@
                     return null;
                 }
                 return new Channel(mService, this, channel);
+            } catch (ServiceSpecificException e) {
+                if (e.errorCode == SEService.IO_ERROR) {
+                    throw new IOException(e.getMessage());
+                } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) {
+                    throw new NoSuchElementException(e.getMessage());
+                } else {
+                    throw new IllegalStateException(e.getMessage());
+                }
             } catch (RemoteException e) {
-                throw new IOException(e.getMessage());
+                throw new IllegalStateException(e.getMessage());
             }
         }
     }
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index b7099b6..13de172 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -120,6 +120,14 @@
     public static final int DENSITY_420 = 420;
 
     /**
+     * Intermediate density for screens that sit somewhere between
+     * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
+     * This is not a density that applications should target, instead relying
+     * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
+     */
+    public static final int DENSITY_440 = 440;
+
+    /**
      * Standard quantized DPI for extra-extra-high-density screens.
      */
     public static final int DENSITY_XXHIGH = 480;
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index d0f5ba7..03e5667 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -57,6 +57,8 @@
     public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
     /** Do not enfore hidden API access restrictions. */
     public static final int DISABLE_HIDDEN_API_CHECKS = 1 << 11;
+    /** Force generation of native debugging information for backtraces. */
+    public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12;
 
     /** No external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_NONE = 0;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 43d7df3..ada9bd7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1756,6 +1756,15 @@
     <permission android:name="android.permission.BIND_IMS_SERVICE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Must be required by a telephony data service to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to manage embedded subscriptions (those on a eUICC) through
          EuiccManager APIs.
          <p>Protection level: signature|privileged|development
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5cc727d..a8a5700 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -360,6 +360,23 @@
     <!-- Regex of wired ethernet ifaces -->
     <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
 
+
+
+    <!-- Configuration of Ethernet interfaces in the following format:
+         <interface name|mac address>;[Network Capabilities];[IP config]
+         Where
+               [Network Capabilities] Optional. A comma seprated list of network capabilities.
+                   Values must be from NetworkCapabilities#NET_CAPABILITIES_* constants.
+               [IP config] Optional. If empty or not specified - DHCP will be used, otherwise
+                    static IP address with the mask.
+         -->
+    <string-array translatable="false" name="config_ethernet_interfaces">
+        <!--
+        <item>eth1;12,13,14,15;192.168.0.10/24</item>
+        <item>eth2;;192.168.0.11/24</item>
+        -->
+    </string-array>
+
     <!-- If the mobile hotspot feature requires provisioning, a package name and class name
         can be provided to launch a supported application that provisions the devices.
 
@@ -2468,6 +2485,14 @@
     <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
     <bool name="config_dynamic_bind_ims">false</bool>
 
+    <!-- Cellular data service package name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wwan_data_service_package" translatable="false">com.android.phone</string>
+
+    <!-- IWLAN data service package name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_wlan_data_service_package" translatable="false"></string>
+
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
     <!-- Home (non-roaming) values for CDMA roaming indicator.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index fb755a1..08be23d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -264,6 +264,8 @@
   <java-symbol type="bool" name="config_mms_content_disposition_support" />
   <java-symbol type="string" name="config_ims_package" />
   <java-symbol type="bool" name="config_dynamic_bind_ims" />
+  <java-symbol type="string" name="config_wwan_data_service_package" />
+  <java-symbol type="string" name="config_wlan_data_service_package" />
   <java-symbol type="bool" name="config_networkSamplingWakesDevice" />
   <java-symbol type="bool" name="config_showMenuShortcutsWhenKeyboardPresent" />
   <java-symbol type="bool" name="config_sip_wifi_only" />
@@ -634,6 +636,7 @@
   <java-symbol type="string" name="chooseActivity" />
   <java-symbol type="string" name="config_default_dns_server" />
   <java-symbol type="string" name="config_ethernet_iface_regex" />
+  <java-symbol type="array" name="config_ethernet_interfaces" />
   <java-symbol type="string" name="config_forceVoiceInteractionServicePackage" />
   <java-symbol type="string" name="config_mms_user_agent" />
   <java-symbol type="string" name="config_mms_user_agent_profile_url" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 6a3a973..5b6577f 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -134,6 +134,7 @@
         <permission name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"/>
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
         <permission name="android.permission.BIND_IMS_SERVICE"/>
+        <permission name="android.permission.BIND_TELEPHONY_DATA_SERVICE"/>
         <permission name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"/>
         <permission name="android.permission.CALL_PRIVILEGED"/>
         <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
@@ -146,6 +147,7 @@
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
         <permission name="android.permission.MANAGE_USERS"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
+        <permission name="android.permission.PACKAGE_USAGE_STATS"/>
         <permission name="android.permission.PERFORM_CDMA_PROVISIONING"/>
         <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
@@ -212,6 +214,7 @@
         <permission name="android.permission.CALL_PRIVILEGED"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.MODIFY_AUDIO_ROUTING" />
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.STOP_APP_SWITCHES"/>
         <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index b08b26d..e467903 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -49,7 +49,6 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.qs.tiles.DndTile;
@@ -340,11 +339,15 @@
 
     private boolean shouldShowUI(int flags) {
         updateStatusBar();
-        return mStatusBar != null
-                && mStatusBar.getWakefulnessState() != WakefulnessLifecycle.WAKEFULNESS_ASLEEP
-                && mStatusBar.getWakefulnessState() != WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP
+        // if status bar isn't null, check if phone is in AOD, else check flags
+        // since we could be using a different status bar
+        return mStatusBar != null ?
+                mStatusBar.getWakefulnessState() != WakefulnessLifecycle.WAKEFULNESS_ASLEEP
+                && mStatusBar.getWakefulnessState() !=
+                        WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP
                 && mStatusBar.isDeviceInteractive()
-                && (flags & AudioManager.FLAG_SHOW_UI) != 0;
+                && (flags & AudioManager.FLAG_SHOW_UI) != 0
+                : (flags & AudioManager.FLAG_SHOW_UI) != 0;
     }
 
     boolean onVolumeChangedW(int stream, int flags) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 6747be3..6743484 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -35,6 +35,7 @@
 import android.telephony.CellInfo;
 import android.telephony.CellLocation;
 import android.telephony.DisconnectCause;
+import android.telephony.LocationAccessPolicy;
 import android.telephony.PhoneStateListener;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
@@ -93,7 +94,8 @@
         IPhoneStateListener callback;
         IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
 
-        int callerUserId;
+        int callerUid;
+        int callerPid;
 
         int events;
 
@@ -117,7 +119,7 @@
                     + " callback=" + callback
                     + " onSubscriptionsChangedListenererCallback="
                                             + onSubscriptionsChangedListenerCallback
-                    + " callerUserId=" + callerUserId + " subId=" + subId + " phoneId=" + phoneId
+                    + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
                     + " events=" + Integer.toHexString(events)
                     + " canReadPhoneState=" + canReadPhoneState + "}";
         }
@@ -356,6 +358,8 @@
     public void addOnSubscriptionsChangedListener(String callingPackage,
             IOnSubscriptionsChangedListener callback) {
         int callerUserId = UserHandle.getCallingUserId();
+        mContext.getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (VDBG) {
             log("listen oscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId()
                 + " callerUserId="  + callerUserId + " callback=" + callback
@@ -399,7 +403,8 @@
 
             r.onSubscriptionsChangedListenerCallback = callback;
             r.callingPackage = callingPackage;
-            r.callerUserId = callerUserId;
+            r.callerUid = Binder.getCallingUid();
+            r.callerPid = Binder.getCallingPid();
             r.events = 0;
             r.canReadPhoneState = true; // permission has been enforced above
             if (DBG) {
@@ -470,6 +475,8 @@
     private void listen(String callingPackage, IPhoneStateListener callback, int events,
             boolean notifyNow, int subId) {
         int callerUserId = UserHandle.getCallingUserId();
+        mContext.getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (VDBG) {
             log("listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
                 + " notifyNow=" + notifyNow + " subId=" + subId + " myUserId="
@@ -514,7 +521,8 @@
 
                 r.callback = callback;
                 r.callingPackage = callingPackage;
-                r.callerUserId = callerUserId;
+                r.callerUid = Binder.getCallingUid();
+                r.callerPid = Binder.getCallingPid();
                 boolean isPhoneStateEvent = (events & (CHECK_PHONE_STATE_PERMISSION_MASK
                         | ENFORCE_PHONE_STATE_PERMISSION_MASK)) != 0;
                 r.canReadPhoneState = isPhoneStateEvent && canReadPhoneState(callingPackage);
@@ -572,8 +580,10 @@
                         try {
                             if (DBG_LOC) log("listen: mCellLocation = "
                                     + mCellLocation[phoneId]);
-                            r.callback.onCellLocationChanged(
-                                    new Bundle(mCellLocation[phoneId]));
+                            if (checkLocationAccess(r)) {
+                                r.callback.onCellLocationChanged(
+                                        new Bundle(mCellLocation[phoneId]));
+                            }
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -619,7 +629,9 @@
                         try {
                             if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
                                     + mCellInfo.get(phoneId));
-                            r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
+                            if (checkLocationAccess(r)) {
+                                r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
+                            }
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -979,7 +991,8 @@
                 mCellInfo.set(phoneId, cellInfo);
                 for (Record r : mRecords) {
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                            idMatch(r.subId, subId, phoneId) &&
+                            checkLocationAccess(r)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
@@ -1262,7 +1275,8 @@
                 mCellLocation[phoneId] = cellLocation;
                 for (Record r : mRecords) {
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                            idMatch(r.subId, subId, phoneId) &&
+                            checkLocationAccess(r)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellLocation: cellLocation=" + cellLocation
@@ -1706,10 +1720,11 @@
         boolean valid = false;
         try {
             foregroundUser = ActivityManager.getCurrentUser();
-            valid = r.callerUserId ==  foregroundUser && r.matchPhoneStateListenerEvent(events);
+            valid = UserHandle.getUserId(r.callerUid) == foregroundUser
+                    && r.matchPhoneStateListenerEvent(events);
             if (DBG | DBG_LOC) {
                 log("validateEventsAndUserLocked: valid=" + valid
-                        + " r.callerUserId=" + r.callerUserId + " foregroundUser=" + foregroundUser
+                        + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
                         + " r.events=" + r.events + " events=" + events);
             }
         } finally {
@@ -1741,6 +1756,16 @@
         }
     }
 
+    private boolean checkLocationAccess(Record r) {
+        long token = Binder.clearCallingIdentity();
+        try {
+            return LocationAccessPolicy.canAccessCellLocation(mContext,
+                    r.callingPackage, r.callerUid, r.callerPid);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private void checkPossibleMissNotify(Record r, int phoneId) {
         int events = r.events;
 
@@ -1788,7 +1813,9 @@
                     log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
                             + mCellInfo.get(phoneId));
                 }
-                r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
+                if (checkLocationAccess(r)) {
+                    r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
+                }
             } catch (RemoteException ex) {
                 mRemoveList.add(r.binder);
             }
@@ -1836,7 +1863,9 @@
             try {
                 if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
                         + mCellLocation[phoneId]);
-                r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
+                if (checkLocationAccess(r)) {
+                    r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
+                }
             } catch (RemoteException ex) {
                 mRemoveList.add(r.binder);
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e944326..f0d6757a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3863,9 +3863,13 @@
                 runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
             }
             String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
-            if ("true".equals(genDebugInfoProperty)) {
+            if ("1".equals(genDebugInfoProperty) || "true".equals(genDebugInfoProperty)) {
                 runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
             }
+            String genMiniDebugInfoProperty = SystemProperties.get("dalvik.vm.minidebuginfo");
+            if ("1".equals(genMiniDebugInfoProperty) || "true".equals(genMiniDebugInfoProperty)) {
+                runtimeFlags |= Zygote.DEBUG_GENERATE_MINI_DEBUG_INFO;
+            }
             if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
                 runtimeFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
             }
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index 4d56468..e3e02e3 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -24,11 +24,11 @@
 import android.net.ProxyInfo;
 import android.net.RouteInfo;
 import android.net.StaticIpConfiguration;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.net.DelayedDiskWrite;
 
 import java.io.BufferedInputStream;
 import java.io.DataInputStream;
@@ -38,8 +38,8 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.InetAddress;
 import java.net.Inet4Address;
+import java.net.InetAddress;
 
 public class IpConfigStore {
     private static final String TAG = "IpConfigStore";
@@ -60,7 +60,7 @@
     protected static final String EXCLUSION_LIST_KEY = "exclusionList";
     protected static final String EOS = "eos";
 
-    protected static final int IPCONFIG_FILE_VERSION = 2;
+    protected static final int IPCONFIG_FILE_VERSION = 3;
 
     public IpConfigStore(DelayedDiskWrite writer) {
         mWriter = writer;
@@ -70,9 +70,14 @@
         this(new DelayedDiskWrite());
     }
 
+    private static boolean writeConfig(DataOutputStream out, String configKey,
+            IpConfiguration config) throws IOException {
+        return writeConfig(out, configKey, config, IPCONFIG_FILE_VERSION);
+    }
+
     @VisibleForTesting
-    public static boolean writeConfig(DataOutputStream out, int configKey,
-                                IpConfiguration config) throws IOException {
+    public static boolean writeConfig(DataOutputStream out, String configKey,
+                                IpConfiguration config, int version) throws IOException {
         boolean written = false;
 
         try {
@@ -153,7 +158,11 @@
 
             if (written) {
                 out.writeUTF(ID_KEY);
-                out.writeInt(configKey);
+                if (version < 3) {
+                    out.writeInt(Integer.valueOf(configKey));
+                } else {
+                    out.writeUTF(configKey);
+                }
             }
         } catch (NullPointerException e) {
             loge("Failure in writing " + config + e);
@@ -163,18 +172,47 @@
         return written;
     }
 
-    public void writeIpAndProxyConfigurations(String filePath,
+    /**
+     * @Deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead.
+     * New method uses string as network identifier which could be interface name or MAC address or
+     * other token.
+     */
+    @Deprecated
+    public void writeIpAndProxyConfigurationsToFile(String filePath,
                                               final SparseArray<IpConfiguration> networks) {
-        mWriter.write(filePath, new DelayedDiskWrite.Writer() {
-            public void onWriteCalled(DataOutputStream out) throws IOException{
-                out.writeInt(IPCONFIG_FILE_VERSION);
-                for(int i = 0; i < networks.size(); i++) {
-                    writeConfig(out, networks.keyAt(i), networks.valueAt(i));
-                }
+        mWriter.write(filePath, out -> {
+            out.writeInt(IPCONFIG_FILE_VERSION);
+            for(int i = 0; i < networks.size(); i++) {
+                writeConfig(out, String.valueOf(networks.keyAt(i)), networks.valueAt(i));
             }
         });
     }
 
+    public void writeIpConfigurations(String filePath,
+                                      ArrayMap<String, IpConfiguration> networks) {
+        mWriter.write(filePath, out -> {
+            out.writeInt(IPCONFIG_FILE_VERSION);
+            for(int i = 0; i < networks.size(); i++) {
+                writeConfig(out, networks.keyAt(i), networks.valueAt(i));
+            }
+        });
+    }
+
+    public static ArrayMap<String, IpConfiguration> readIpConfigurations(String filePath) {
+        BufferedInputStream bufferedInputStream;
+        try {
+            bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
+        } catch (FileNotFoundException e) {
+            // Return an empty array here because callers expect an empty array when the file is
+            // not present.
+            loge("Error opening configuration file: " + e);
+            return new ArrayMap<>(0);
+        }
+        return readIpConfigurations(bufferedInputStream);
+    }
+
+    /** @Deprecated use {@link #readIpConfigurations(String)} */
+    @Deprecated
     public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
         BufferedInputStream bufferedInputStream;
         try {
@@ -188,21 +226,40 @@
         return readIpAndProxyConfigurations(bufferedInputStream);
     }
 
+    /** @Deprecated use {@link #readIpConfigurations(InputStream)} */
+    @Deprecated
     public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(
             InputStream inputStream) {
-        SparseArray<IpConfiguration> networks = new SparseArray<IpConfiguration>();
+        ArrayMap<String, IpConfiguration> networks = readIpConfigurations(inputStream);
+        if (networks == null) {
+            return null;
+        }
+
+        SparseArray<IpConfiguration> networksById = new SparseArray<>();
+        for (int i = 0; i < networks.size(); i++) {
+            int id = Integer.valueOf(networks.keyAt(i));
+            networksById.put(id, networks.valueAt(i));
+        }
+
+        return networksById;
+    }
+
+    /** Returns a map of network identity token and {@link IpConfiguration}. */
+    public static ArrayMap<String, IpConfiguration> readIpConfigurations(
+            InputStream inputStream) {
+        ArrayMap<String, IpConfiguration> networks = new ArrayMap<>();
         DataInputStream in = null;
         try {
             in = new DataInputStream(inputStream);
 
             int version = in.readInt();
-            if (version != 2 && version != 1) {
+            if (version != 3 && version != 2 && version != 1) {
                 loge("Bad version on IP configuration file, ignore read");
                 return null;
             }
 
             while (true) {
-                int id = -1;
+                String uniqueToken = null;
                 // Default is DHCP with no proxy
                 IpAssignment ipAssignment = IpAssignment.DHCP;
                 ProxySettings proxySettings = ProxySettings.NONE;
@@ -217,7 +274,12 @@
                     key = in.readUTF();
                     try {
                         if (key.equals(ID_KEY)) {
-                            id = in.readInt();
+                            if (version < 3) {
+                                int id = in.readInt();
+                                uniqueToken = String.valueOf(id);
+                            } else {
+                                uniqueToken = in.readUTF();
+                            }
                         } else if (key.equals(IP_ASSIGNMENT_KEY)) {
                             ipAssignment = IpAssignment.valueOf(in.readUTF());
                         } else if (key.equals(LINK_ADDRESS_KEY)) {
@@ -280,9 +342,9 @@
                     }
                 } while (true);
 
-                if (id != -1) {
+                if (uniqueToken != null) {
                     IpConfiguration config = new IpConfiguration();
-                    networks.put(id, config);
+                    networks.put(uniqueToken, config);
 
                     switch (ipAssignment) {
                         case STATIC:
diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
new file mode 100644
index 0000000..9f4b754
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.server.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.net.ProxyInfo;
+import android.net.StaticIpConfiguration;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArrayMap;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit tests for {@link IpConfigStore}
+ */
+@RunWith(AndroidJUnit4.class)
+public class IpConfigStoreTest {
+
+    @Test
+    public void backwardCompatibility2to3() throws IOException {
+        final int KEY_CONFIG = 17;
+        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+        DataOutputStream outputStream = new DataOutputStream(byteStream);
+
+        IpConfiguration expectedConfig = new IpConfiguration(IpAssignment.DHCP,
+                ProxySettings.NONE, null, null);
+
+        // Emulate writing to old format.
+        writeDhcpConfigV2(outputStream, KEY_CONFIG, expectedConfig);
+
+        InputStream in = new ByteArrayInputStream(byteStream.toByteArray());
+        ArrayMap<String, IpConfiguration> configurations = IpConfigStore.readIpConfigurations(in);
+
+        assertNotNull(configurations);
+        assertEquals(1, configurations.size());
+        IpConfiguration actualConfig = configurations.get(String.valueOf(KEY_CONFIG));
+        assertNotNull(actualConfig);
+        assertEquals(expectedConfig, actualConfig);
+    }
+
+    @Test
+    public void staticIpMultiNetworks() throws Exception {
+        final String IFACE_1 = "eth0";
+        final String IFACE_2 = "eth1";
+        final String IP_ADDR_1 = "192.168.1.10/24";
+        final String IP_ADDR_2 = "192.168.1.20/24";
+        final String DNS_IP_ADDR_1 = "1.2.3.4";
+        final String DNS_IP_ADDR_2 = "5.6.7.8";
+
+        StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
+        staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1);
+        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1));
+        staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2));
+
+        ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2");
+
+        IpConfiguration expectedConfig1 = new IpConfiguration(IpAssignment.STATIC,
+                ProxySettings.STATIC, staticIpConfiguration, proxyInfo);
+        IpConfiguration expectedConfig2 = new IpConfiguration(expectedConfig1);
+        expectedConfig2.getStaticIpConfiguration().ipAddress = new LinkAddress(IP_ADDR_2);
+
+        ArrayMap<String, IpConfiguration> expectedNetworks = new ArrayMap<>();
+        expectedNetworks.put(IFACE_1, expectedConfig1);
+        expectedNetworks.put(IFACE_2, expectedConfig2);
+
+        MockedDelayedDiskWrite writer = new MockedDelayedDiskWrite();
+        IpConfigStore store = new IpConfigStore(writer);
+        store.writeIpConfigurations("file/path/not/used/", expectedNetworks);
+
+        InputStream in = new ByteArrayInputStream(writer.byteStream.toByteArray());
+        ArrayMap<String, IpConfiguration> actualNetworks = IpConfigStore.readIpConfigurations(in);
+        assertNotNull(actualNetworks);
+        assertEquals(2, actualNetworks.size());
+        assertEquals(expectedNetworks.get(IFACE_1), actualNetworks.get(IFACE_1));
+        assertEquals(expectedNetworks.get(IFACE_2), actualNetworks.get(IFACE_2));
+    }
+
+    // This is simplified snapshot of code that was used to store values in V2 format (key as int).
+    private static void writeDhcpConfigV2(DataOutputStream out, int configKey,
+            IpConfiguration config) throws IOException {
+        out.writeInt(2);  // VERSION 2
+        switch (config.ipAssignment) {
+            case DHCP:
+                out.writeUTF("ipAssignment");
+                out.writeUTF(config.ipAssignment.toString());
+                break;
+            default:
+                fail("Not supported in test environment");
+        }
+
+        out.writeUTF("id");
+        out.writeInt(configKey);
+        out.writeUTF("eos");
+    }
+
+    /** Synchronously writes into given byte steam */
+    private static class MockedDelayedDiskWrite extends DelayedDiskWrite {
+        final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+
+        @Override
+        public void write(String filePath, Writer w) {
+            DataOutputStream outputStream = new DataOutputStream(byteStream);
+
+            try {
+                w.onWriteCalled(outputStream);
+            } catch (IOException e) {
+                fail();
+            }
+        }
+    }
+}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index fcfc593..95eb14a 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -134,6 +134,25 @@
             "android.telecom.extra.LOG_SELF_MANAGED_CALLS";
 
     /**
+     * Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
+     * indicates whether calls for a {@link PhoneAccount} should generate a "call recording tone"
+     * when the user is recording audio on the device.
+     * <p>
+     * The call recording tone is played over the telephony audio stream so that the remote party
+     * has an audible indication that it is possible their call is being recorded using a call
+     * recording app on the device.
+     * <p>
+     * This extra only has an effect for calls placed via Telephony (e.g.
+     * {@link #CAPABILITY_SIM_SUBSCRIPTION}).
+     * <p>
+     * The call recording tone is a 1400 hz tone which repeats every 15 seconds while recording is
+     * in progress.
+     * @hide
+     */
+    public static final String EXTRA_PLAY_CALL_RECORDING_TONE =
+            "android.telecom.extra.PLAY_CALL_RECORDING_TONE";
+
+    /**
      * Flag indicating that this {@code PhoneAccount} can act as a connection manager for
      * other connections. The {@link ConnectionService} associated with this {@code PhoneAccount}
      * will be allowed to manage phone calls including using its own proprietary phone-call
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 94ed218..dc3195c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -77,6 +77,14 @@
     public static final String
             KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
 
+   /**
+    * Boolean indicating if the "Call barring" item is visible in the Call Settings menu.
+    * true means visible. false means gone.
+    * @hide
+    */
+    public static final String KEY_CALL_BARRING_VISIBILITY_BOOL =
+            "call_barring_visibility_bool";
+
     /**
      * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED
      * events from the Sim.
@@ -146,6 +154,15 @@
     public static final String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
 
     /**
+     * Determines if the carrier requires that a tone be played to the remote party when an app is
+     * recording audio during a call (e.g. using a call recording app).
+     * <p>
+     * Note: This requires the Telephony config_supports_telephony_audio_device overlay to be true
+     * in order to work.
+     * @hide
+     */
+    public static final String KEY_PLAY_CALL_RECORDING_TONE_BOOL = "play_call_recording_tone_bool";
+    /**
      * Determines if the carrier requires converting the destination number before sending out an
      * SMS. Certain networks and numbering plans require different formats.
      */
@@ -491,6 +508,20 @@
     public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL
             = "carrier_volte_override_wfc_provisioning_bool";
 
+    /**
+     * Override the device's configuration for the cellular data service to use for this SIM card.
+     * @hide
+     */
+    public static final String KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING
+            = "carrier_data_service_wwan_package_override_string";
+
+    /**
+     * Override the device's configuration for the IWLAN data service to use for this SIM card.
+     * @hide
+     */
+    public static final String KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING
+            = "carrier_data_service_wlan_package_override_string";
+
     /** Flag specifying whether VoLTE TTY is supported. */
     public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL
             = "carrier_volte_tty_supported_bool";
@@ -1375,6 +1406,14 @@
     public static final String KEY_VIDEO_CALLS_CAN_BE_HD_AUDIO = "video_calls_can_be_hd_audio";
 
     /**
+     * When true, indicates that the HD audio icon in the in-call screen should be shown for
+     * GSM/CDMA calls.
+     * @hide
+     */
+    public static final String KEY_GSM_CDMA_CALLS_CAN_BE_HD_AUDIO =
+            "gsm_cdma_calls_can_be_hd_audio";
+
+    /**
      * Whether system apps are allowed to use fallback if carrier video call is not available.
      * Defaults to {@code true}.
      *
@@ -1771,6 +1810,7 @@
         sDefaults.putBoolean(KEY_ADDITIONAL_CALL_SETTING_BOOL, true);
         sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL, false);
         sDefaults.putBoolean(KEY_ALLOW_LOCAL_DTMF_TONES_BOOL, true);
+        sDefaults.putBoolean(KEY_PLAY_CALL_RECORDING_TONE_BOOL, false);
         sDefaults.putBoolean(KEY_APN_EXPAND_BOOL, true);
         sDefaults.putBoolean(KEY_AUTO_RETRY_ENABLED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_SETTINGS_ENABLE_BOOL, false);
@@ -1797,6 +1837,8 @@
         sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true);
+        sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
+        sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
         sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING, "");
         sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING, "");
         sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING, "");
@@ -1810,6 +1852,7 @@
         sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false);
 
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
+        sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false);
         sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false);
         sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false);
         sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
@@ -2009,6 +2052,7 @@
         sDefaults.putBoolean(KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_WIFI_CALLS_CAN_BE_HD_AUDIO, true);
         sDefaults.putBoolean(KEY_VIDEO_CALLS_CAN_BE_HD_AUDIO, true);
+        sDefaults.putBoolean(KEY_GSM_CDMA_CALLS_CAN_BE_HD_AUDIO, false);
         sDefaults.putBoolean(KEY_ALLOW_VIDEO_CALLING_FALLBACK_BOOL, true);
 
         sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index dfaaab9..ece1ee3 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -36,48 +36,14 @@
     private int mEvdoEcio;  // This value is the EVDO Ec/Io
     private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
 
-    /**
-     * Empty constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthCdma() {
         setDefaultValues();
     }
 
-    /**
-     * Constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
             int evdoSnr) {
-        initialize(cdmaDbm, cdmaEcio, evdoDbm, evdoEcio, evdoSnr);
-    }
-
-    /**
-     * Copy constructors
-     *
-     * @param s Source SignalStrength
-     *
-     * @hide
-     */
-    public CellSignalStrengthCdma(CellSignalStrengthCdma s) {
-        copyFrom(s);
-    }
-
-    /**
-     * Initialize all the values
-     *
-     * @param cdmaDbm
-     * @param cdmaEcio
-     * @param evdoDbm
-     * @param evdoEcio
-     * @param evdoSnr
-     *
-     * @hide
-     */
-    public void initialize(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr) {
         mCdmaDbm = cdmaDbm;
         mCdmaEcio = cdmaEcio;
         mEvdoDbm = evdoDbm;
@@ -85,9 +51,12 @@
         mEvdoSnr = evdoSnr;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
+    public CellSignalStrengthCdma(CellSignalStrengthCdma s) {
+        copyFrom(s);
+    }
+
+    /** @hide */
     protected void copyFrom(CellSignalStrengthCdma s) {
         mCdmaDbm = s.mCdmaDbm;
         mCdmaEcio = s.mCdmaEcio;
@@ -96,9 +65,7 @@
         mEvdoSnr = s.mEvdoSnr;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
     @Override
     public CellSignalStrengthCdma copy() {
         return new CellSignalStrengthCdma(this);
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index f68d2ca..8687cd1 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -34,80 +34,40 @@
     private static final int GSM_SIGNAL_STRENGTH_GOOD = 8;
     private static final int GSM_SIGNAL_STRENGTH_MODERATE = 5;
 
-    private int mSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
+    private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
     private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
-    private int mTimingAdvance;
+    private int mTimingAdvance; // range from 0-219 or Integer.MAX_VALUE if unknown
 
-    /**
-     * Empty constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthGsm() {
         setDefaultValues();
     }
 
-    /**
-     * Constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthGsm(int ss, int ber) {
-        initialize(ss, ber);
+        this(ss, ber, Integer.MAX_VALUE);
     }
 
-    /**
-     * Copy constructors
-     *
-     * @param s Source SignalStrength
-     *
-     * @hide
-     */
-    public CellSignalStrengthGsm(CellSignalStrengthGsm s) {
-        copyFrom(s);
-    }
-
-    /**
-     * Initialize all the values
-     *
-     * @param ss SignalStrength as ASU value
-     * @param ber is Bit Error Rate
-     *
-     * @hide
-     */
-    public void initialize(int ss, int ber) {
-        mSignalStrength = ss;
-        mBitErrorRate = ber;
-        mTimingAdvance = Integer.MAX_VALUE;
-    }
-
-    /**
-     * Initialize all the values
-     *
-     * @param ss SignalStrength as ASU value
-     * @param ber is Bit Error Rate
-     * @param ta timing advance
-     *
-     * @hide
-     */
-    public void initialize(int ss, int ber, int ta) {
+    /** @hide */
+    public CellSignalStrengthGsm(int ss, int ber, int ta) {
         mSignalStrength = ss;
         mBitErrorRate = ber;
         mTimingAdvance = ta;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
+    public CellSignalStrengthGsm(CellSignalStrengthGsm s) {
+        copyFrom(s);
+    }
+
+    /** @hide */
     protected void copyFrom(CellSignalStrengthGsm s) {
         mSignalStrength = s.mSignalStrength;
         mBitErrorRate = s.mBitErrorRate;
         mTimingAdvance = s.mTimingAdvance;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
     @Override
     public CellSignalStrengthGsm copy() {
         return new CellSignalStrengthGsm(this);
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 6ffc8b6..f009fb1 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -37,50 +37,15 @@
     private int mCqi;
     private int mTimingAdvance;
 
-    /**
-     * Empty constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthLte() {
         setDefaultValues();
     }
 
-    /**
-     * Constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthLte(int signalStrength, int rsrp, int rsrq, int rssnr, int cqi,
             int timingAdvance) {
-        initialize(signalStrength, rsrp, rsrq, rssnr, cqi, timingAdvance);
-    }
-
-    /**
-     * Copy constructors
-     *
-     * @param s Source SignalStrength
-     *
-     * @hide
-     */
-    public CellSignalStrengthLte(CellSignalStrengthLte s) {
-        copyFrom(s);
-    }
-
-    /**
-     * Initialize all the values
-     *
-     * @param lteSignalStrength
-     * @param rsrp
-     * @param rsrq
-     * @param rssnr
-     * @param cqi
-     *
-     * @hide
-     */
-    public void initialize(int lteSignalStrength, int rsrp, int rsrq, int rssnr, int cqi,
-            int timingAdvance) {
-        mSignalStrength = lteSignalStrength;
+        mSignalStrength = signalStrength;
         mRsrp = rsrp;
         mRsrq = rsrq;
         mRssnr = rssnr;
@@ -88,25 +53,12 @@
         mTimingAdvance = timingAdvance;
     }
 
-    /**
-     * Initialize from the SignalStrength structure.
-     *
-     * @param ss
-     *
-     * @hide
-     */
-    public void initialize(SignalStrength ss, int timingAdvance) {
-        mSignalStrength = ss.getLteSignalStrength();
-        mRsrp = ss.getLteRsrp();
-        mRsrq = ss.getLteRsrq();
-        mRssnr = ss.getLteRssnr();
-        mCqi = ss.getLteCqi();
-        mTimingAdvance = timingAdvance;
+    /** @hide */
+    public CellSignalStrengthLte(CellSignalStrengthLte s) {
+        copyFrom(s);
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
     protected void copyFrom(CellSignalStrengthLte s) {
         mSignalStrength = s.mSignalStrength;
         mRsrp = s.mRsrp;
@@ -116,9 +68,7 @@
         mTimingAdvance = s.mTimingAdvance;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
     @Override
     public CellSignalStrengthLte copy() {
         return new CellSignalStrengthLte(this);
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 2cd56b8..dd32a96 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -34,62 +34,32 @@
     private static final int WCDMA_SIGNAL_STRENGTH_GOOD = 8;
     private static final int WCDMA_SIGNAL_STRENGTH_MODERATE = 5;
 
-    private int mSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
-    private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+    private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
+    private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
 
-    /**
-     * Empty constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthWcdma() {
         setDefaultValues();
     }
 
-    /**
-     * Constructor
-     *
-     * @hide
-     */
+    /** @hide */
     public CellSignalStrengthWcdma(int ss, int ber) {
-        initialize(ss, ber);
-    }
-
-    /**
-     * Copy constructors
-     *
-     * @param s Source SignalStrength
-     *
-     * @hide
-     */
-    public CellSignalStrengthWcdma(CellSignalStrengthWcdma s) {
-        copyFrom(s);
-    }
-
-    /**
-     * Initialize all the values
-     *
-     * @param ss SignalStrength as ASU value
-     * @param ber is Bit Error Rate
-     *
-     * @hide
-     */
-    public void initialize(int ss, int ber) {
         mSignalStrength = ss;
         mBitErrorRate = ber;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
+    public CellSignalStrengthWcdma(CellSignalStrengthWcdma s) {
+        copyFrom(s);
+    }
+
+    /** @hide */
     protected void copyFrom(CellSignalStrengthWcdma s) {
         mSignalStrength = s.mSignalStrength;
         mBitErrorRate = s.mBitErrorRate;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
     @Override
     public CellSignalStrengthWcdma copy() {
         return new CellSignalStrengthWcdma(this);
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
new file mode 100644
index 0000000..b362df9
--- /dev/null
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -0,0 +1,160 @@
+/*
+ * 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.telephony;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.location.LocationManager;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Process;
+import android.os.Trace;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.util.SparseBooleanArray;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper for performing location access checks.
+ * @hide
+ */
+public final class LocationAccessPolicy {
+    /**
+     * API to determine if the caller has permissions to get cell location.
+     *
+     * @param pkgName Package name of the application requesting access
+     * @param uid The uid of the package
+     * @param pid The pid of the package
+     * @return boolean true or false if permissions is granted
+     */
+    public static boolean canAccessCellLocation(@NonNull Context context, @NonNull String pkgName,
+            int uid, int pid) throws SecurityException {
+        Trace.beginSection("TelephonyLocationCheck");
+        try {
+            // Always allow the phone process to access location. This avoid breaking legacy code
+            // that rely on public-facing APIs to access cell location, and it doesn't create a
+            // info leak risk because the cell location is stored in the phone process anyway.
+            if (uid == Process.PHONE_UID) {
+                return true;
+            }
+
+            // We always require the location permission and also require the
+            // location mode to be on for non-legacy apps. Legacy apps are
+            // required to be in the foreground to at least mitigate the case
+            // where a legacy app the user is not using tracks their location.
+            // Granting ACCESS_FINE_LOCATION to an app automatically grants it
+            // ACCESS_COARSE_LOCATION.
+
+            if (context.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, pid, uid) ==
+                    PackageManager.PERMISSION_DENIED) {
+                return false;
+            }
+            final int opCode = AppOpsManager.permissionToOpCode(
+                    Manifest.permission.ACCESS_COARSE_LOCATION);
+            if (opCode != AppOpsManager.OP_NONE && context.getSystemService(AppOpsManager.class)
+                    .noteOpNoThrow(opCode, uid, pkgName) != AppOpsManager.MODE_ALLOWED) {
+                return false;
+            }
+            if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))
+                    && !isLegacyForeground(context, pkgName, uid)) {
+                return false;
+            }
+            // If the user or profile is current, permission is granted.
+            // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
+            return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context);
+        } finally {
+            Trace.endSection();
+        }
+    }
+
+    private static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) {
+        int locationMode = Settings.Secure.getIntForUser(context.getContentResolver(),
+                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF, userId);
+        return locationMode != Settings.Secure.LOCATION_MODE_OFF
+                && 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)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    private static boolean isCurrentProfile(@NonNull Context context, int uid) {
+        long token = Binder.clearCallingIdentity();
+        try {
+            final int currentUser = ActivityManager.getCurrentUser();
+            final int callingUserId = UserHandle.getUserId(uid);
+            if (callingUserId == currentUser) {
+                return true;
+            } else {
+                List<UserInfo> userProfiles = context.getSystemService(
+                        UserManager.class).getProfiles(currentUser);
+                for (UserInfo user : userProfiles) {
+                    if (user.id == callingUserId) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index 059a2d0..da3d87b 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -437,6 +437,7 @@
             int result = downloadService.setTempFileRootDirectory(mSubscriptionId, filePath);
             if (result != MbmsErrors.SUCCESS) {
                 sendErrorToApp(result, null);
+                return;
             }
         } catch (RemoteException e) {
             mService.set(null);
@@ -686,30 +687,42 @@
     }
 
     /**
-     * Gets information about the status of a file pending download.
+     * Requests information about the state of a file pending download.
      *
-     * If there was a problem communicating with the middleware or if it has no records of the
+     * The state will be delivered as a callback via
+     * {@link DownloadStateCallback#onStateUpdated(DownloadRequest, FileInfo, int)}. If no such
+     * callback has been registered via
+     * {@link #registerStateCallback(DownloadRequest, DownloadStateCallback, Handler)}, this
+     * method will be a no-op.
+     *
+     * If the middleware has no record of the
      * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
-     * {@link #STATUS_UNKNOWN} will be returned.
+     * an {@link IllegalArgumentException} will be thrown.
      *
      * @param downloadRequest The download request to query.
      * @param fileInfo The particular file within the request to get information on.
-     * @return The status of the download.
      */
-    @DownloadStatus
-    public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo) {
+    public void requestDownloadState(DownloadRequest downloadRequest, FileInfo fileInfo) {
         IMbmsDownloadService downloadService = mService.get();
         if (downloadService == null) {
             throw new IllegalStateException("Middleware not yet bound");
         }
 
         try {
-            return downloadService.getDownloadStatus(downloadRequest, fileInfo);
+            int result = downloadService.requestDownloadState(downloadRequest, fileInfo);
+            if (result != MbmsErrors.SUCCESS) {
+                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
+                    throw new IllegalArgumentException("Unknown download request.");
+                }
+                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_FILE_INFO) {
+                    throw new IllegalArgumentException("Unknown file.");
+                }
+                sendErrorToApp(result, null);
+            }
         } catch (RemoteException e) {
             mService.set(null);
             sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
-            return STATUS_UNKNOWN;
         }
     }
 
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index ff67116..fadfc91 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -22,6 +22,7 @@
 import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
 import com.android.i18n.phonenumbers.ShortNumberInfo;
 
+import android.annotation.IntDef;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -42,6 +43,8 @@
 
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -49,8 +52,31 @@
 /**
  * Various utilities for dealing with phone number strings.
  */
-public class PhoneNumberUtils
-{
+public class PhoneNumberUtils {
+    /** {@hide} */
+    @IntDef(prefix = "BCD_EXTENDED_TYPE_", value = {
+            BCD_EXTENDED_TYPE_EF_ADN,
+            BCD_EXTENDED_TYPE_CALLED_PARTY,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BcdExtendType {}
+
+    /*
+     * The BCD extended type used to determine the extended char for the digit which is greater than
+     * 9.
+     *
+     * see TS 51.011 section 10.5.1 EF_ADN(Abbreviated dialling numbers)
+     */
+    public static final int BCD_EXTENDED_TYPE_EF_ADN = 1;
+
+    /*
+     * The BCD extended type used to determine the extended char for the digit which is greater than
+     * 9.
+     *
+     * see TS 24.008 section 10.5.4.7 Called party BCD number
+     */
+    public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2;
+
     /*
      * Special characters
      *
@@ -77,22 +103,6 @@
     public static final int TOA_International = 0x91;
     public static final int TOA_Unknown = 0x81;
 
-    /*
-     * The BCD extended type used to determine the extended char for the digit which is greater than
-     * 9.
-     *
-     * see TS 51.011 section 10.5.1 EF_ADN(Abbreviated dialling numbers)
-     */
-    public static final int BCD_EXTENDED_TYPE_EF_ADN = 1;
-
-    /*
-     * The BCD extended type used to determine the extended char for the digit which is greater than
-     * 9.
-     *
-     * see TS 24.008 section 10.5.4.7 Called party BCD number
-     */
-    public static final int BCD_EXTENDED_TYPE_CALLED_PARTY = 2;
-
     static final String LOG_TAG = "PhoneNumberUtils";
     private static final boolean DBG = false;
 
@@ -844,7 +854,7 @@
      *
      */
     public static String calledPartyBCDToString(
-            byte[] bytes, int offset, int length, int bcdExtType) {
+            byte[] bytes, int offset, int length, @BcdExtendType int bcdExtType) {
         boolean prependPlus = false;
         StringBuilder ret = new StringBuilder(1 + length * 2);
 
@@ -944,7 +954,8 @@
     }
 
     private static void internalCalledPartyBCDFragmentToString(
-            StringBuilder sb, byte [] bytes, int offset, int length, int bcdExtType) {
+            StringBuilder sb, byte [] bytes, int offset, int length,
+            @BcdExtendType int bcdExtType) {
         for (int i = offset ; i < length + offset ; i++) {
             byte b;
             char c;
@@ -999,7 +1010,7 @@
      * TOA byte. For example: SIM ADN extension fields
      */
     public static String calledPartyBCDFragmentToString(
-            byte[] bytes, int offset, int length, int bcdExtType) {
+            byte[] bytes, int offset, int length, @BcdExtendType int bcdExtType) {
         StringBuilder ret = new StringBuilder(length * 2);
         internalCalledPartyBCDFragmentToString(ret, bytes, offset, length, bcdExtType);
         return ret.toString();
@@ -1009,7 +1020,7 @@
      * Returns the correspond character for given {@code b} based on {@code bcdExtType}, or 0 on
      * invalid code.
      */
-    private static char bcdToChar(byte b, int bcdExtType) {
+    private static char bcdToChar(byte b, @BcdExtendType int bcdExtType) {
         if (b < 0xa) {
             return (char) ('0' + b);
         }
@@ -1027,7 +1038,7 @@
         return extended.charAt(b - 0xa);
     }
 
-    private static int charToBCD(char c, int bcdExtType) {
+    private static int charToBCD(char c, @BcdExtendType int bcdExtType) {
         if ('0' <= c && c <= '9') {
             return c - '0';
         }
@@ -1134,7 +1145,7 @@
      *
      * @return BCD byte array
      */
-    public static byte[] numberToCalledPartyBCD(String number, int bcdExtType) {
+    public static byte[] numberToCalledPartyBCD(String number, @BcdExtendType int bcdExtType) {
         return numberToCalledPartyBCDHelper(number, false, bcdExtType);
     }
 
@@ -1143,7 +1154,7 @@
      * the return array.
      */
     private static byte[] numberToCalledPartyBCDHelper(
-            String number, boolean includeLength, int bcdExtType) {
+            String number, boolean includeLength, @BcdExtendType int bcdExtType) {
         int numberLenReal = number.length();
         int numberLenEffective = numberLenReal;
         boolean hasPlus = number.indexOf('+') != -1;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 90a3677..1176491 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -22,13 +22,13 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.text.TextUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -1340,6 +1340,39 @@
     }
 
     /** @hide */
+    public static int rilRadioTechnologyToAccessNetworkType(@RilRadioTechnology int rt) {
+        switch(rt) {
+            case RIL_RADIO_TECHNOLOGY_GPRS:
+            case RIL_RADIO_TECHNOLOGY_EDGE:
+            case RIL_RADIO_TECHNOLOGY_GSM:
+                return AccessNetworkType.GERAN;
+            case RIL_RADIO_TECHNOLOGY_UMTS:
+            case RIL_RADIO_TECHNOLOGY_HSDPA:
+            case RIL_RADIO_TECHNOLOGY_HSPAP:
+            case RIL_RADIO_TECHNOLOGY_HSUPA:
+            case RIL_RADIO_TECHNOLOGY_HSPA:
+            case RIL_RADIO_TECHNOLOGY_TD_SCDMA:
+                return AccessNetworkType.UTRAN;
+            case RIL_RADIO_TECHNOLOGY_IS95A:
+            case RIL_RADIO_TECHNOLOGY_IS95B:
+            case RIL_RADIO_TECHNOLOGY_1xRTT:
+            case RIL_RADIO_TECHNOLOGY_EVDO_0:
+            case RIL_RADIO_TECHNOLOGY_EVDO_A:
+            case RIL_RADIO_TECHNOLOGY_EVDO_B:
+            case RIL_RADIO_TECHNOLOGY_EHRPD:
+                return AccessNetworkType.CDMA2000;
+            case RIL_RADIO_TECHNOLOGY_LTE:
+            case RIL_RADIO_TECHNOLOGY_LTE_CA:
+                return AccessNetworkType.EUTRAN;
+            case RIL_RADIO_TECHNOLOGY_IWLAN:
+                return AccessNetworkType.IWLAN;
+            case RIL_RADIO_TECHNOLOGY_UNKNOWN:
+            default:
+                return AccessNetworkType.UNKNOWN;
+        }
+    }
+
+    /** @hide */
     public int getDataNetworkType() {
         return rilRadioTechnologyToNetworkType(mRilDataRadioTechnology);
     }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 78a4c65..9a45e7b 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -1127,7 +1127,11 @@
 
     // SMS send failure result codes
 
-    /** No error. {@hide}*/
+    /**
+     * No error.
+     * @hide
+     */
+    @SystemApi
     static public final int RESULT_ERROR_NONE    = 0;
     /** Generic failure cause */
     static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
@@ -1139,12 +1143,113 @@
     static public final int RESULT_ERROR_NO_SERVICE         = 4;
     /** Failed because we reached the sending queue limit. */
     static public final int RESULT_ERROR_LIMIT_EXCEEDED     = 5;
-    /** Failed because FDN is enabled. {@hide} */
+    /**
+     * Failed because FDN is enabled.
+     * @hide
+     */
+    @SystemApi
     static public final int RESULT_ERROR_FDN_CHECK_FAILURE  = 6;
     /** Failed because user denied the sending of this short code. */
     static public final int RESULT_ERROR_SHORT_CODE_NOT_ALLOWED = 7;
     /** Failed because the user has denied this app ever send premium short codes. */
     static public final int RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED = 8;
+    /**
+     * Failed because the radio was not available
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_RADIO_NOT_AVAILABLE = 9;
+    /**
+     * Failed because of network rejection
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_NETWORK_REJECT = 10;
+    /**
+     * Failed because of invalid arguments
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_INVALID_ARGUMENTS = 11;
+    /**
+     * Failed because of an invalid state
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_INVALID_STATE = 12;
+    /**
+     * Failed because there is no memory
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_NO_MEMORY = 13;
+    /**
+     * Failed because the sms format is not valid
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_INVALID_SMS_FORMAT = 14;
+    /**
+     * Failed because of a system error
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_SYSTEM_ERROR = 15;
+    /**
+     * Failed because of a modem error
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_MODEM_ERROR = 16;
+    /**
+     * Failed because of a network error
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_NETWORK_ERROR = 17;
+    /**
+     * Failed because of an encoding error
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_ENCODING_ERROR = 18;
+    /**
+     * Failed because of an invalid smsc address
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_INVALID_SMSC_ADDRESS = 19;
+    /**
+     * Failed because the operation is not allowed
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_OPERATION_NOT_ALLOWED = 20;
+    /**
+     * Failed because of an internal error
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_INTERNAL_ERROR = 21;
+    /**
+     * Failed because there are no resources
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_NO_RESOURCES = 22;
+    /**
+     * Failed because the operation was cancelled
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_CANCELLED = 23;
+    /**
+     * Failed because the request is not supported
+     * @hide
+     */
+    @SystemApi
+    static public final int RESULT_REQUEST_NOT_SUPPORTED = 24;
+
 
     static private final String PHONE_PACKAGE_NAME = "com.android.phone";
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 1fae04b..137f491 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -541,9 +541,9 @@
      *                 onSubscriptionsChanged overridden.
      */
     public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
-        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         if (DBG) {
-            logd("register OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
+            logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
                     + " listener=" + listener);
         }
         try {
@@ -552,7 +552,7 @@
             ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                     "telephony.registry"));
             if (tr != null) {
-                tr.addOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
+                tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
             }
         } catch (RemoteException ex) {
             // Should not happen
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 63e8c3b..e8c1cb1 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -34,6 +34,8 @@
 import android.telephony.Rlog;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -105,7 +107,9 @@
 
     private final SparseArray<DataServiceProvider> mServiceMap = new SparseArray<>();
 
-    private final IBinder mBinder = new IDataServiceWrapper();
+    /** @hide */
+    @VisibleForTesting
+    public final IDataServiceWrapper mBinder = new IDataServiceWrapper();
 
     /**
      * The abstract class of the actual data service implementation. The data service provider
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
index 4e095e3a..93c316f 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.os.Message;
 import android.os.RemoteException;
+import android.telephony.ims.internal.stub.SmsImplBase;
 
 import com.android.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
@@ -28,6 +29,7 @@
 import com.android.ims.internal.IImsMMTelFeature;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.ImsCallSession;
 
@@ -171,6 +173,49 @@
                 return MMTelFeature.this.getMultiEndpointInterface();
             }
         }
+
+        @Override
+        public void setSmsListener(IImsSmsListener l) throws RemoteException {
+            synchronized (mLock) {
+                MMTelFeature.this.setSmsListener(l);
+            }
+        }
+
+        @Override
+        public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
+                byte[] pdu) {
+            synchronized (mLock) {
+                MMTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
+            }
+        }
+
+        @Override
+        public void acknowledgeSms(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MMTelFeature.this.acknowledgeSms(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public void acknowledgeSmsReport(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MMTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public String getSmsFormat() {
+            synchronized (mLock) {
+                return MMTelFeature.this.getSmsFormat();
+            }
+        }
+
+        @Override
+        public void onSmsReady() {
+            synchronized (mLock) {
+                MMTelFeature.this.onSmsReady();
+            }
+        }
     };
 
     /**
@@ -346,6 +391,43 @@
         return null;
     }
 
+    private void setSmsListener(IImsSmsListener listener) {
+        getSmsImplementation().registerSmsListener(listener);
+    }
+
+    private void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+            byte[] pdu) {
+        getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu);
+    }
+
+    private void acknowledgeSms(int token, int messageRef,
+            @SmsImplBase.DeliverStatusResult int result) {
+        getSmsImplementation().acknowledgeSms(token, messageRef, result);
+    }
+
+    private void acknowledgeSmsReport(int token, int messageRef,
+            @SmsImplBase.StatusReportResult int result) {
+        getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
+    }
+
+    private void onSmsReady() {
+        getSmsImplementation().onReady();
+    }
+
+    /**
+     * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
+     * non-functional implementation is returned.
+     *
+     * @return an instance of {@link SmsImplBase} which should be implemented by the IMS Provider.
+     */
+    protected SmsImplBase getSmsImplementation() {
+        return new SmsImplBase();
+    }
+
+    public String getSmsFormat() {
+        return getSmsImplementation().getSmsFormat();
+    }
+
     @Override
     public void onFeatureReady() {
 
diff --git a/telephony/java/android/telephony/ims/internal/SmsImplBase.java b/telephony/java/android/telephony/ims/internal/SmsImplBase.java
deleted file mode 100644
index 47414cf..0000000
--- a/telephony/java/android/telephony/ims/internal/SmsImplBase.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.telephony.ims.internal;
-
-import android.annotation.IntDef;
-import android.annotation.SystemApi;
-import android.os.RemoteException;
-import android.telephony.SmsManager;
-import android.telephony.SmsMessage;
-import android.telephony.ims.internal.aidl.IImsSmsListener;
-import android.telephony.ims.internal.feature.MmTelFeature;
-import android.util.Log;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Base implementation for SMS over IMS.
- *
- * Any service wishing to provide SMS over IMS should extend this class and implement all methods
- * that the service supports.
- * @hide
- */
-public class SmsImplBase {
-  private static final String LOG_TAG = "SmsImplBase";
-
-  @IntDef({
-          SEND_STATUS_OK,
-          SEND_STATUS_ERROR,
-          SEND_STATUS_ERROR_RETRY,
-          SEND_STATUS_ERROR_FALLBACK
-      })
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface SendStatusResult {}
-  /**
-   * Message was sent successfully.
-   */
-  public static final int SEND_STATUS_OK = 1;
-
-  /**
-   * IMS provider failed to send the message and platform should not retry falling back to sending
-   * the message using the radio.
-   */
-  public static final int SEND_STATUS_ERROR = 2;
-
-  /**
-   * IMS provider failed to send the message and platform should retry again after setting TP-RD bit
-   * to high.
-   */
-  public static final int SEND_STATUS_ERROR_RETRY = 3;
-
-  /**
-   * IMS provider failed to send the message and platform should retry falling back to sending
-   * the message using the radio.
-   */
-  public static final int SEND_STATUS_ERROR_FALLBACK = 4;
-
-  @IntDef({
-          DELIVER_STATUS_OK,
-          DELIVER_STATUS_ERROR
-      })
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface DeliverStatusResult {}
-  /**
-   * Message was delivered successfully.
-   */
-  public static final int DELIVER_STATUS_OK = 1;
-
-  /**
-   * Message was not delivered.
-   */
-  public static final int DELIVER_STATUS_ERROR = 2;
-
-  @IntDef({
-          STATUS_REPORT_STATUS_OK,
-          STATUS_REPORT_STATUS_ERROR
-      })
-  @Retention(RetentionPolicy.SOURCE)
-  public @interface StatusReportResult {}
-
-  /**
-   * Status Report was set successfully.
-   */
-  public static final int STATUS_REPORT_STATUS_OK = 1;
-
-  /**
-   * Error while setting status report.
-   */
-  public static final int STATUS_REPORT_STATUS_ERROR = 2;
-
-
-  // Lock for feature synchronization
-  private final Object mLock = new Object();
-  private IImsSmsListener mListener;
-
-  /**
-   * Registers a listener responsible for handling tasks like delivering messages.
-   *
-   * @param listener listener to register.
-   *
-   * @hide
-   */
-  public final void registerSmsListener(IImsSmsListener listener) {
-    synchronized (mLock) {
-      mListener = listener;
-    }
-  }
-
-  /**
-   * This method will be triggered by the platform when the user attempts to send an SMS. This
-   * method should be implemented by the IMS providers to provide implementation of sending an SMS
-   * over IMS.
-   *
-   * @param smsc the Short Message Service Center address.
-   * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
-   * {@link SmsMessage#FORMAT_3GPP2}.
-   * @param messageRef the message reference.
-   * @param isRetry whether it is a retry of an already attempted message or not.
-   * @param pdu PDUs representing the contents of the message.
-   */
-  public void sendSms(int messageRef, String format, String smsc, boolean isRetry, byte[] pdu) {
-    // Base implementation returns error. Should be overridden.
-    try {
-      onSendSmsResult(messageRef, SEND_STATUS_ERROR, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
-    } catch (RemoteException e) {
-      Log.e(LOG_TAG, "Can not send sms: " + e.getMessage());
-    }
-  }
-
-  /**
-   * This method will be triggered by the platform after {@link #onSmsReceived(String, byte[])} has
-   * been called to deliver the result to the IMS provider.
-   *
-   * @param result result of delivering the message. Valid values are defined in
-   * {@link DeliverStatusResult}
-   * @param messageRef the message reference or -1 of unavailable.
-   */
-  public void acknowledgeSms(int messageRef, @DeliverStatusResult int result) {
-
-  }
-
-  /**
-   * This method will be triggered by the platform after
-   * {@link #onSmsStatusReportReceived(int, int, byte[])} has been called to provide the result to
-   * the IMS provider.
-   *
-   * @param result result of delivering the message. Valid values are defined in
-   * {@link StatusReportResult}
-   * @param messageRef the message reference or -1 of unavailable.
-   */
-  public void acknowledgeSmsReport(int messageRef, @StatusReportResult int result) {
-
-  }
-
-  /**
-   * This method should be triggered by the IMS providers when there is an incoming message. The
-   * platform will deliver the message to the messages database and notify the IMS provider of the
-   * result by calling {@link #acknowledgeSms(int, int)}.
-   *
-   * This method must not be called before {@link MmTelFeature#onFeatureReady()} is called.
-   *
-   * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
-   * {@link SmsMessage#FORMAT_3GPP2}.
-   * @param pdu PDUs representing the contents of the message.
-   * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
-   */
-  public final void onSmsReceived(String format, byte[] pdu) throws IllegalStateException {
-    synchronized (mLock) {
-      if (mListener == null) {
-        throw new IllegalStateException("Feature not ready.");
-      }
-      try {
-        mListener.onSmsReceived(format, pdu);
-        acknowledgeSms(-1, DELIVER_STATUS_OK);
-      } catch (RemoteException e) {
-        Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
-        acknowledgeSms(-1, DELIVER_STATUS_ERROR);
-      }
-    }
-  }
-
-  /**
-   * This method should be triggered by the IMS providers to pass the result of the sent message
-   * to the platform.
-   *
-   * This method must not be called before {@link MmTelFeature#onFeatureReady()} is called.
-   *
-   * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
-   * @param status result of sending the SMS. Valid values are defined in {@link SendStatusResult}
-   * @param reason reason in case status is failure. Valid values are:
-   *  {@link SmsManager#RESULT_ERROR_NONE},
-   *  {@link SmsManager#RESULT_ERROR_GENERIC_FAILURE},
-   *  {@link SmsManager#RESULT_ERROR_RADIO_OFF},
-   *  {@link SmsManager#RESULT_ERROR_NULL_PDU},
-   *  {@link SmsManager#RESULT_ERROR_NO_SERVICE},
-   *  {@link SmsManager#RESULT_ERROR_LIMIT_EXCEEDED},
-   *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NOT_ALLOWED},
-   *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED}
-   * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
-   * @throws RemoteException if the connection to the framework is not available. If this happens
-   *  attempting to send the SMS should be aborted.
-   */
-  public final void onSendSmsResult(int messageRef, @SendStatusResult int status, int reason)
-      throws IllegalStateException, RemoteException {
-    synchronized (mLock) {
-      if (mListener == null) {
-        throw new IllegalStateException("Feature not ready.");
-      }
-      mListener.onSendSmsResult(messageRef, status, reason);
-    }
-  }
-
-  /**
-   * Sets the status report of the sent message.
-   *
-   * @param messageRef the message reference.
-   * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
-   * {@link SmsMessage#FORMAT_3GPP2}.
-   * @param pdu PDUs representing the content of the status report.
-   * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
-   */
-  public final void onSmsStatusReportReceived(int messageRef, String format, byte[] pdu) {
-    synchronized (mLock) {
-      if (mListener == null) {
-        throw new IllegalStateException("Feature not ready.");
-      }
-      try {
-        mListener.onSmsStatusReportReceived(messageRef, format, pdu);
-      } catch (RemoteException e) {
-        Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
-        acknowledgeSmsReport(messageRef, STATUS_REPORT_STATUS_ERROR);
-      }
-    }
-  }
-
-  /**
-   * Returns the SMS format. Default is {@link SmsMessage#FORMAT_3GPP} unless overridden by IMS
-   * Provider.
-   *
-   * @return  the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
-   * {@link SmsMessage#FORMAT_3GPP2}.
-   */
-  public String getSmsFormat() {
-    return SmsMessage.FORMAT_3GPP;
-  }
-
-}
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl b/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl
index d976686..e226ada 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl
+++ b/telephony/java/android/telephony/ims/internal/aidl/IImsMmTelFeature.aidl
@@ -18,7 +18,6 @@
 
 import android.os.Message;
 import android.telephony.ims.internal.aidl.IImsMmTelListener;
-import android.telephony.ims.internal.aidl.IImsSmsListener;
 import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
 import android.telephony.ims.internal.aidl.IImsCallSessionListener;
 import android.telephony.ims.internal.feature.CapabilityChangeRequest;
@@ -50,10 +49,4 @@
             IImsCapabilityCallback c);
     oneway void queryCapabilityConfiguration(int capability, int radioTech,
             IImsCapabilityCallback c);
-    // SMS APIs
-    void setSmsListener(IImsSmsListener l);
-    oneway void sendSms(int messageRef, String format, String smsc, boolean retry, in byte[] pdu);
-    oneway void acknowledgeSms(int messageRef, int result);
-    oneway void acknowledgeSmsReport(int messageRef, int result);
-    String getSmsFormat();
 }
diff --git a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java
index 057c9a86..9b576c7 100644
--- a/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/internal/feature/MmTelFeature.java
@@ -21,14 +21,10 @@
 import android.os.RemoteException;
 import android.telecom.TelecomManager;
 import android.telephony.ims.internal.ImsCallSessionListener;
-import android.telephony.ims.internal.SmsImplBase;
-import android.telephony.ims.internal.SmsImplBase.DeliverStatusResult;
-import android.telephony.ims.internal.SmsImplBase.StatusReportResult;
 import android.telephony.ims.internal.aidl.IImsCallSessionListener;
 import android.telephony.ims.internal.aidl.IImsCapabilityCallback;
 import android.telephony.ims.internal.aidl.IImsMmTelFeature;
 import android.telephony.ims.internal.aidl.IImsMmTelListener;
-import android.telephony.ims.internal.aidl.IImsSmsListener;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.telephony.ims.stub.ImsEcbmImplBase;
 import android.telephony.ims.stub.ImsMultiEndpointImplBase;
@@ -68,11 +64,6 @@
         }
 
         @Override
-        public void setSmsListener(IImsSmsListener l) throws RemoteException {
-            MmTelFeature.this.setSmsListener(l);
-        }
-
-        @Override
         public int getFeatureState() throws RemoteException {
             synchronized (mLock) {
                 return MmTelFeature.this.getFeatureState();
@@ -152,34 +143,6 @@
                 IImsCapabilityCallback c) {
             queryCapabilityConfigurationInternal(capability, radioTech, c);
         }
-
-        @Override
-        public void sendSms(int messageRef, String format, String smsc, boolean retry, byte[] pdu) {
-            synchronized (mLock) {
-                MmTelFeature.this.sendSms(messageRef, format, smsc, retry, pdu);
-            }
-        }
-
-        @Override
-        public void acknowledgeSms(int messageRef, int result) {
-            synchronized (mLock) {
-                MmTelFeature.this.acknowledgeSms(messageRef, result);
-            }
-        }
-
-        @Override
-        public void acknowledgeSmsReport(int messageRef, int result) {
-            synchronized (mLock) {
-                MmTelFeature.this.acknowledgeSmsReport(messageRef, result);
-            }
-        }
-
-        @Override
-        public String getSmsFormat() {
-            synchronized (mLock) {
-                return MmTelFeature.this.getSmsFormat();
-            }
-        }
     };
 
     /**
@@ -291,10 +254,6 @@
         }
     }
 
-    private void setSmsListener(IImsSmsListener listener) {
-        getSmsImplementation().registerSmsListener(listener);
-    }
-
     private void queryCapabilityConfigurationInternal(int capability, int radioTech,
             IImsCapabilityCallback c) {
         boolean enabled = queryCapabilityConfiguration(capability, radioTech);
@@ -456,32 +415,6 @@
         // Base Implementation - Should be overridden
     }
 
-    private void sendSms(int messageRef, String format, String smsc, boolean isRetry, byte[] pdu) {
-        getSmsImplementation().sendSms(messageRef, format, smsc, isRetry, pdu);
-    }
-
-    private void acknowledgeSms(int messageRef, @DeliverStatusResult int result) {
-        getSmsImplementation().acknowledgeSms(messageRef, result);
-    }
-
-    private void acknowledgeSmsReport(int messageRef, @StatusReportResult int result) {
-        getSmsImplementation().acknowledgeSmsReport(messageRef, result);
-    }
-
-    private String getSmsFormat() {
-        return getSmsImplementation().getSmsFormat();
-    }
-
-    /**
-     * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
-     * non-functional implementation is returned.
-     *
-     * @return an instance of {@link SmsImplBase} which should be implemented by the IMS Provider.
-     */
-    protected SmsImplBase getSmsImplementation() {
-        return new SmsImplBase();
-    }
-
     /**{@inheritDoc}*/
     @Override
     public void onFeatureRemoved() {
diff --git a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java b/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
new file mode 100644
index 0000000..57df526
--- /dev/null
+++ b/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
@@ -0,0 +1,313 @@
+/*
+ * 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.telephony.ims.internal.stub;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
+import android.util.Log;
+
+import com.android.ims.internal.IImsSmsListener;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Base implementation for SMS over IMS.
+ *
+ * Any service wishing to provide SMS over IMS should extend this class and implement all methods
+ * that the service supports.
+ *
+ * @hide
+ */
+@SystemApi
+public class SmsImplBase {
+    private static final String LOG_TAG = "SmsImplBase";
+
+    /** @hide */
+    @IntDef({
+            SEND_STATUS_OK,
+            SEND_STATUS_ERROR,
+            SEND_STATUS_ERROR_RETRY,
+            SEND_STATUS_ERROR_FALLBACK
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SendStatusResult {}
+    /**
+     * Message was sent successfully.
+     */
+    public static final int SEND_STATUS_OK = 1;
+
+    /**
+     * IMS provider failed to send the message and platform should not retry falling back to sending
+     * the message using the radio.
+     */
+    public static final int SEND_STATUS_ERROR = 2;
+
+    /**
+     * IMS provider failed to send the message and platform should retry again after setting TP-RD
+     * bit to high.
+     */
+    public static final int SEND_STATUS_ERROR_RETRY = 3;
+
+    /**
+     * IMS provider failed to send the message and platform should retry falling back to sending
+     * the message using the radio.
+     */
+    public static final int SEND_STATUS_ERROR_FALLBACK = 4;
+
+    /** @hide */
+    @IntDef({
+            DELIVER_STATUS_OK,
+            DELIVER_STATUS_ERROR
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeliverStatusResult {}
+    /**
+     * Message was delivered successfully.
+     */
+    public static final int DELIVER_STATUS_OK = 1;
+
+    /**
+     * Message was not delivered.
+     */
+    public static final int DELIVER_STATUS_ERROR = 2;
+
+    /** @hide */
+    @IntDef({
+            STATUS_REPORT_STATUS_OK,
+            STATUS_REPORT_STATUS_ERROR
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StatusReportResult {}
+
+    /**
+     * Status Report was set successfully.
+     */
+    public static final int STATUS_REPORT_STATUS_OK = 1;
+
+    /**
+     * Error while setting status report.
+     */
+    public static final int STATUS_REPORT_STATUS_ERROR = 2;
+
+
+    // Lock for feature synchronization
+    private final Object mLock = new Object();
+    private IImsSmsListener mListener;
+
+    /**
+     * Registers a listener responsible for handling tasks like delivering messages.
+     *
+     * @param listener listener to register.
+     *
+     * @hide
+     */
+    public final void registerSmsListener(IImsSmsListener listener) {
+        synchronized (mLock) {
+            mListener = listener;
+        }
+    }
+
+    /**
+     * This method will be triggered by the platform when the user attempts to send an SMS. This
+     * method should be implemented by the IMS providers to provide implementation of sending an SMS
+     * over IMS.
+     *
+     * @param token unique token generated by the platform that should be used when triggering
+     *             callbacks for this specific message.
+     * @param messageRef the message reference.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     *               {@link SmsMessage#FORMAT_3GPP2}.
+     * @param smsc the Short Message Service Center address.
+     * @param isRetry whether it is a retry of an already attempted message or not.
+     * @param pdu PDUs representing the contents of the message.
+     */
+    public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+            byte[] pdu) {
+        // Base implementation returns error. Should be overridden.
+        try {
+            onSendSmsResult(token, messageRef, SEND_STATUS_ERROR,
+                    SmsManager.RESULT_ERROR_GENERIC_FAILURE);
+        } catch (RuntimeException e) {
+            Log.e(LOG_TAG, "Can not send sms: " + e.getMessage());
+        }
+    }
+
+    /**
+     * This method will be triggered by the platform after
+     * {@link #onSmsReceived(int, String, byte[])} has been called to deliver the result to the IMS
+     * provider.
+     *
+     * @param token token provided in {@link #onSmsReceived(int, String, byte[])}
+     * @param result result of delivering the message. Valid values are:
+     *  {@link #DELIVER_STATUS_OK},
+     *  {@link #DELIVER_STATUS_OK}
+     * @param messageRef the message reference
+     */
+    public void acknowledgeSms(int token, @DeliverStatusResult int messageRef, int result) {
+        Log.e(LOG_TAG, "acknowledgeSms() not implemented.");
+    }
+
+    /**
+     * This method will be triggered by the platform after
+     * {@link #onSmsStatusReportReceived(int, int, String, byte[])} has been called to provide the
+     * result to the IMS provider.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param result result of delivering the message. Valid values are:
+     *  {@link #STATUS_REPORT_STATUS_OK},
+     *  {@link #STATUS_REPORT_STATUS_ERROR}
+     * @param messageRef the message reference
+     */
+    public void acknowledgeSmsReport(int token, int messageRef, @StatusReportResult int result) {
+        Log.e(LOG_TAG, "acknowledgeSmsReport() not implemented.");
+    }
+
+    /**
+     * This method should be triggered by the IMS providers when there is an incoming message. The
+     * platform will deliver the message to the messages database and notify the IMS provider of the
+     * result by calling {@link #acknowledgeSms(int, int, int)}.
+     *
+     * This method must not be called before {@link #onReady()} is called.
+     *
+     * @param token unique token generated by IMS providers that the platform will use to trigger
+     *              callbacks for this message.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDUs representing the contents of the message.
+     * @throws RuntimeException if called before {@link #onReady()} is triggered.
+     */
+    public final void onSmsReceived(int token, String format, byte[] pdu) throws RuntimeException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new RuntimeException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsReceived(token, format, pdu);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
+                acknowledgeSms(token, 0, DELIVER_STATUS_ERROR);
+            }
+        }
+    }
+
+    /**
+     * This method should be triggered by the IMS providers to pass the result of the sent message
+     * to the platform.
+     *
+     * This method must not be called before {@link #onReady()} is called.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
+     * @param status result of sending the SMS. Valid values are:
+     *  {@link #SEND_STATUS_OK},
+     *  {@link #SEND_STATUS_ERROR},
+     *  {@link #SEND_STATUS_ERROR_RETRY},
+     *  {@link #SEND_STATUS_ERROR_FALLBACK},
+     * @param reason reason in case status is failure. Valid values are:
+     *  {@link SmsManager#RESULT_ERROR_NONE},
+     *  {@link SmsManager#RESULT_ERROR_GENERIC_FAILURE},
+     *  {@link SmsManager#RESULT_ERROR_RADIO_OFF},
+     *  {@link SmsManager#RESULT_ERROR_NULL_PDU},
+     *  {@link SmsManager#RESULT_ERROR_NO_SERVICE},
+     *  {@link SmsManager#RESULT_ERROR_LIMIT_EXCEEDED},
+     *  {@link SmsManager#RESULT_ERROR_FDN_CHECK_FAILURE},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NOT_ALLOWED},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED},
+     *  {@link SmsManager#RESULT_RADIO_NOT_AVAILABLE},
+     *  {@link SmsManager#RESULT_NETWORK_REJECT},
+     *  {@link SmsManager#RESULT_INVALID_ARGUMENTS},
+     *  {@link SmsManager#RESULT_INVALID_STATE},
+     *  {@link SmsManager#RESULT_NO_MEMORY},
+     *  {@link SmsManager#RESULT_INVALID_SMS_FORMAT},
+     *  {@link SmsManager#RESULT_SYSTEM_ERROR},
+     *  {@link SmsManager#RESULT_MODEM_ERROR},
+     *  {@link SmsManager#RESULT_NETWORK_ERROR},
+     *  {@link SmsManager#RESULT_ENCODING_ERROR},
+     *  {@link SmsManager#RESULT_INVALID_SMSC_ADDRESS},
+     *  {@link SmsManager#RESULT_OPERATION_NOT_ALLOWED},
+     *  {@link SmsManager#RESULT_INTERNAL_ERROR},
+     *  {@link SmsManager#RESULT_NO_RESOURCES},
+     *  {@link SmsManager#RESULT_CANCELLED},
+     *  {@link SmsManager#RESULT_REQUEST_NOT_SUPPORTED}
+     *
+     * @throws RuntimeException if called before {@link #onReady()} is triggered or if the
+     * connection to the framework is not available. If this happens attempting to send the SMS
+     * should be aborted.
+     */
+    public final void onSendSmsResult(int token, int messageRef,  @SendStatusResult int status,
+            int reason) throws RuntimeException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new RuntimeException("Feature not ready.");
+            }
+            try {
+                mListener.onSendSmsResult(token, messageRef, status, reason);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Sets the status report of the sent message.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDUs representing the content of the status report.
+     * @throws RuntimeException if called before {@link #onReady()} is triggered
+     */
+    public final void onSmsStatusReportReceived(int token, int messageRef, String format,
+            byte[] pdu) throws RuntimeException{
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new RuntimeException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsStatusReportReceived(token, messageRef, format, pdu);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
+                acknowledgeSmsReport(token, messageRef, STATUS_REPORT_STATUS_ERROR);
+            }
+        }
+    }
+
+    /**
+     * Returns the SMS format. Default is {@link SmsMessage#FORMAT_3GPP} unless overridden by IMS
+     * Provider.
+     *
+     * @return  the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     */
+    public String getSmsFormat() {
+      return SmsMessage.FORMAT_3GPP;
+    }
+
+    /**
+     * Called when SmsImpl has been initialized and communication with the framework is set up.
+     * Any attempt by this class to access the framework before this method is called will return
+     * with an {@link RuntimeException}.
+     */
+    public void onReady() {
+        // Base Implementation - Should be overridden
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsErrors.java b/telephony/java/android/telephony/mbms/MbmsErrors.java
index af0af24..75ca35e 100644
--- a/telephony/java/android/telephony/mbms/MbmsErrors.java
+++ b/telephony/java/android/telephony/mbms/MbmsErrors.java
@@ -128,6 +128,9 @@
 
         /** Indicates that the middleware has no record of the supplied {@link DownloadRequest}. */
         public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402;
+
+        /** Indicates the the middleware has no record of the supplied {@link FileInfo} */
+        public static final int ERROR_UNKNOWN_FILE_INFO = 403;
     }
 
     private MbmsErrors() {}
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
index cb93542..7d9845f 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
@@ -46,7 +46,7 @@
 
     int cancelDownload(in DownloadRequest downloadRequest);
 
-    int getDownloadStatus(in DownloadRequest downloadRequest, in FileInfo fileInfo);
+    int requestDownloadState(in DownloadRequest downloadRequest, in FileInfo fileInfo);
 
     int resetDownloadKnowledge(in DownloadRequest downloadRequest);
 
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
index 4fee3df..86b1b7a 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
@@ -370,18 +370,18 @@
     }
 
     /**
-     * Gets information about the status of a file pending download.
+     * Requests information about the state of a file pending download.
      *
-     * If the middleware has not yet been properly initialized or if it has no records of the
+     * If the middleware has no records of the
      * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
-     * {@link MbmsDownloadSession#STATUS_UNKNOWN} must be returned.
+     * {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_FILE_INFO} must be returned.
      *
      * @param downloadRequest The download request to query.
      * @param fileInfo The particular file within the request to get information on.
-     * @return The status of the download.
+     * @return {@link MbmsErrors#SUCCESS} if the request was successful, an error code otherwise.
      */
     @Override
-    public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo)
+    public int requestDownloadState(DownloadRequest downloadRequest, FileInfo fileInfo)
             throws RemoteException {
         return 0;
     }
diff --git a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
index 52b3853..10c7f3e 100644
--- a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
+++ b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
@@ -25,6 +25,7 @@
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
 
 import android.os.Message;
@@ -53,4 +54,12 @@
     IImsEcbm getEcbmInterface();
     void setUiTTYMode(int uiTtyMode, in Message onComplete);
     IImsMultiEndpoint getMultiEndpointInterface();
+    // SMS APIs
+    void setSmsListener(IImsSmsListener l);
+    oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
+            in byte[] pdu);
+    oneway void acknowledgeSms(int token, int messageRef, int result);
+    oneway void acknowledgeSmsReport(int token, int messageRef, int result);
+    String getSmsFormat();
+    oneway void onSmsReady();
 }
diff --git a/telephony/java/android/telephony/ims/internal/aidl/IImsSmsListener.aidl b/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
similarity index 67%
rename from telephony/java/android/telephony/ims/internal/aidl/IImsSmsListener.aidl
rename to telephony/java/com/android/ims/internal/IImsSmsListener.aidl
index 468629a..5a4b7e4 100644
--- a/telephony/java/android/telephony/ims/internal/aidl/IImsSmsListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-package android.telephony.ims.internal.aidl;
+package com.android.ims.internal;
 
 /**
- * See MMTelFeature for more information.
+ * See SmsImplBase for more information.
  * {@hide}
  */
 interface IImsSmsListener {
-    void onSendSmsResult(in int messageRef, in int status, in int reason);
-    void onSmsStatusReportReceived(in int messageRef, in String format, in byte[] pdu);
-    void onSmsReceived(in String format, in byte[] pdu);
+    void onSendSmsResult(int token, int messageRef, int status, int reason);
+    void onSmsStatusReportReceived(int token, int messageRef, in String format,
+            in byte[] pdu);
+    void onSmsReceived(int token, in String format, in byte[] pdu);
 }
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 91032f3..d999c13 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -108,6 +108,7 @@
     public static final int EVENT_SET_CARRIER_DATA_ENABLED = BASE + 46;
     public static final int EVENT_DATA_RECONNECT = BASE + 47;
     public static final int EVENT_ROAMING_SETTING_CHANGE = BASE + 48;
+    public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49;
 
     /***** Constants *****/
 
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index cdee9e6..a3a3080 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -220,11 +220,6 @@
     String SETUP_DATA_PROTOCOL_IPV6   = "IPV6";
     String SETUP_DATA_PROTOCOL_IPV4V6 = "IPV4V6";
 
-    /* Deactivate data call reasons */
-    int DEACTIVATE_REASON_NONE = 0;
-    int DEACTIVATE_REASON_RADIO_OFF = 1;
-    int DEACTIVATE_REASON_PDP_RESET = 2;
-
     /* NV config radio reset types. */
     int NV_CONFIG_RELOAD_RESET = 1;
     int NV_CONFIG_ERASE_RESET = 2;