Merge "Extend carrier configs for visual voicemail"
diff --git a/api/current.txt b/api/current.txt
index f4ba7eb..5d968be 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -36,6 +36,7 @@
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
+    field public static final java.lang.String BIND_VISUAL_VOICEMAIL_SERVICE = "android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
     field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
     field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
@@ -7077,6 +7078,7 @@
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -38222,6 +38224,7 @@
     method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String, int);
     method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
     method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
+    method public boolean isConcurrentVoiceAndDataAllowed();
     method public boolean isHearingAidCompatibilitySupported();
     method public boolean isNetworkRoaming();
     method public boolean isSmsCapable();
@@ -38232,6 +38235,7 @@
     method public void listen(android.telephony.PhoneStateListener, int);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+    method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public void setDataEnabled(boolean);
     method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
     method public boolean setOperatorBrandOverride(java.lang.String);
@@ -38312,6 +38316,54 @@
     method public void onReceiveUssdResponseFailed(java.lang.String, int);
   }
 
+  public abstract class VisualVoicemailService extends android.app.Service {
+    ctor public VisualVoicemailService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onCellServiceConnected(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
+    method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
+    method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms);
+    method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask);
+    method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent);
+    method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
+  }
+
+  public static class VisualVoicemailService.VisualVoicemailTask {
+    method public final void finish();
+  }
+
+  public final class VisualVoicemailSms implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getFields();
+    method public java.lang.String getMessageBody();
+    method public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
+    method public java.lang.String getPrefix();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSms> CREATOR;
+  }
+
+  public final class VisualVoicemailSmsFilterSettings implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
+    field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
+    field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
+    field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
+    field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
+    field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
+    field public final java.lang.String clientPrefix;
+    field public final int destinationPort;
+    field public final java.util.List<java.lang.String> originatingNumbers;
+  }
+
+  public static class VisualVoicemailSmsFilterSettings.Builder {
+    ctor public VisualVoicemailSmsFilterSettings.Builder();
+    method public android.telephony.VisualVoicemailSmsFilterSettings build();
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setClientPrefix(java.lang.String);
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setDestinationPort(int);
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setOriginatingNumbers(java.util.List<java.lang.String>);
+  }
+
 }
 
 package android.telephony.cdma {
diff --git a/api/system-current.txt b/api/system-current.txt
index c00f3dd..f336cdb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -55,6 +55,7 @@
     field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
     field public static final java.lang.String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
+    field public static final java.lang.String BIND_VISUAL_VOICEMAIL_SERVICE = "android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
     field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
     field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
@@ -7380,6 +7381,7 @@
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -41439,6 +41441,7 @@
     method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String, int);
     method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
     method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
+    method public boolean isConcurrentVoiceAndDataAllowed();
     method public boolean isDataConnectivityPossible();
     method public boolean isHearingAidCompatibilitySupported();
     method public boolean isIdle();
@@ -41457,6 +41460,7 @@
     method public boolean needsOtaServiceProvisioning();
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+    method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
     method public void setDataEnabled(boolean);
     method public void setDataEnabled(int, boolean);
@@ -41558,6 +41562,54 @@
     method public void onReceiveUssdResponseFailed(java.lang.String, int);
   }
 
+  public abstract class VisualVoicemailService extends android.app.Service {
+    ctor public VisualVoicemailService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onCellServiceConnected(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
+    method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
+    method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms);
+    method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask);
+    method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent);
+    method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
+  }
+
+  public static class VisualVoicemailService.VisualVoicemailTask {
+    method public final void finish();
+  }
+
+  public final class VisualVoicemailSms implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getFields();
+    method public java.lang.String getMessageBody();
+    method public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
+    method public java.lang.String getPrefix();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSms> CREATOR;
+  }
+
+  public final class VisualVoicemailSmsFilterSettings implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
+    field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
+    field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
+    field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
+    field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
+    field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
+    field public final java.lang.String clientPrefix;
+    field public final int destinationPort;
+    field public final java.util.List<java.lang.String> originatingNumbers;
+  }
+
+  public static class VisualVoicemailSmsFilterSettings.Builder {
+    ctor public VisualVoicemailSmsFilterSettings.Builder();
+    method public android.telephony.VisualVoicemailSmsFilterSettings build();
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setClientPrefix(java.lang.String);
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setDestinationPort(int);
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setOriginatingNumbers(java.util.List<java.lang.String>);
+  }
+
 }
 
 package android.telephony.cdma {
diff --git a/api/test-current.txt b/api/test-current.txt
index bf488ee..65cfd84 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -36,6 +36,7 @@
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
+    field public static final java.lang.String BIND_VISUAL_VOICEMAIL_SERVICE = "android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
     field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
     field public static final java.lang.String BIND_VR_LISTENER_SERVICE = "android.permission.BIND_VR_LISTENER_SERVICE";
@@ -7086,6 +7087,7 @@
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -38321,6 +38323,7 @@
     method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String, int);
     method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
     method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
+    method public boolean isConcurrentVoiceAndDataAllowed();
     method public boolean isHearingAidCompatibilitySupported();
     method public boolean isNetworkRoaming();
     method public boolean isSmsCapable();
@@ -38331,6 +38334,7 @@
     method public void listen(android.telephony.PhoneStateListener, int);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+    method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public void setDataEnabled(boolean);
     method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
     method public boolean setOperatorBrandOverride(java.lang.String);
@@ -38411,6 +38415,54 @@
     method public void onReceiveUssdResponseFailed(java.lang.String, int);
   }
 
+  public abstract class VisualVoicemailService extends android.app.Service {
+    ctor public VisualVoicemailService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onCellServiceConnected(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
+    method public abstract void onSimRemoved(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telecom.PhoneAccountHandle);
+    method public abstract void onSmsReceived(android.telephony.VisualVoicemailService.VisualVoicemailTask, android.telephony.VisualVoicemailSms);
+    method public abstract void onStopped(android.telephony.VisualVoicemailService.VisualVoicemailTask);
+    method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, java.lang.String, short, java.lang.String, android.app.PendingIntent);
+    method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
+  }
+
+  public static class VisualVoicemailService.VisualVoicemailTask {
+    method public final void finish();
+  }
+
+  public final class VisualVoicemailSms implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getFields();
+    method public java.lang.String getMessageBody();
+    method public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
+    method public java.lang.String getPrefix();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSms> CREATOR;
+  }
+
+  public final class VisualVoicemailSmsFilterSettings implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.VisualVoicemailSmsFilterSettings> CREATOR;
+    field public static final java.lang.String DEFAULT_CLIENT_PREFIX = "//VVM";
+    field public static final int DEFAULT_DESTINATION_PORT = -1; // 0xffffffff
+    field public static final java.util.List<java.lang.String> DEFAULT_ORIGINATING_NUMBERS;
+    field public static final int DESTINATION_PORT_ANY = -1; // 0xffffffff
+    field public static final int DESTINATION_PORT_DATA_SMS = -2; // 0xfffffffe
+    field public final java.lang.String clientPrefix;
+    field public final int destinationPort;
+    field public final java.util.List<java.lang.String> originatingNumbers;
+  }
+
+  public static class VisualVoicemailSmsFilterSettings.Builder {
+    ctor public VisualVoicemailSmsFilterSettings.Builder();
+    method public android.telephony.VisualVoicemailSmsFilterSettings build();
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setClientPrefix(java.lang.String);
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setDestinationPort(int);
+    method public android.telephony.VisualVoicemailSmsFilterSettings.Builder setOriginatingNumbers(java.util.List<java.lang.String>);
+  }
+
 }
 
 package android.telephony.cdma {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index e6cebc0..e0b03d2 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -22,6 +22,8 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.ParcelUuid;
@@ -593,32 +595,38 @@
     public static final int TRANSPORT_LE = 2;
 
     /**
-     * Bluetooth LE 1M PHY.
+     * Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or
+     * connection.
      */
     public static final int PHY_LE_1M = 1;
 
     /**
-     * Bluetooth LE 2M PHY.
+     * Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or
+     * connection.
      */
     public static final int PHY_LE_2M = 2;
 
     /**
-     * Bluetooth LE Coded PHY.
+     * Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning
+     * or connection.
      */
     public static final int PHY_LE_CODED = 3;
 
     /**
-     * Bluetooth LE 1M PHY mask.
+     * Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available
+     * options in a bitmask.
      */
     public static final int PHY_LE_1M_MASK = 1;
 
     /**
-     * Bluetooth LE 2M PHY mask.
+     * Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available
+     * options in a bitmask.
      */
     public static final int PHY_LE_2M_MASK = 2;
 
     /**
-     * Bluetooth LE Coded PHY mask.
+     * Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many
+     * available options in a bitmask.
      */
     public static final int PHY_LE_CODED_MASK = 4;
 
@@ -1679,12 +1687,45 @@
      *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
      * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
      *             {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
-     *             and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if
-     *             {@code autoConnect} is set to true.
-     * @throws IllegalArgumentException if callback is null
+     *             and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect
+     *             if {@code autoConnect} is set to true.
+     * @throws NullPointerException if callback is null
      */
     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
                                      BluetoothGattCallback callback, int transport, int phy) {
+        return connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M_MASK, null);
+    }
+
+    /**
+     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+     * The callback is used to deliver results to Caller, such as connection status as well
+     * as any further GATT client operations.
+     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+     * GATT client operations.
+     * @param callback GATT callback handler that will receive asynchronous callbacks.
+     * @param autoConnect Whether to directly connect to the remote device (false)
+     *                    or to automatically connect as soon as the remote
+     *                    device becomes available (true).
+     * @param transport preferred transport for GATT connections to remote dual-mode devices
+     *             {@link BluetoothDevice#TRANSPORT_AUTO} or
+     *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+     * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
+     *             {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+     *             an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect
+     *             if {@code autoConnect} is set to true.
+     * @param handler The handler to use for the callback. If {@code null}, callbacks will happen
+     *             on the service's main thread.
+     * @throws NullPointerException if callback is null
+     */
+    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+                                     BluetoothGattCallback callback, int transport, int phy,
+                                     Handler handler) {
+        if (callback == null)
+            throw new NullPointerException("callback is null");
+
+        if (handler == null)
+            handler = new Handler(Looper.getMainLooper());
+
         // TODO(Bluetooth) check whether platform support BLE
         //     Do the check here or in GattServer?
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1696,7 +1737,7 @@
                 return null;
             }
             BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, phy);
-            gatt.connect(autoConnect, callback);
+            gatt.connect(autoConnect, callback, handler);
             return gatt;
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return null;
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 9144ae7..7806e31 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.content.Context;
+import android.os.Handler;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.util.Log;
@@ -43,6 +44,7 @@
 
     private IBluetoothGatt mService;
     private BluetoothGattCallback mCallback;
+    private Handler mHandler;
     private int mClientIf;
     private BluetoothDevice mDevice;
     private boolean mAutoConnect;
@@ -154,8 +156,14 @@
                 }
                 mClientIf = clientIf;
                 if (status != GATT_SUCCESS) {
-                    mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
-                                                      BluetoothProfile.STATE_DISCONNECTED);
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
+                                              BluetoothProfile.STATE_DISCONNECTED);
+                        }
+                    });
+
                     synchronized(mStateLock) {
                         mConnState = CONN_STATE_IDLE;
                     }
@@ -181,11 +189,12 @@
                     return;
                 }
 
-                try {
-                    mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
+                    }
+                });
             }
 
             /**
@@ -200,11 +209,12 @@
                     return;
                 }
 
-                try {
-                    mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
+                    }
+                });
             }
 
             /**
@@ -221,11 +231,13 @@
                 }
                 int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
                                                BluetoothProfile.STATE_DISCONNECTED;
-                try {
-                    mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
+                    }
+                });
 
                 synchronized(mStateLock) {
                     if (connected) {
@@ -279,11 +291,12 @@
                     }
                 }
 
-                try {
-                    mCallback.onServicesDiscovered(BluetoothGatt.this, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onServicesDiscovered(BluetoothGatt.this, status);
+                    }
+                });
             }
 
             /**
@@ -328,11 +341,12 @@
 
                 if (status == 0) characteristic.setValue(value);
 
-                try {
-                    mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
+                    }
+                });
             }
 
             /**
@@ -373,11 +387,12 @@
 
                 mAuthRetryState = AUTH_RETRY_STATE_IDLE;
 
-                try {
-                    mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
+                    }
+                });
             }
 
             /**
@@ -398,11 +413,12 @@
 
                 characteristic.setValue(value);
 
-                try {
-                    mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
+                    }
+                });
             }
 
             /**
@@ -442,11 +458,12 @@
 
                 mAuthRetryState = AUTH_RETRY_STATE_IDLE;
 
-                try {
-                    mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
+                    }
+                });
             }
 
             /**
@@ -485,11 +502,12 @@
 
                 mAuthRetryState = AUTH_RETRY_STATE_IDLE;
 
-                try {
-                    mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
+                    }
+                });
             }
 
             /**
@@ -508,11 +526,12 @@
                     mDeviceBusy = false;
                 }
 
-                try {
-                    mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
+                    }
+                });
             }
 
             /**
@@ -526,11 +545,12 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
-                try {
-                    mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
+                    }
+                });
             }
 
             /**
@@ -544,11 +564,13 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
-                try {
-                    mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
+                    }
+                });
             }
 
             /**
@@ -564,12 +586,14 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
-                try {
-                    mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
-                                                  timeout, status);
-                } catch (Exception ex) {
-                    Log.w(TAG, "Unhandled exception in callback", ex);
-                }
+
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
+                                                      timeout, status);
+                    }
+                });
             }
         };
 
@@ -659,11 +683,12 @@
      * @return If true, the callback will be called to notify success or failure,
      *         false on immediate error
      */
-    private boolean registerApp(BluetoothGattCallback callback) {
+    private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
         if (DBG) Log.d(TAG, "registerApp()");
         if (mService == null) return false;
 
         mCallback = callback;
+        mHandler = handler;
         UUID uuid = UUID.randomUUID();
         if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
 
@@ -716,7 +741,8 @@
      *                    device becomes available (true).
      * @return true, if the connection attempt was initiated successfully
      */
-    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
+    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
+                                Handler handler) {
         if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
         synchronized(mStateLock) {
             if (mConnState != CONN_STATE_IDLE) {
@@ -727,7 +753,7 @@
 
         mAutoConnect = autoConnect;
 
-        if (!registerApp(callback)) {
+        if (!registerApp(callback, handler)) {
             synchronized(mStateLock) {
                 mConnState = CONN_STATE_IDLE;
             }
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 11a15c6..c6f82ff 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -30,7 +30,8 @@
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
      * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param status status of the operation
+     * @param status Status of the PHY update operation.
+     *                  {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
      */
     public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
     }
@@ -43,7 +44,8 @@
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
      * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param status status of the operation
+     * @param status Status of the PHY read operation.
+     *                  {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
      */
     public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
     }
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 3b8f962..02307bd 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -167,7 +167,8 @@
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
      * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param status status of the operation
+     * @param status Status of the PHY update operation.
+     *                  {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
      */
     public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
     }
@@ -180,7 +181,8 @@
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
      * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
      *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param status status of the operation
+     * @param status Status of the PHY read operation.
+     *                  {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
      */
     public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
     }
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 87a2b05..9ce2a5b 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -33,4 +33,20 @@
      * @hide
      */
     public abstract boolean satisfiedBy(NetworkSpecifier other);
+
+    /**
+     * Optional method which can be overriden by concrete implementations of NetworkSpecifier to
+     * check a self-reported UID. A concrete implementation may contain a UID which would be self-
+     * reported by the caller (since NetworkSpecifier implementations should be non-mutable). This
+     * function is called by ConnectivityService and is passed the actual UID of the caller -
+     * allowing the verification of the self-reported UID. In cases of mismatch the implementation
+     * should throw a SecurityException.
+     *
+     * @param requestorUid The UID of the requestor as obtained from its binder.
+     *
+     * @hide
+     */
+    public void assertValidFromUid(int requestorUid) {
+        // empty
+    }
 }
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 1e54163..e48a0d0 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -107,15 +107,7 @@
 
     /**
      * Broadcast intent to inform a new visual voicemail SMS has been received. This intent will
-     * only be delivered to the voicemail client. The intent will have the following extra values:
-     *
-     * <ul>
-     *   <li><em>{@link #EXTRA_VOICEMAIL_SMS_TYPE}</em> - (String) The event type of the SMS. Common
-     *   values are "SYNC" or "STATUS"</li>
-     *   <li><em>{@link #EXTRA_VOICEMAIL_SMS_DATA}</em> - (Bundle) The fields sent by the SMS</li>
-     *   <li><em>{@link #EXTRA_VOICEMAIL_SMS_SUBID}</em> - (Integer) The subscription ID of the
-     *   phone account that received the SMS</li>
-     * </ul>
+     * only be delivered to the telephony service. {@link #EXTRA_VOICEMAIL_SMS} will be included.
      */
     /** @hide */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -123,42 +115,11 @@
             "android.intent.action.VOICEMAIL_SMS_RECEIVED";
 
     /**
-     * Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to
-     * indicate the event type of the SMS. Common values are "SYNC" or "STATUS". The extra will not
-     * exist if the framework cannot parse the SMS as voicemail but the carrier pattern indicates
-     * it is.
-     */
-    /** @hide */
-    public static final String EXTRA_VOICEMAIL_SMS_PREFIX =
-            "com.android.voicemail.extra.VOICEMAIL_SMS_PREFIX";
-
-    /**
-     * Optional extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to
-     * indicate the fields sent by the SMS. The extra will not exist if the framework cannot
-     * parse the SMS as voicemail but the carrier pattern indicates it is.
-     */
-    /** @hide */
-    public static final String EXTRA_VOICEMAIL_SMS_FIELDS =
-            "com.android.voicemail.extra.VOICEMAIL_SMS_FIELDS";
-
-    /**
-     * Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate the
-     * message body of the SMS. This extra is included if the framework cannot
-     * parse the SMS as voicemail but the carrier pattern indicates it is.
-     */
-    /**
+     * Extra in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} indicating the content of the SMS.
+     *
      * @hide
      */
-    public static final String EXTRA_VOICEMAIL_SMS_MESSAGE_BODY =
-        "com.android.voicemail.extra.VOICEMAIL_SMS_MESSAGE_BODY";
-
-    /**
-     * Extra included in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} broadcast intents to indicate he
-     * subscription ID of the phone account that received the SMS.
-     */
-    /** @hide */
-    public static final String EXTRA_VOICEMAIL_SMS_SUBID =
-            "com.android.voicemail.extra.VOICEMAIL_SMS_SUBID";
+    public static final String EXTRA_VOICEMAIL_SMS = "android.provider.extra.VOICEMAIL_SMS";
 
     /**
      * Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9e7bf27..f5f67d06 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1560,6 +1560,14 @@
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Must be required by a link {@link android.telephony.VisualVoicemailService} to ensure that
+         only the system can bind to it.
+         <p>Protection level: signature|privileged
+    -->
+    <permission
+      android:name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"
+      android:protectionLevel="signature|privileged"/>
+
     <!-- Must be required by a {@link android.telecom.CallScreeningService},
          to ensure that only the system can bind to it.
          <p>Protection level: signature|privileged
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 616a8c0..88bc54d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -49,7 +49,6 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.PacketKeepalive;
@@ -70,6 +69,7 @@
 import android.net.NetworkMisc;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
 import android.net.NetworkState;
 import android.net.NetworkUtils;
 import android.net.Proxy;
@@ -110,7 +110,6 @@
 import android.util.LocalLog;
 import android.util.LocalLog.ReadOnlyLocalLog;
 import android.util.Log;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -4131,6 +4130,18 @@
                 0, 0, thresholds);
     }
 
+    private void ensureValidNetworkSpecifier(NetworkCapabilities nc) {
+        if (nc == null) {
+            return;
+        }
+        NetworkSpecifier ns = nc.getNetworkSpecifier();
+        if (ns == null) {
+            return;
+        }
+        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns);
+        ns.assertValidFromUid(Binder.getCallingUid());
+    }
+
     @Override
     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
             Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
@@ -4156,9 +4167,7 @@
         if (timeoutMs < 0) {
             throw new IllegalArgumentException("Bad timeout specified");
         }
-
-        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
-                networkCapabilities.getNetworkSpecifier());
+        ensureValidNetworkSpecifier(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
                 nextNetworkRequestId(), type);
@@ -4230,9 +4239,7 @@
         enforceNetworkRequestPermissions(networkCapabilities);
         enforceMeteredApnPolicy(networkCapabilities);
         ensureRequestableCapabilities(networkCapabilities);
-
-        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
-                networkCapabilities.getNetworkSpecifier());
+        ensureValidNetworkSpecifier(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
@@ -4294,9 +4301,7 @@
             // can't request networks.
             nc.addCapability(NET_CAPABILITY_FOREGROUND);
         }
-
-        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
-                networkCapabilities.getNetworkSpecifier());
+        ensureValidNetworkSpecifier(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
@@ -4314,9 +4319,7 @@
         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
             enforceAccessPermission();
         }
-
-        MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
-                networkCapabilities.getNetworkSpecifier());
+        ensureValidNetworkSpecifier(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(
                 new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(),
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5ae4d67..c5fc038 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5324,35 +5324,61 @@
         return tracesFile;
     }
 
+    public static class DumpStackFileObserver extends FileObserver {
+        // Keep in sync with frameworks/native/cmds/dumpstate/utils.cpp
+        private static final int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
+        static final int TRACE_DUMP_TIMEOUT_SECONDS = TRACE_DUMP_TIMEOUT_MS / 1000;
+
+        private final String mTracesPath;
+        private boolean mClosed;
+
+        public DumpStackFileObserver(String tracesPath) {
+            super(tracesPath, FileObserver.CLOSE_WRITE);
+            mTracesPath = tracesPath;
+        }
+
+        @Override
+        public synchronized void onEvent(int event, String path) {
+            mClosed = true;
+            notify();
+        }
+
+        public void dumpWithTimeout(int pid) {
+            Process.sendSignal(pid, Process.SIGNAL_QUIT);
+            synchronized (this) {
+                try {
+                    wait(TRACE_DUMP_TIMEOUT_MS); // Wait for traces file to be closed.
+                } catch (InterruptedException e) {
+                    Slog.wtf(TAG, e);
+                }
+            }
+            if (!mClosed) {
+                Slog.w(TAG, "Didn't see close of " + mTracesPath + " for pid " + pid +
+                       ". Attempting native stack collection.");
+                Debug.dumpNativeBacktraceToFileTimeout(pid, mTracesPath, TRACE_DUMP_TIMEOUT_SECONDS);
+            }
+            mClosed = false;
+        }
+    }
+
     private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
             ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, String[] nativeProcs) {
         // Use a FileObserver to detect when traces finish writing.
         // The order of traces is considered important to maintain for legibility.
-        FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
-            @Override
-            public synchronized void onEvent(int event, String path) { notify(); }
-        };
-
+        DumpStackFileObserver observer = new DumpStackFileObserver(tracesPath);
         try {
             observer.startWatching();
 
             // First collect all of the stacks of the most important pids.
             if (firstPids != null) {
-                try {
-                    int num = firstPids.size();
-                    for (int i = 0; i < num; i++) {
-                        synchronized (observer) {
-                            if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid "
-                                    + firstPids.get(i));
-                            final long sime = SystemClock.elapsedRealtime();
-                            Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
-                            observer.wait(1000);  // Wait for write-close, give up after 1 sec
-                            if (DEBUG_ANR) Slog.d(TAG, "Done with pid " + firstPids.get(i)
-                                    + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
-                        }
-                    }
-                } catch (InterruptedException e) {
-                    Slog.wtf(TAG, e);
+                int num = firstPids.size();
+                for (int i = 0; i < num; i++) {
+                    if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid "
+                            + firstPids.get(i));
+                    final long sime = SystemClock.elapsedRealtime();
+                    observer.dumpWithTimeout(firstPids.get(i));
+                    if (DEBUG_ANR) Slog.d(TAG, "Done with pid " + firstPids.get(i)
+                            + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
                 }
             }
 
@@ -5364,7 +5390,8 @@
                         if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
                         final long sime = SystemClock.elapsedRealtime();
 
-                        Debug.dumpNativeBacktraceToFileTimeout(pid, tracesPath, 10);
+                        Debug.dumpNativeBacktraceToFileTimeout(
+                                pid, tracesPath, DumpStackFileObserver.TRACE_DUMP_TIMEOUT_SECONDS);
                         if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
                                 + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
                     }
@@ -5391,19 +5418,12 @@
                     ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i);
                     if (lastPids.indexOfKey(stats.pid) >= 0) {
                         numProcs++;
-                        try {
-                            synchronized (observer) {
-                                if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid "
-                                        + stats.pid);
-                                final long stime = SystemClock.elapsedRealtime();
-                                Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
-                                observer.wait(1000);  // Wait for write-close, give up after 1 sec
-                                if (DEBUG_ANR) Slog.d(TAG, "Done with extra pid " + stats.pid
-                                        + " in " + (SystemClock.elapsedRealtime()-stime) + "ms");
-                            }
-                        } catch (InterruptedException e) {
-                            Slog.wtf(TAG, e);
-                        }
+                        if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid "
+                                + stats.pid);
+                        final long stime = SystemClock.elapsedRealtime();
+                        observer.dumpWithTimeout(stats.pid);
+                        if (DEBUG_ANR) Slog.d(TAG, "Done with extra pid " + stats.pid
+                                + " in " + (SystemClock.elapsedRealtime()-stime) + "ms");
                     } else if (DEBUG_ANR) {
                         Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
                                 + stats.pid);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index cc41060..f97a672 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -866,7 +866,7 @@
             final int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             try {
-                if (uid != Process.BLUETOOTH_UID) {
+                if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) {
                     throw new SecurityException("Only Bluetooth service processes can set"
                             + " Callback");
                 }
diff --git a/telephony/java/android/telephony/MbmsDownloadManager.java b/telephony/java/android/telephony/MbmsDownloadManager.java
index ad61d02..bb4bf1e 100644
--- a/telephony/java/android/telephony/MbmsDownloadManager.java
+++ b/telephony/java/android/telephony/MbmsDownloadManager.java
@@ -35,35 +35,29 @@
     private int mSubId = INVALID_SUBSCRIPTION_ID;
 
     /**
-     * should use createManager to create/initialize a copy
+     * Create a new MbmsDownloadManager using the system default data subscription ID.
+     *
+     * Note that this call will bind a remote service and that may take a bit.  This
+     * may throw an Illegal ArgumentException or RemoteException.
+     *
      * @hide
      */
-    public MbmsDownloadManager(Context context) {
+    public MbmsDownloadManager(Context context, IMbmsDownloadManagerListener listener,
+            String downloadAppName) {
         mContext = context;
     }
 
-    public static MbmsDownloadManager createManager(Context context,
-            IMbmsDownloadManagerListener listener, String downloadAppName) {
-//        MbmsDownloadManager mdm = context.getSystemService(Context.MBMS_DOWNLOAD_SERVICE);
-//        if (mdm == null) return mdm;
-//        mdm.initialize(listener, downloadAppName,
-//                SubscriptionManager.getDefaultSubscriptionId());
-//        return mdm;
-        return null;
-    }
-
-    public static MbmsDownloadManager createManager(Context context,
-            IMbmsDownloadManagerListener listener, String downloadAppName, int subId) {
-//        MbmsDownloadManager mdm = context.getSystemService(Context.MBMS_DOWNLOAD_SERVICE);
-//        if (mdm == null) return mdm;
-//        mdm.initialize(listener, downloadAppName, subId);
-//        return mdm;
-        return null;
-    }
-
-    private void initialize(IMbmsDownloadManagerListener listener, String downloadAppName,
-            int subId) {
-        // assert all empty and set
+    /**
+     * Create a new MbmsDownloadManager using the given subscription ID.
+     *
+     * Note that this call will bind a remote service and that may take a bit.  This
+     * may throw an Illegal ArgumentException or RemoteException.
+     *
+     * @hide
+     */
+    public MbmsDownloadManager(Context context, IMbmsDownloadManagerListener listener,
+            String downloadAppName, int subId) {
+        mContext = context;
     }
 
     /**
@@ -71,6 +65,19 @@
      * They may occur at times far in the future.
      * servicesClasses lets the app filter on types of files and is opaque data between
      *     the app and the carrier
+     *
+     * Multiple calls replace trhe list of serviceClasses of interest.
+     *
+     * May throw an IllegalArgumentException or RemoteException.
+     *
+     * Synchronous responses include
+     * <li>SUCCESS</li>
+     * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
+     *
+     * Asynchronous errors through the listener include any of the errors except
+     * <li>ERROR_MSDC_UNABLE_TO_)START_SERVICE</li>
+     * <li>ERROR_MSDC_INVALID_SERVICE_ID</li>
+     * <li>ERROR_MSDC_END_OF_SESSION</li>
      */
     public int getFileServices(List<String> serviceClasses) {
         return 0;
@@ -106,15 +113,39 @@
      *     of a currently occuring download.  Note this can only run while the calling app
      *     is running, so future downloads will simply result in resultIntents being sent
      *     for completed or errored-out downloads.  A NULL indicates no callbacks are needed.
+     *
+     * May throw an IllegalArgumentException or RemoteExcpetion.
+     *
+     * Asynchronous errors through the listener include any of the errors
      */
     public DownloadRequest download(DownloadRequest downloadRequest, DownloadListener listener) {
         return null;
     }
 
+    /**
+     * Returns a list DownloadRequests that originated from this application (UID).
+     *
+     * May throw a RemoteException.
+     *
+     * Asynchronous errors through the listener include any of the errors except
+     * <li>ERROR_UNABLED_TO_START_SERVICE</li>
+     * <li>ERROR_MSDC_INVALID_SERVICE_ID</li>
+     * <li>ERROR_MSDC_END_OF_SESSION</li>
+     */
     public List<DownloadRequest> listPendingDownloads() {
         return null;
     }
 
+    /**
+     * Attempts to cancel the specified DownloadRequest.
+     *
+     * May throw a RemoteException.
+     *
+     * Synchronous responses may include
+     * <li>SUCCESS</li>
+     * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
+     * <li>ERROR_MSDC_UNKNOWN_REQUEST</li>
+     */
     public int cancelDownload(DownloadRequest downloadRequest) {
         return 0;
     }
@@ -127,6 +158,10 @@
      * Future downloads include counts of files with pending repair operations, counts of
      * files with future downloads and indication of scheduled download times with unknown
      * file details.
+     *
+     * May throw an IllegalArgumentException or RemoteException.
+     *
+     * If the DownloadRequest is unknown the results will be null.
      */
     public DownloadStatus getDownloadStatus(DownloadRequest downloadRequest) {
         return null;
@@ -140,8 +175,15 @@
      * content, even if that content has since been deleted.  If this function is called
      * repeated content will be downloaded again when available.  This does not interrupt
      * in-progress downloads.
+     *
+     * May throw an IllegalArgumentException or RemoteException.
+     *
+     * <li>SUCCESS</li>
+     * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
+     * <li>ERROR_MSDC_UNKNOWN_REQUEST</li>
      */
-    public void resetDownloadKnowledge(DownloadRequest downloadRequest) {
+    public int resetDownloadKnowledge(DownloadRequest downloadRequest) {
+        return 0;
     }
 
     public void dispose() {
diff --git a/telephony/java/android/telephony/MbmsStreamingManager.java b/telephony/java/android/telephony/MbmsStreamingManager.java
index 0bcde2f..9a2ba6d 100644
--- a/telephony/java/android/telephony/MbmsStreamingManager.java
+++ b/telephony/java/android/telephony/MbmsStreamingManager.java
@@ -39,7 +39,7 @@
      * Create a new MbmsStreamingManager using the system default data subscription ID.
      *
      * Note that this call will bind a remote service and that may take a bit.  This
-     * may throw an IllegalArgumentException.
+     * may throw an IllegalArgumentException or RemoteException.
      */
     public MbmsStreamingManager(Context context, IMbmsStreamingManagerListener listener,
             String streamingAppName) {
@@ -47,10 +47,10 @@
     }
 
     /**
-     * Create a new MbmsStreamingManager using the give subscription ID.
+     * Create a new MbmsStreamingManager using the given subscription ID.
      *
      * Note that this call will bind a remote service and that may take a bit.  This
-     * may throw an IllegalArgumentException.
+     * may throw an IllegalArgumentException or RemoteException.
      */
     public MbmsStreamingManager(Context context, IMbmsStreamingManagerListener listener,
                     String streamingAppName, int subId) {
@@ -72,10 +72,17 @@
      * the app and the carrier.
      *
      * Multiple calls replace the list of serviceClasses of interest.
-     * The return value is a success/error-code with the following possible values:
+     *
+     * May throw an IllegalArgumentException or RemoteException.
+     *
+     * Synchronous responses include
      * <li>SUCCESS</li>
-     * <li>NO_MIDDLEWARE</li>
-     * <li>QUEUE_LIMIT</li>
+     * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
+     *
+     * Asynchronous errors through the listener include any of the errors except
+     * <li>ERROR_MSDC_UNABLE_TO_)START_SERVICE</li>
+     * <li>ERROR_MSDC_INVALID_SERVICE_ID</li>
+     * <li>ERROR_MSDC_END_OF_SESSION</li>
      */
     public int getStreamingServices(List<String> classList) {
         return 0;
@@ -85,6 +92,9 @@
      * Starts streaming a requested service, reporting status to the indicated listener.
      * Returns an object used to control that stream.
      *
+     * May throw an IllegalArgumentException or RemoteException.
+     *
+     * Asynchronous errors through the listener include any of the errors
      */
     public StreamingService startStreaming(StreamingServiceInfo serviceInfo,
             IStreamingServiceListener listener) {
@@ -96,10 +106,17 @@
      * on this given subId.  Results are returned asynchronously through the previously
      * registered callback.
      *
+     * May throw a RemoteException.
+     *
      * The return value is a success/error-code with the following possible values:
      * <li>SUCCESS</li>
-     * <li>NO_MIDDLEWARE</li>
-     * <li>QUEU_LIMIT</li>
+     * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
+     *
+     * Asynchronous errors through the listener include any of the errors except
+     * <li>ERROR_UNABLED_TO_START_SERVICE</li>
+     * <li>ERROR_MSDC_INVALID_SERVICE_ID</li>
+     * <li>ERROR_MSDC_END_OF_SESSION</li>
+     *
      */
     public int getActiveStreamingServices() {
         return 0;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1d860d1..5a848d9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -25,12 +25,14 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.ActivityThread;
+import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.Uri;
 import android.os.BatteryStats;
+import android.os.Binder;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.os.Bundle;
@@ -65,6 +67,7 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -2785,18 +2788,17 @@
 
     /**
      * @returns the settings of the visual voicemail SMS filter for a phone account set by the
-     * package, or {@code null} if the filter is disabled.
+     * current active visual voicemail client, or {@code null} if the filter is disabled.
      *
      * <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission.
      */
     /** @hide */
     @Nullable
-    public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(String packageName,
-            int subId) {
+    public VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getSystemVisualVoicemailSmsFilterSettings(packageName, subId);
+                return telephony.getActiveVisualVoicemailSmsFilterSettings(subId);
             }
         } catch (RemoteException ex) {
         } catch (NullPointerException ex) {
@@ -2806,6 +2808,35 @@
     }
 
     /**
+     * Send a visual voicemail SMS. The IPC caller must be the current default dialer.
+     *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#SEND_SMS SEND_SMS}
+     *
+     * @param phoneAccountHandle The account to send the SMS with.
+     * @param number The destination number.
+     * @param port The destination port for data SMS, or 0 for text SMS.
+     * @param text The message content. For data sms, it will be encoded as a UTF-8 byte stream.
+     * @param sentIntent The sent intent passed to the {@link SmsManager}
+     *
+     * @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent)
+     * @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent)
+     *
+     * @hide
+     */
+    public void sendVisualVoicemailSmsForSubscriber(int subId, String number, int port,
+            String text, PendingIntent sentIntent) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.sendVisualVoicemailSmsForSubscriber(
+                        mContext.getOpPackageName(), subId, number, port, text, sentIntent);
+            }
+        } catch (RemoteException ex) {
+        }
+    }
+
+    /**
      * Initial SIM activation state, unknown. Not set by any carrier apps.
      * @hide
      */
@@ -5006,32 +5037,46 @@
 
     /* <p>Requires permission:
      * @link android.Manifest.permission#CALL_PHONE}
+     * @param ussdRequest the USSD command to be executed.
+     * @param wrappedCallback receives a callback result.
      */
     @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public void sendUssdRequest(String ussdRequest,
                                 final OnReceiveUssdResponseCallback callback, Handler handler) {
-       checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
+        sendUssdRequest(ussdRequest, getSubId(), callback, handler);
+    }
 
-       ResultReceiver wrappedCallback = new ResultReceiver(handler) {
-           @Override
-           protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
-              Rlog.d(TAG, "USSD:" + resultCode);
-              checkNotNull(ussdResponse, "ussdResponse cannot be null.");
-              UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
+   /* <p>Requires permission:
+    * @link android.Manifest.permission#CALL_PHONE}
+    * @param subId The subscription to use.
+    * @param ussdRequest the USSD command to be executed.
+    * @param wrappedCallback receives a callback result.
+    */
+    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
+    public void sendUssdRequest(String ussdRequest, int subId,
+                                final OnReceiveUssdResponseCallback callback, Handler handler) {
+        checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
 
-              if (resultCode == USSD_RETURN_SUCCESS) {
-                 callback.onReceiveUssdResponse(response.getUssdRequest(),
-                         response.getReturnMessage());
-              } else {
-                 callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
-              }
-           }
+        ResultReceiver wrappedCallback = new ResultReceiver(handler) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
+                Rlog.d(TAG, "USSD:" + resultCode);
+                checkNotNull(ussdResponse, "ussdResponse cannot be null.");
+                UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
+
+                if (resultCode == USSD_RETURN_SUCCESS) {
+                    callback.onReceiveUssdResponse(response.getUssdRequest(),
+                            response.getReturnMessage());
+                } else {
+                    callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
+                }
+            }
         };
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.handleUssdRequest(ussdRequest, wrappedCallback);
+                telephony.handleUssdRequest(subId, ussdRequest, wrappedCallback);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#sendUSSDCode", e);
@@ -5042,6 +5087,20 @@
         }
     }
 
+   /*
+    * @return true, if the device is currently on a technology (e.g. UMTS or LTE) which can support
+    * voice and data simultaneously. This can change based on location or network condition.
+    */
+    public boolean isConcurrentVoiceAndDataAllowed() {
+        try {
+            ITelephony telephony = getITelephony();
+            return (telephony == null ? false : telephony.isConcurrentVoiceAndDataAllowed(mSubId));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#isConcurrentVoiceAndDataAllowed", e);
+        }
+        return false;
+    }
+
     /** @hide */
     @SystemApi
     public boolean handlePinMmi(String dialString) {
diff --git a/telephony/java/android/telephony/VisualVoicemailService.java b/telephony/java/android/telephony/VisualVoicemailService.java
new file mode 100644
index 0000000..84833e3
--- /dev/null
+++ b/telephony/java/android/telephony/VisualVoicemailService.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.MainThread;
+import android.annotation.SdkConstant;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.util.Log;
+
+/**
+ * This service is implemented by dialer apps that wishes to handle OMTP or similar visual
+ * voicemails. Telephony binds to this service when the cell service is first connected, a visual
+ * voicemail SMS has been received, or when a SIM has been removed. Telephony will only bind to the
+ * default dialer for such events (See {@link TelecomManager#getDefaultDialerPackage()}). The
+ * {@link android.service.carrier.CarrierMessagingService} precedes the VisualVoicemailService in
+ * the SMS filtering chain and may intercept the visual voicemail SMS before it reaches this
+ * service.
+ * <p>
+ * Below is an example manifest registration for a {@code VisualVoicemailService}.
+ * <pre>
+ * {@code
+ * <service android:name="your.package.YourVisualVoicemailServiceImplementation"
+ *          android:permission="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE">
+ *      <intent-filter>
+ *          <action android:name="android.telephony.VisualVoicemailService"/>
+ *      </intent-filter>
+ * </service>
+ * }
+ * </pre>
+ */
+public abstract class VisualVoicemailService extends Service {
+
+    private static final String TAG = "VvmService";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.telephony.VisualVoicemailService";
+
+    /**
+     * @hide
+     */
+    public static final int MSG_ON_CELL_SERVICE_CONNECTED = 1;
+    /**
+     * @hide
+     */
+    public static final int MSG_ON_SMS_RECEIVED = 2;
+    /**
+     * @hide
+     */
+    public static final int MSG_ON_SIM_REMOVED = 3;
+    /**
+     * @hide
+     */
+    public static final int MSG_TASK_ENDED = 4;
+    /**
+     * @hide
+     */
+    public static final int MSG_TASK_STOPPED = 5;
+
+    /**
+     * @hide
+     */
+    public static final String DATA_PHONE_ACCOUNT_HANDLE = "data_phone_account_handle";
+    /**
+     * @hide
+     */
+    public static final String DATA_SMS = "data_sms";
+
+    /**
+     * Represents a visual voicemail event which needs to be handled. While the task is being
+     * processed telephony will hold a wakelock for the VisualVoicemailService. The service can
+     * unblock the main thread and pass the task to a worker thread. Once the task is finished,
+     * {@link VisualVoicemailTask#finish()} should be called to signal telephony to release the
+     * resources. Telephony will call {@link VisualVoicemailService#onStopped(VisualVoicemailTask)}
+     * when the task is going to be terminated before completion.
+     *
+     * @see #onCellServiceConnected(VisualVoicemailTask, PhoneAccountHandle)
+     * @see #onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)
+     * @see #onSimRemoved(VisualVoicemailTask, PhoneAccountHandle)
+     * @see #onStopped(VisualVoicemailTask)
+     */
+    public static class VisualVoicemailTask {
+
+        private final int mTaskId;
+        private final Messenger mReplyTo;
+
+        private VisualVoicemailTask(Messenger replyTo, int taskId) {
+            mTaskId = taskId;
+            mReplyTo = replyTo;
+        }
+
+        /**
+         * Call to signal telephony the task has completed. Must be called for every task.
+         */
+        public final void finish() {
+            Message message = Message.obtain();
+            try {
+                message.what = MSG_TASK_ENDED;
+                message.arg1 = mTaskId;
+                mReplyTo.send(message);
+            } catch (RemoteException e) {
+                Log.e(TAG,
+                        "Cannot send MSG_TASK_ENDED, remote handler no longer exist");
+            }
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof VisualVoicemailTask)) {
+                return false;
+            }
+            return mTaskId == ((VisualVoicemailTask) obj).mTaskId;
+        }
+
+        @Override
+        public int hashCode() {
+            return mTaskId;
+        }
+    }
+
+    /**
+     * Handles messages sent by telephony.
+     */
+    private final Messenger mMessenger = new Messenger(new Handler() {
+        @Override
+        public void handleMessage(final Message msg) {
+            final PhoneAccountHandle handle = msg.getData()
+                    .getParcelable(DATA_PHONE_ACCOUNT_HANDLE);
+            VisualVoicemailTask task = new VisualVoicemailTask(msg.replyTo, msg.arg1);
+            switch (msg.what) {
+                case MSG_ON_CELL_SERVICE_CONNECTED:
+                    onCellServiceConnected(task, handle);
+                    break;
+                case MSG_ON_SMS_RECEIVED:
+                    VisualVoicemailSms sms = msg.getData().getParcelable(DATA_SMS);
+                    onSmsReceived(task, sms);
+                    break;
+                case MSG_ON_SIM_REMOVED:
+                    onSimRemoved(task, handle);
+                    break;
+                case MSG_TASK_STOPPED:
+                    onStopped(task);
+                    break;
+                default:
+                    super.handleMessage(msg);
+                    break;
+            }
+        }
+    });
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mMessenger.getBinder();
+    }
+
+    /**
+     * Called when the cellular service is connected on a {@link PhoneAccountHandle} for the first
+     * time, or when the carrier config has changed. It will not be called when the signal is lost
+     * then restored.
+     *
+     * @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be
+     * called when the task is completed.
+     * @param phoneAccountHandle The {@link PhoneAccountHandle} triggering this event.
+     */
+    @MainThread
+    public abstract void onCellServiceConnected(VisualVoicemailTask task,
+                                                PhoneAccountHandle phoneAccountHandle);
+
+    /**
+     * Called when a SMS matching the {@link VisualVoicemailSmsFilterSettings} set by
+     * {@link #setSmsFilterSettings(Context, PhoneAccountHandle, VisualVoicemailSmsFilterSettings)}
+     * is received.
+     *
+     * @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be
+     * called when the task is completed.
+     * @param sms The content of the received SMS.
+     */
+    @MainThread
+    public abstract void onSmsReceived(VisualVoicemailTask task,
+                                       VisualVoicemailSms sms);
+
+    /**
+     * Called when a SIM is removed.
+     *
+     * @param task The task representing this event. {@link VisualVoicemailTask#finish()} must be
+     * called when the task is completed.
+     * @param phoneAccountHandle The {@link PhoneAccountHandle} triggering this event.
+     */
+    @MainThread
+    public abstract void onSimRemoved(VisualVoicemailTask task,
+                                      PhoneAccountHandle phoneAccountHandle);
+
+    /**
+     * Called before the system is about to terminate a task. The service should persist any
+     * necessary data and call finish on the task immediately.
+     */
+    @MainThread
+    public abstract void onStopped(VisualVoicemailTask task);
+
+    /**
+     * Set the visual voicemail SMS filter settings for the VisualVoicemailService.
+     * {@link #onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)} will be called when
+     * a SMS matching the settings is received. The caller should have
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} and implements a
+     * VisualVoicemailService.
+     * <p>
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     *
+     * @param phoneAccountHandle The account to apply the settings to.
+     * @param settings The settings for the filter, or {@code null} to disable the filter.
+     */
+    public final static void setSmsFilterSettings(Context context,
+            PhoneAccountHandle phoneAccountHandle,
+            VisualVoicemailSmsFilterSettings settings) {
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        int subId = getSubId(context, phoneAccountHandle);
+        if (settings == null) {
+            telephonyManager.disableVisualVoicemailSmsFilter(subId);
+        } else {
+            telephonyManager.enableVisualVoicemailSmsFilter(subId, settings);
+        }
+    }
+
+    /**
+     * Send a visual voicemail SMS. The caller must be the current default dialer.
+     * <p>
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#SEND_SMS SEND_SMS}
+     *
+     * @param phoneAccountHandle The account to send the SMS with.
+     * @param number The destination number.
+     * @param port The destination port for data SMS, or 0 for text SMS.
+     * @param text The message content. For data sms, it will be encoded as a UTF-8 byte stream.
+     * @param sentIntent The sent intent passed to the {@link SmsManager}
+     * @see SmsManager#sendDataMessage(String, String, short, byte[], PendingIntent, PendingIntent)
+     * @see SmsManager#sendTextMessage(String, String, String, PendingIntent, PendingIntent)
+     */
+    public final static void sendVisualVoicemailSms(Context context,
+            PhoneAccountHandle phoneAccountHandle, String number,
+            short port, String text, PendingIntent sentIntent) {
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        telephonyManager.sendVisualVoicemailSmsForSubscriber(getSubId(context, phoneAccountHandle),
+                number, port, text, sentIntent);
+    }
+
+    private static int getSubId(Context context, PhoneAccountHandle phoneAccountHandle) {
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+        return telephonyManager
+                .getSubIdForPhoneAccount(telecomManager.getPhoneAccount(phoneAccountHandle));
+    }
+
+}
diff --git a/telephony/java/android/telephony/VisualVoicemailSms.java b/telephony/java/android/telephony/VisualVoicemailSms.java
new file mode 100644
index 0000000..6235c10
--- /dev/null
+++ b/telephony/java/android/telephony/VisualVoicemailSms.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+
+/**
+ * Represents the content of a visual voicemail SMS. If a incoming SMS matches the {@link
+ * VisualVoicemailSmsFilterSettings} set by the default dialer, {@link
+ * VisualVoicemailService#onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)} will be called.
+ */
+public final class VisualVoicemailSms implements Parcelable {
+
+    private final PhoneAccountHandle mPhoneAccountHandle;
+    @Nullable
+    private final String mPrefix;
+
+    @Nullable
+    private final Bundle mFields;
+
+    private final String mMessageBody;
+
+    VisualVoicemailSms(Builder builder) {
+        mPhoneAccountHandle = builder.mPhoneAccountHandle;
+        mPrefix = builder.mPrefix;
+        mFields = builder.mFields;
+        mMessageBody = builder.mMessageBody;
+    }
+
+    /**
+     * The {@link PhoneAccountHandle} that received the SMS.
+     */
+    public PhoneAccountHandle getPhoneAccountHandle() {
+        return mPhoneAccountHandle;
+    }
+
+    /**
+     * The event type of the SMS or {@code null} if the framework cannot parse the SMS as voicemail
+     * but the carrier pattern indicates it is. Common values are "SYNC" or "STATUS".
+     */
+    public String getPrefix() {
+        return mPrefix;
+    }
+
+    /**
+     * The key-value pairs sent by the SMS, or {@code null} if the framework cannot parse the SMS as
+     * voicemail but the carrier pattern indicates it is.
+     */
+    public Bundle getFields() {
+        return mFields;
+    }
+
+    /**
+     * Raw message body of the received SMS.
+     */
+    public String getMessageBody() {
+        return mMessageBody;
+    }
+
+    /**
+     * Builder for the {@link VisualVoicemailSms}. Internal use only.
+     *
+     * @hide
+     */
+    public static class Builder {
+
+        private PhoneAccountHandle mPhoneAccountHandle;
+        private String mPrefix;
+        private Bundle mFields;
+        private String mMessageBody;
+
+        public VisualVoicemailSms build() {
+            return new VisualVoicemailSms(this);
+        }
+
+        public Builder setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
+            this.mPhoneAccountHandle = phoneAccountHandle;
+            return this;
+        }
+
+        public Builder setPrefix(String prefix) {
+            this.mPrefix = prefix;
+            return this;
+        }
+
+        public Builder setFields(Bundle fields) {
+            this.mFields = fields;
+            return this;
+        }
+
+        public Builder setMessageBody(String messageBody) {
+            this.mMessageBody = messageBody;
+            return this;
+        }
+
+    }
+
+
+    public static final Creator<VisualVoicemailSms> CREATOR =
+            new Creator<VisualVoicemailSms>() {
+                @Override
+                public VisualVoicemailSms createFromParcel(Parcel in) {
+                    return new Builder()
+                            .setPhoneAccountHandle((PhoneAccountHandle) in.readParcelable(null))
+                            .setPrefix(in.readString())
+                            .setFields(in.readBundle())
+                            .setMessageBody(in.readString())
+                            .build();
+                }
+
+                @Override
+                public VisualVoicemailSms[] newArray(int size) {
+                    return new VisualVoicemailSms[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(getPhoneAccountHandle(), flags);
+        dest.writeString(getPrefix());
+        dest.writeBundle(getFields());
+        dest.writeString(getMessageBody());
+    }
+}
diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
index 5b81027..9d19d08 100644
--- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
+++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
@@ -15,9 +15,13 @@
  */
 package android.telephony;
 
+import android.content.Context;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import android.telecom.PhoneAccountHandle;
+import android.telephony.VisualVoicemailService.VisualVoicemailTask;
 import java.util.Collections;
 import java.util.List;
 
@@ -28,31 +32,26 @@
  * <p>[clientPrefix]:[prefix]:([key]=[value];)*
  *
  * <p>will be regarded as a visual voicemail SMS, and removed before reaching the SMS provider. The
- * intent {@link android.provider.VoicemailContract#ACTION_VOICEMAIL_SMS_RECEIVED} will then be sent
- * to the default dialer with the information extracted from the SMS.
+ * {@link VisualVoicemailService} in the current default dialer will be bound and
+ * {@link VisualVoicemailService#onSmsReceived(VisualVoicemailTask, VisualVoicemailSms)}
+ * will called with the information extracted from the SMS.
  *
  * <p>Use {@link android.telephony.VisualVoicemailSmsFilterSettings.Builder} to construct this
  * class.
  *
- * @see android.telephony.TelephonyManager#enableVisualVoicemailSmsFilter
- *
- * @hide
+ * @see VisualVoicemailService#setSmsFilterSettings(Context, PhoneAccountHandle, VisualVoicemailSmsFilterSettings)
  */
-public class VisualVoicemailSmsFilterSettings implements Parcelable {
+public final class VisualVoicemailSmsFilterSettings implements Parcelable {
 
 
     /**
      * The visual voicemail SMS message does not have to be a data SMS, and can be directed to any
      * port.
-     *
-     * @hide
      */
     public static final int DESTINATION_PORT_ANY = -1;
 
     /**
      * The visual voicemail SMS message can be directed to any port, but must be a data SMS.
-     *
-     * @hide
      */
     public static final int DESTINATION_PORT_DATA_SMS = -2;
 
@@ -62,8 +61,6 @@
 
     /**
      * Builder class for {@link VisualVoicemailSmsFilterSettings} objects.
-     *
-     * @hide
      */
     public static class Builder {
 
@@ -171,4 +168,13 @@
         dest.writeInt(destinationPort);
     }
 
+    @Override
+    public String toString(){
+        return "[VisualVoicemailSmsFilterSettings "
+                + "clientPrefix=" + clientPrefix
+                + ", originatingNumbers=" + originatingNumbers
+                + ", destinationPort=" + destinationPort
+                + "]";
+    }
+
 }
diff --git a/telephony/java/android/telephony/mbms/StreamingService.java b/telephony/java/android/telephony/mbms/StreamingService.java
index f93b1a8..ee0d894 100644
--- a/telephony/java/android/telephony/mbms/StreamingService.java
+++ b/telephony/java/android/telephony/mbms/StreamingService.java
@@ -37,7 +37,9 @@
     }
 
     /**
-     * Retreive the Uri used to play this stream
+     * Retreive the Uri used to play this stream.
+     *
+     * This may throw a RemoteException.
      */
     public Uri getPlaybackUri() {
         return null;
@@ -52,6 +54,8 @@
 
     /**
      * Retreive the current state of this stream.
+     *
+     * This may throw a RemoteException.
      */
     public int getState() {
         return STATE_STOPPED;
@@ -59,12 +63,19 @@
 
     /**
      * Stop streaming this service.  Terminal.
+     *
+     * This may throw a RemoteException.
      */
     public void stopStreaming() {
     }
 
     /**
      * Switch this stream to a different service.  Used for smooth transitions.
+     *
+     * This may throw a RemoteException.
+     *
+     * Asynchronous errors through the listener include any of the errors except
+     * <li>ERROR_MSDC_UNABLE_TO_INITIALIZE</li>
      */
     public void switchStream(StreamingServiceInfo streamingServiceInfo) {
     }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2741bd4..6de62de 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony;
 
+import android.app.PendingIntent;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -277,10 +278,11 @@
     /**
      * Handles USSD commands.
      *
+     * @param subId The subscription to use.
      * @param ussdRequest the USSD command to be executed.
      * @param wrappedCallback receives a callback result.
      */
-    void handleUssdRequest(String ussdRequest, in ResultReceiver wrappedCallback);
+    void handleUssdRequest(int subId, String ussdRequest, in ResultReceiver wrappedCallback);
 
     /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
@@ -490,6 +492,12 @@
      */
     int getVoiceMessageCountForSubscriber(int subId);
 
+    /**
+      * Returns true if current state supports both voice and data
+      * simultaneously. This can change based on location or network condition.
+      */
+    boolean isConcurrentVoiceAndDataAllowed(int subId);
+
     oneway void setVisualVoicemailEnabled(String callingPackage,
             in PhoneAccountHandle accountHandle, boolean enabled);
 
@@ -506,9 +514,18 @@
     VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(String callingPackage,
             int subId);
 
-    // Get settings set by the package, requires READ_PRIVILEGED_PHONE_STATE permission
-    VisualVoicemailSmsFilterSettings getSystemVisualVoicemailSmsFilterSettings(String packageName,
-            int subId);
+    /**
+     *  Get settings set by the current default dialer, Internal use only.
+     *  Requires READ_PRIVILEGED_PHONE_STATE permission.
+     */
+    VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId);
+
+    /**
+     * Send a visual voicemail SMS. Internal use only.
+     * Requires caller to be the default dialer and have SEND_SMS permission
+     */
+    oneway void sendVisualVoicemailSmsForSubscriber(in String callingPackage, in int subId,
+            in String number, in int port, in String text, in PendingIntent sentIntent);
 
     /**
      * Returns the network type for data transmission
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1be8d5e..51732788 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -1993,6 +1993,40 @@
     }
 
     @SmallTest
+    public void testNetworkSpecifierUidSpoofSecurityException() {
+        class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+            @Override
+            public boolean satisfiedBy(NetworkSpecifier other) {
+                return true;
+            }
+
+            @Override
+            public void assertValidFromUid(int requestorUid) {
+                throw new SecurityException("failure");
+            }
+
+            @Override
+            public int describeContents() { return 0; }
+            @Override
+            public void writeToParcel(Parcel dest, int flags) {}
+        }
+
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+
+        UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
+        NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
+                networkSpecifier).build();
+        TestNetworkCallback networkCallback = new TestNetworkCallback();
+        try {
+            mCm.requestNetwork(networkRequest, networkCallback);
+            fail("Network request with spoofed UID did not throw a SecurityException");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
+    @SmallTest
     public void testRegisterDefaultNetworkCallback() throws Exception {
         final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 3fcbd4b..b9ce61c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -31,6 +31,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.SparseArray;
@@ -453,7 +454,8 @@
                 peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
                 null, // peerMac (not used in this method)
                 pmk,
-                passphrase);
+                passphrase,
+                Process.myUid());
     }
 
     /** @hide */
@@ -490,7 +492,8 @@
                 0, // 0 is an invalid peer ID
                 peer,
                 pmk,
-                passphrase);
+                passphrase,
+                Process.myUid());
     }
 
     private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub {
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index 5993480..e152f6c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -19,6 +19,7 @@
 import android.net.NetworkSpecifier;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Log;
 
 import java.util.Arrays;
 import java.util.Objects;
@@ -115,9 +116,18 @@
      */
     public final String passphrase;
 
+    /**
+     * The UID of the process initializing this network specifier. Validated by receiver using
+     * checkUidIfNecessary() and is used by satisfiedBy() to determine whether matches the
+     * offered network.
+     *
+     * @hide
+     */
+    public final int requestorUid;
+
     /** @hide */
     public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId,
-            byte[] peerMac, byte[] pmk, String passphrase) {
+            byte[] peerMac, byte[] pmk, String passphrase, int requestorUid) {
         this.type = type;
         this.role = role;
         this.clientId = clientId;
@@ -126,6 +136,7 @@
         this.peerMac = peerMac;
         this.pmk = pmk;
         this.passphrase = passphrase;
+        this.requestorUid = requestorUid;
     }
 
     public static final Creator<WifiAwareNetworkSpecifier> CREATOR =
@@ -140,7 +151,8 @@
                         in.readInt(), // peerId
                         in.createByteArray(), // peerMac
                         in.createByteArray(), // pmk
-                        in.readString()); // passphrase
+                        in.readString(), // passphrase
+                        in.readInt()); // requestorUid
                 }
 
                 @Override
@@ -164,6 +176,7 @@
         dest.writeByteArray(peerMac);
         dest.writeByteArray(pmk);
         dest.writeString(passphrase);
+        dest.writeInt(requestorUid);
     }
 
     /** @hide */
@@ -186,6 +199,7 @@
         result = 31 * result + Arrays.hashCode(peerMac);
         result = 31 * result + Arrays.hashCode(pmk);
         result = 31 * result + Objects.hashCode(passphrase);
+        result = 31 * result + requestorUid;
 
         return result;
     }
@@ -210,7 +224,8 @@
                 && peerId == lhs.peerId
                 && Arrays.equals(peerMac, lhs.peerMac)
                 && Arrays.equals(pmk, lhs.pmk)
-                && Objects.equals(passphrase, lhs.passphrase);
+                && Objects.equals(passphrase, lhs.passphrase)
+                && requestorUid == lhs.requestorUid;
     }
 
     /** @hide */
@@ -228,7 +243,16 @@
                 .append(", pmk=").append((pmk == null) ? "<null>" : "<non-null>")
                 // masking PII
                 .append(", passphrase=").append((passphrase == null) ? "<null>" : "<non-null>")
+                .append(", requestorUid=").append(requestorUid)
                 .append("]");
         return sb.toString();
     }
+
+    /** @hide */
+    @Override
+    public void assertValidFromUid(int requestorUid) {
+        if (this.requestorUid != requestorUid) {
+            throw new SecurityException("mismatched UIDs");
+        }
+    }
 }