diff options
33 files changed, 1364 insertions, 304 deletions
diff --git a/Android.mk b/Android.mk index a2d70ce70506..623ceba9c65f 100644 --- a/Android.mk +++ b/Android.mk @@ -130,7 +130,6 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothGatt.aidl \ core/java/android/bluetooth/IBluetoothGattCallback.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \ - core/java/android/bluetooth/le/IAdvertiserCallback.aidl \ core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl \ core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl \ core/java/android/bluetooth/le/IScannerCallback.aidl \ diff --git a/api/current.txt b/api/current.txt index f59322a827a4..8894f97dc9e0 100644 --- a/api/current.txt +++ b/api/current.txt @@ -36,6 +36,7 @@ package android { 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 @@ package android.bluetooth { 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; @@ -18179,9 +18181,9 @@ package android.icu.util { method protected final void computeGregorianFields(int); method protected int computeGregorianMonthStart(int, int); method protected int computeJulianDay(); - method protected int computeMillisInDay(); + method protected deprecated int computeMillisInDay(); method protected void computeTime(); - method protected int computeZoneOffset(long, int); + method protected deprecated int computeZoneOffset(long, int); method public int fieldDifference(java.util.Date, int); method protected java.lang.String fieldName(int); method protected static final long floorDivide(long, long); @@ -38226,6 +38228,8 @@ package android.telephony { method public boolean isWorldPhone(); 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); @@ -38300,6 +38304,60 @@ package android.telephony { field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp"; } + public static abstract class TelephonyManager.OnReceiveUssdResponseCallback { + ctor public TelephonyManager.OnReceiveUssdResponseCallback(); + method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence); + 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 dab25acb0fbd..3a3ba966ce52 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -55,6 +55,7 @@ package android { 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 @@ package android.bluetooth { 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; @@ -19394,9 +19396,9 @@ package android.icu.util { method protected final void computeGregorianFields(int); method protected int computeGregorianMonthStart(int, int); method protected int computeJulianDay(); - method protected int computeMillisInDay(); + method protected deprecated int computeMillisInDay(); method protected void computeTime(); - method protected int computeZoneOffset(long, int); + method protected deprecated int computeZoneOffset(long, int); method public int fieldDifference(java.util.Date, int); method protected java.lang.String fieldName(int); method protected static final long floorDivide(long, long); @@ -41451,6 +41453,8 @@ package android.telephony { method public void listen(android.telephony.PhoneStateListener, int); 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); @@ -41546,6 +41550,60 @@ package android.telephony { field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp"; } + public static abstract class TelephonyManager.OnReceiveUssdResponseCallback { + ctor public TelephonyManager.OnReceiveUssdResponseCallback(); + method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence); + 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 0126ae5571a0..88b3c2f486c6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -36,6 +36,7 @@ package android { 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 @@ package android.bluetooth { 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; @@ -18197,9 +18199,9 @@ package android.icu.util { method protected final void computeGregorianFields(int); method protected int computeGregorianMonthStart(int, int); method protected int computeJulianDay(); - method protected int computeMillisInDay(); + method protected deprecated int computeMillisInDay(); method protected void computeTime(); - method protected int computeZoneOffset(long, int); + method protected deprecated int computeZoneOffset(long, int); method public int fieldDifference(java.util.Date, int); method protected java.lang.String fieldName(int); method protected static final long floorDivide(long, long); @@ -38325,6 +38327,8 @@ package android.telephony { method public boolean isWorldPhone(); 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); @@ -38399,6 +38403,60 @@ package android.telephony { field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp"; } + public static abstract class TelephonyManager.OnReceiveUssdResponseCallback { + ctor public TelephonyManager.OnReceiveUssdResponseCallback(); + method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence); + 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 e6cebc0819f5..e0b03d22abe9 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -22,6 +22,8 @@ import android.annotation.SdkConstant; 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 final class BluetoothDevice implements Parcelable { 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 @@ public final class BluetoothDevice implements Parcelable { * {@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 @@ public final class BluetoothDevice implements Parcelable { 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 9144ae722911..7806e31c418e 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 @@ public final class BluetoothGatt implements BluetoothProfile { private IBluetoothGatt mService; private BluetoothGattCallback mCallback; + private Handler mHandler; private int mClientIf; private BluetoothDevice mDevice; private boolean mAutoConnect; @@ -154,8 +156,14 @@ public final class BluetoothGatt implements BluetoothProfile { } 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { } 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 @@ public final class BluetoothGatt implements BluetoothProfile { } } - 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 @@ public final class BluetoothGatt implements BluetoothProfile { * @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 @@ public final class BluetoothGatt implements BluetoothProfile { * 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 @@ public final class BluetoothGatt implements BluetoothProfile { 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 11a15c66385a..c6f82ffb7ae4 100644 --- a/core/java/android/bluetooth/BluetoothGattCallback.java +++ b/core/java/android/bluetooth/BluetoothGattCallback.java @@ -30,7 +30,8 @@ public abstract class BluetoothGattCallback{ * {@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 @@ public abstract class BluetoothGattCallback{ * {@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 3b8f962bf73e..02307bd9ef9f 100644 --- a/core/java/android/bluetooth/BluetoothGattServerCallback.java +++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java @@ -167,7 +167,8 @@ public abstract class BluetoothGattServerCallback { * {@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 @@ public abstract class BluetoothGattServerCallback { * {@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/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index a2066cb4991e..fb6b89341db4 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -31,7 +31,6 @@ import android.os.WorkSource; import android.bluetooth.IBluetoothGattCallback; import android.bluetooth.IBluetoothGattServerCallback; -import android.bluetooth.le.IAdvertiserCallback; import android.bluetooth.le.IAdvertisingSetCallback; import android.bluetooth.le.IPeriodicAdvertisingCallback; import android.bluetooth.le.IScannerCallback; diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index 21e9497daa62..67d56d5060e9 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -22,7 +22,6 @@ import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothUuid; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothManager; -import android.bluetooth.le.IAdvertiserCallback; import android.os.Handler; import android.os.Looper; import android.os.ParcelUuid; diff --git a/core/java/android/bluetooth/le/IAdvertiserCallback.aidl b/core/java/android/bluetooth/le/IAdvertiserCallback.aidl deleted file mode 100644 index c58b1dfec965..000000000000 --- a/core/java/android/bluetooth/le/IAdvertiserCallback.aidl +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.bluetooth.le; - -import android.bluetooth.le.AdvertiseSettings; - -/** - * Callback definitions for interacting with Advertiser - * @hide - */ -oneway interface IAdvertiserCallback { - void onAdvertiserRegistered(in int status, in int advertiserId); - - void onMultiAdvertiseCallback(in int status, boolean isStart, - in AdvertiseSettings advertiseSettings); -} diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 5edc7c64275c..1da0d281538d 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -20,6 +20,7 @@ import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.BitUtils; import java.util.Objects; @@ -292,7 +293,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public int[] getCapabilities() { - return enumerateBits(mNetworkCapabilities); + return BitUtils.unpackBits(mNetworkCapabilities); } /** @@ -308,19 +309,6 @@ public final class NetworkCapabilities implements Parcelable { return ((mNetworkCapabilities & (1 << capability)) != 0); } - private int[] enumerateBits(long val) { - int size = Long.bitCount(val); - int[] result = new int[size]; - int index = 0; - int resource = 0; - while (val > 0) { - if ((val & 1) == 1) result[index++] = resource; - val = val >> 1; - resource++; - } - return result; - } - private void combineNetCapabilities(NetworkCapabilities nc) { this.mNetworkCapabilities |= nc.mNetworkCapabilities; } @@ -433,6 +421,15 @@ public final class NetworkCapabilities implements Parcelable { private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR; private static final int MAX_TRANSPORT = TRANSPORT_WIFI_AWARE; + private static final String[] TRANSPORT_NAMES = { + "CELLULAR", + "WIFI", + "BLUETOOTH", + "ETHERNET", + "VPN", + "WIFI_AWARE" + }; + /** * Adds the given transport type to this {@code NetworkCapability} instance. * Multiple transports may be applied sequentially. Note that when searching @@ -479,7 +476,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public int[] getTransportTypes() { - return enumerateBits(mTransportTypes); + return BitUtils.unpackBits(mTransportTypes); } /** @@ -886,18 +883,23 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public static String transportNamesOf(int[] types) { - String transports = ""; - for (int i = 0; i < types.length;) { - switch (types[i]) { - case TRANSPORT_CELLULAR: transports += "CELLULAR"; break; - case TRANSPORT_WIFI: transports += "WIFI"; break; - case TRANSPORT_BLUETOOTH: transports += "BLUETOOTH"; break; - case TRANSPORT_ETHERNET: transports += "ETHERNET"; break; - case TRANSPORT_VPN: transports += "VPN"; break; - case TRANSPORT_WIFI_AWARE: transports += "WIFI_AWARE"; break; - } - if (++i < types.length) transports += "|"; + if (types == null || types.length == 0) { + return ""; + } + StringBuilder transports = new StringBuilder(); + for (int t : types) { + transports.append("|").append(transportNameOf(t)); + } + return transports.substring(1); + } + + /** + * @hide + */ + public static String transportNameOf(int transport) { + if (transport < 0 || TRANSPORT_NAMES.length <= transport) { + return "UNKNOWN"; } - return transports; + return TRANSPORT_NAMES[transport]; } } diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java index 87a2b05a4430..9ce2a5bd1b54 100644 --- a/core/java/android/net/NetworkSpecifier.java +++ b/core/java/android/net/NetworkSpecifier.java @@ -33,4 +33,20 @@ public abstract class NetworkSpecifier { * @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/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index dbe2f6d3283d..c34de1551ebf 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -315,8 +315,6 @@ interface INetworkManagementService void setFirewallEnabled(boolean enabled); boolean isFirewallEnabled(); void setFirewallInterfaceRule(String iface, boolean allow); - void setFirewallEgressSourceRule(String addr, boolean allow); - void setFirewallEgressDestRule(String addr, int port, boolean allow); void setFirewallUidRule(int chain, int uid, int rule); void setFirewallUidRules(int chain, in int[] uids, in int[] rules); void setFirewallChainEnabled(int chain, boolean enable); diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java index 1e5416382f8c..e48a0d08de7d 100644 --- a/core/java/android/provider/VoicemailContract.java +++ b/core/java/android/provider/VoicemailContract.java @@ -107,15 +107,7 @@ public class VoicemailContract { /** * 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 @@ public class VoicemailContract { "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/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java index a208ccb8f35f..1b354d0d9df0 100644 --- a/core/java/com/android/internal/util/BitUtils.java +++ b/core/java/com/android/internal/util/BitUtils.java @@ -21,10 +21,16 @@ import android.annotation.Nullable; import libcore.util.Objects; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.UUID; -public class BitUtils { +/** + * A utility class for handling unsigned integers and unsigned arithmetics, as well as syntactic + * sugar methods for ByteBuffer. Useful for networking and packet manipulations. + * {@hide} + */ +public final class BitUtils { private BitUtils() {} public static boolean maskedEquals(long a, long b, long mask) { @@ -55,4 +61,67 @@ public class BitUtils { && maskedEquals(a.getMostSignificantBits(), b.getMostSignificantBits(), mask.getMostSignificantBits()); } + + public static int[] unpackBits(long val) { + int size = Long.bitCount(val); + int[] result = new int[size]; + int index = 0; + int bitPos = 0; + while (val > 0) { + if ((val & 1) == 1) result[index++] = bitPos; + val = val >> 1; + bitPos++; + } + return result; + } + + public static long packBits(int[] bits) { + long packed = 0; + for (int b : bits) { + packed |= (1 << b); + } + return packed; + } + + public static int uint8(byte b) { + return b & 0xff; + } + + public static int uint16(short s) { + return s & 0xffff; + } + + public static long uint32(int i) { + return i & 0xffffffffL; + } + + public static int bytesToBEInt(byte[] bytes) { + return (uint8(bytes[0]) << 24) + + (uint8(bytes[1]) << 16) + + (uint8(bytes[2]) << 8) + + (uint8(bytes[3])); + } + + public static int bytesToLEInt(byte[] bytes) { + return Integer.reverseBytes(bytesToBEInt(bytes)); + } + + public static int getUint8(ByteBuffer buffer, int position) { + return uint8(buffer.get(position)); + } + + public static int getUint16(ByteBuffer buffer, int position) { + return uint16(buffer.getShort(position)); + } + + public static long getUint32(ByteBuffer buffer, int position) { + return uint32(buffer.getInt(position)); + } + + public static void put(ByteBuffer buffer, int position, byte[] bytes) { + final int original = buffer.position(); + buffer.position(position); + buffer.put(bytes); + buffer.position(original); + } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 9e7bf2777a5a..f5f67d06d84a 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 616a8c028f28..88bc54d26755 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.Intent; 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.NetworkInfo.DetailedState; 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.ArraySet; 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ public class ConnectivityService extends IConnectivityManager.Stub // 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 @@ public class ConnectivityService extends IConnectivityManager.Stub 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/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index f4e11c792ed7..7e1a1ca60826 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -1896,30 +1896,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } - @Override - public void setFirewallEgressSourceRule(String addr, boolean allow) { - enforceSystemUid(); - Preconditions.checkState(mFirewallEnabled); - final String rule = allow ? "allow" : "deny"; - try { - mConnector.execute("firewall", "set_egress_source_rule", addr, rule); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - } - - @Override - public void setFirewallEgressDestRule(String addr, int port, boolean allow) { - enforceSystemUid(); - Preconditions.checkState(mFirewallEnabled); - final String rule = allow ? "allow" : "deny"; - try { - mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - } - private void closeSocketsForFirewallChainLocked(int chain, String chainName) { // UID ranges to close sockets on. UidRange[] ranges; diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index cc41060a55eb..f97a672b6d40 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 @@ public class MediaSessionService extends SystemService implements Monitor { 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/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java index 0a907496ebdd..985a12c13c19 100644 --- a/services/net/java/android/net/apf/ApfFilter.java +++ b/services/net/java/android/net/apf/ApfFilter.java @@ -18,6 +18,14 @@ package android.net.apf; import static android.system.OsConstants.*; +import static com.android.internal.util.BitUtils.bytesToBEInt; +import static com.android.internal.util.BitUtils.getUint16; +import static com.android.internal.util.BitUtils.getUint32; +import static com.android.internal.util.BitUtils.getUint8; +import static com.android.internal.util.BitUtils.uint16; +import static com.android.internal.util.BitUtils.uint32; +import static com.android.internal.util.BitUtils.uint8; + import android.os.SystemClock; import android.net.LinkAddress; import android.net.LinkProperties; @@ -1157,41 +1165,9 @@ public class ApfFilter { } } - private static int uint8(byte b) { - return b & 0xff; - } - - private static int uint16(short s) { - return s & 0xffff; - } - - private static long uint32(int i) { - return i & 0xffffffffL; - } - - private static int getUint8(ByteBuffer buffer, int position) { - return uint8(buffer.get(position)); - } - - private static int getUint16(ByteBuffer buffer, int position) { - return uint16(buffer.getShort(position)); - } - - private static long getUint32(ByteBuffer buffer, int position) { - return uint32(buffer.getInt(position)); - } - // TODO: move to android.net.NetworkUtils @VisibleForTesting public static int ipv4BroadcastAddress(byte[] addrBytes, int prefixLength) { - return bytesToInt(addrBytes) | (int) (uint32(-1) >>> prefixLength); - } - - @VisibleForTesting - public static int bytesToInt(byte[] addrBytes) { - return (uint8(addrBytes[0]) << 24) - + (uint8(addrBytes[1]) << 16) - + (uint8(addrBytes[2]) << 8) - + (uint8(addrBytes[3])); + return bytesToBEInt(addrBytes) | (int) (uint32(-1) >>> prefixLength); } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 1c020aef5417..5d222d425918 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -16,24 +16,30 @@ package android.telephony; +import static com.android.internal.util.Preconditions.checkNotNull; + import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; 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.ResultReceiver; +import android.os.Binder; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.os.Bundle; +import android.os.Handler; import android.os.PersistableBundle; import android.os.RemoteException; +import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SystemProperties; import android.service.carrier.CarrierIdentifier; @@ -61,6 +67,7 @@ import java.io.FileInputStream; 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; @@ -838,6 +845,29 @@ public class TelephonyManager { */ public static final String VVM_TYPE_CVVM = "vvm_type_cvvm"; + /** + * @hide + */ + public static final String USSD_RESPONSE = "USSD_RESPONSE"; + + /** + * USSD return code success. + * @hide + */ + public static final int USSD_RETURN_SUCCESS = 100; + + /** + * USSD return code for failure case. + * @hide + */ + public static final int USSD_RETURN_FAILURE = -1; + + /** + * USSD return code for failure case. + * @hide + */ + public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; + // // // Device Info @@ -2758,18 +2788,17 @@ public class TelephonyManager { /** * @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) { @@ -2779,6 +2808,35 @@ public class TelephonyManager { } /** + * 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 */ @@ -4965,6 +5023,70 @@ public class TelephonyManager { return new int[0]; } + public static abstract class OnReceiveUssdResponseCallback { + /** + ** Called when USSD has succeeded. + **/ + public void onReceiveUssdResponse(String request, CharSequence response) {}; + + /** + ** Called when USSD has failed. + **/ + public void onReceiveUssdResponseFailed(String request, int failureCode) {}; + } + + /* <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) { + sendUssdRequest(ussdRequest, getSubId(), callback, handler); + } + + /* <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."); + + 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(subId, ussdRequest, wrappedCallback); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#sendUSSDCode", e); + UssdResponse response = new UssdResponse(ussdRequest, ""); + Bundle returnData = new Bundle(); + returnData.putParcelable(USSD_RESPONSE, response); + wrappedCallback.send(USSD_ERROR_SERVICE_UNAVAIL, returnData); + } + } + /** @hide */ @SystemApi public boolean handlePinMmi(String dialString) { diff --git a/telephony/java/android/telephony/UssdResponse.aidl b/telephony/java/android/telephony/UssdResponse.aidl new file mode 100644 index 000000000000..add28a02ae10 --- /dev/null +++ b/telephony/java/android/telephony/UssdResponse.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright 2007, 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; + +parcelable UssdResponse; diff --git a/telephony/java/android/telephony/UssdResponse.java b/telephony/java/android/telephony/UssdResponse.java new file mode 100644 index 000000000000..5df681d4406e --- /dev/null +++ b/telephony/java/android/telephony/UssdResponse.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2006 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.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +/** + * Represents the Ussd response, including + * the message and the return code. + * @hide + */ +public final class UssdResponse implements Parcelable { + private CharSequence mReturnMessage; + private String mUssdRequest; + + + /** + * Implement the Parcelable interface + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mUssdRequest); + TextUtils.writeToParcel(mReturnMessage, dest, 0); + } + + public String getUssdRequest() { + return mUssdRequest; + } + + public CharSequence getReturnMessage() { + return mReturnMessage; + } + + /** + * Implement the Parcelable interface + */ + @Override + public int describeContents() { + return 0; + } + + /** + * * Initialize the object from the request and return message. + */ + public UssdResponse(String ussdRequest, CharSequence returnMessage) { + mUssdRequest = ussdRequest; + mReturnMessage = returnMessage; + } + + public static final Parcelable.Creator<UssdResponse> CREATOR = new Creator<UssdResponse>() { + + @Override + public UssdResponse createFromParcel(Parcel in) { + String request = in.readString(); + CharSequence message = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); + return new UssdResponse(request, message); + } + + @Override + public UssdResponse[] newArray(int size) { + return new UssdResponse[size]; + } + }; +} diff --git a/telephony/java/android/telephony/VisualVoicemailService.java b/telephony/java/android/telephony/VisualVoicemailService.java new file mode 100644 index 000000000000..84833e38232f --- /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 000000000000..6235c10ab12a --- /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 5b81027655f0..9d19d0860407 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 @@ import java.util.List; * <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 @@ public class VisualVoicemailSmsFilterSettings implements Parcelable { /** * Builder class for {@link VisualVoicemailSmsFilterSettings} objects. - * - * @hide */ public static class Builder { @@ -171,4 +168,13 @@ public class VisualVoicemailSmsFilterSettings implements Parcelable { dest.writeInt(destinationPort); } + @Override + public String toString(){ + return "[VisualVoicemailSmsFilterSettings " + + "clientPrefix=" + clientPrefix + + ", originatingNumbers=" + originatingNumbers + + ", destinationPort=" + destinationPort + + "]"; + } + } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index c6b750e71098..6b9c81d6cfed 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; @@ -273,6 +274,16 @@ interface ITelephony { */ boolean handlePinMmi(String dialString); + + /** + * 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(int subId, String ussdRequest, in ResultReceiver wrappedCallback); + /** * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated * without SEND (so <code>dial</code> is not appropriate) for @@ -497,9 +508,18 @@ interface ITelephony { 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/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java index 91d6c6840f47..d4896264cae8 100644 --- a/tests/net/java/android/net/apf/ApfTest.java +++ b/tests/net/java/android/net/apf/ApfTest.java @@ -39,6 +39,8 @@ import static android.system.OsConstants.*; import com.android.frameworks.tests.net.R; import com.android.internal.util.HexDump; +import static com.android.internal.util.BitUtils.bytesToBEInt; +import static com.android.internal.util.BitUtils.put; import org.mockito.ArgumentCaptor; import org.mockito.Mock; @@ -65,7 +67,7 @@ import libcore.io.Streams; * Tests for APF program generator and interpreter. * * Build, install and run with: - * runtest frameworks-services -c android.net.apf.ApfTest + * runtest frameworks-net -c android.net.apf.ApfTest */ public class ApfTest extends AndroidTestCase { private static final int TIMEOUT_MS = 500; @@ -1235,15 +1237,6 @@ public class ApfTest extends AndroidTestCase { byte[] apf_program); @SmallTest - public void testBytesToInt() { - assertEquals(0x00000000, ApfFilter.bytesToInt(IPV4_ANY_HOST_ADDR)); - assertEquals(0xffffffff, ApfFilter.bytesToInt(IPV4_BROADCAST_ADDRESS)); - assertEquals(0x0a000001, ApfFilter.bytesToInt(MOCK_IPV4_ADDR)); - assertEquals(0x0a000002, ApfFilter.bytesToInt(ANOTHER_IPV4_ADDR)); - assertEquals(0x0a001fff, ApfFilter.bytesToInt(MOCK_BROADCAST_IPV4_ADDR)); - assertEquals(0xe0000001, ApfFilter.bytesToInt(MOCK_MULTICAST_IPV4_ADDR)); - } - public void testBroadcastAddress() throws Exception { assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0)); assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32)); @@ -1257,7 +1250,7 @@ public class ApfTest extends AndroidTestCase { } public void assertEqualsIp(String expected, int got) throws Exception { - int want = ApfFilter.bytesToInt(InetAddress.getByName(expected).getAddress()); + int want = bytesToBEInt(InetAddress.getByName(expected).getAddress()); assertEquals(want, got); } } diff --git a/tests/net/java/com/android/internal/util/BitUtilsTest.java b/tests/net/java/com/android/internal/util/BitUtilsTest.java new file mode 100644 index 000000000000..0ad8a21f7712 --- /dev/null +++ b/tests/net/java/com/android/internal/util/BitUtilsTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import java.nio.ByteBuffer; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static com.android.internal.util.BitUtils.*; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class BitUtilsTest { + + @Test + public void testUnsignedByteWideningConversions() { + byte b0 = 0; + byte b1 = 1; + byte bm1 = -1; + assertEquals(0, uint8(b0)); + assertEquals(1, uint8(b1)); + assertEquals(127, uint8(Byte.MAX_VALUE)); + assertEquals(128, uint8(Byte.MIN_VALUE)); + assertEquals(255, uint8(bm1)); + assertEquals(255, uint8((byte)255)); + } + + @Test + public void testUnsignedShortWideningConversions() { + short s0 = 0; + short s1 = 1; + short sm1 = -1; + assertEquals(0, uint16(s0)); + assertEquals(1, uint16(s1)); + assertEquals(32767, uint16(Short.MAX_VALUE)); + assertEquals(32768, uint16(Short.MIN_VALUE)); + assertEquals(65535, uint16(sm1)); + assertEquals(65535, uint16((short)65535)); + } + + @Test + public void testUnsignedIntWideningConversions() { + assertEquals(0, uint32(0)); + assertEquals(1, uint32(1)); + assertEquals(2147483647L, uint32(Integer.MAX_VALUE)); + assertEquals(2147483648L, uint32(Integer.MIN_VALUE)); + assertEquals(4294967295L, uint32(-1)); + assertEquals(4294967295L, uint32((int)4294967295L)); + } + + @Test + public void testBytesToInt() { + assertEquals(0x00000000, bytesToBEInt(bytes(0, 0, 0, 0))); + assertEquals(0xffffffff, bytesToBEInt(bytes(255, 255, 255, 255))); + assertEquals(0x0a000001, bytesToBEInt(bytes(10, 0, 0, 1))); + assertEquals(0x0a000002, bytesToBEInt(bytes(10, 0, 0, 2))); + assertEquals(0x0a001fff, bytesToBEInt(bytes(10, 0, 31, 255))); + assertEquals(0xe0000001, bytesToBEInt(bytes(224, 0, 0, 1))); + + assertEquals(0x00000000, bytesToLEInt(bytes(0, 0, 0, 0))); + assertEquals(0x01020304, bytesToLEInt(bytes(4, 3, 2, 1))); + assertEquals(0xffff0000, bytesToLEInt(bytes(0, 0, 255, 255))); + } + + @Test + public void testUnsignedGetters() { + ByteBuffer b = ByteBuffer.allocate(4); + b.putInt(0xffff); + + assertEquals(0x0, getUint8(b, 0)); + assertEquals(0x0, getUint8(b, 1)); + assertEquals(0xff, getUint8(b, 2)); + assertEquals(0xff, getUint8(b, 3)); + + assertEquals(0x0, getUint16(b, 0)); + assertEquals(0xffff, getUint16(b, 2)); + + b.rewind(); + b.putInt(0xffffffff); + assertEquals(0xffffffffL, getUint32(b, 0)); + } + + static byte[] bytes(int b1, int b2, int b3, int b4) { + return new byte[] {b(b1), b(b2), b(b3), b(b4)}; + } + + static byte b(int i) { + return (byte) i; + } +} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 1be8d5e85660..517327882bfa 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1993,6 +1993,40 @@ public class ConnectivityServiceTest extends AndroidTestCase { } @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 3fcbd4b60259..b9ce61cf9760 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.Bundle; 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 @@ public class WifiAwareManager { 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 @@ public class WifiAwareManager { 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 59934806f398..e152f6ced571 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java @@ -19,6 +19,7 @@ package android.net.wifi.aware; 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 class WifiAwareNetworkSpecifier extends NetworkSpecifier implements */ 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 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements this.peerMac = peerMac; this.pmk = pmk; this.passphrase = passphrase; + this.requestorUid = requestorUid; } public static final Creator<WifiAwareNetworkSpecifier> CREATOR = @@ -140,7 +151,8 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements in.readInt(), // peerId in.createByteArray(), // peerMac in.createByteArray(), // pmk - in.readString()); // passphrase + in.readString(), // passphrase + in.readInt()); // requestorUid } @Override @@ -164,6 +176,7 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements dest.writeByteArray(peerMac); dest.writeByteArray(pmk); dest.writeString(passphrase); + dest.writeInt(requestorUid); } /** @hide */ @@ -186,6 +199,7 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements 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 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements && 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 @@ public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements .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"); + } + } } |