Merge "Add VisualVoicemailService"
diff --git a/api/current.txt b/api/current.txt
index ddb42b9..8894f97 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7078,6 +7078,7 @@
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
+ method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
method public boolean createBond();
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -38228,6 +38229,7 @@
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 503e897..3a3ba96 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7381,6 +7381,7 @@
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
+ method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
method public boolean createBond();
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -41453,6 +41454,7 @@
method public boolean needsOtaServiceProvisioning();
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method public void setDataEnabled(boolean);
method public void setDataEnabled(int, boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 3b4fabe..88b3c2f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -7087,6 +7087,7 @@
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
+ method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
method public boolean createBond();
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -38327,6 +38328,7 @@
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+ method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
method public void setDataEnabled(boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index e6cebc0..e0b03d2 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -22,6 +22,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.ParcelUuid;
@@ -593,32 +595,38 @@
public static final int TRANSPORT_LE = 2;
/**
- * Bluetooth LE 1M PHY.
+ * Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or
+ * connection.
*/
public static final int PHY_LE_1M = 1;
/**
- * Bluetooth LE 2M PHY.
+ * Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or
+ * connection.
*/
public static final int PHY_LE_2M = 2;
/**
- * Bluetooth LE Coded PHY.
+ * Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning
+ * or connection.
*/
public static final int PHY_LE_CODED = 3;
/**
- * Bluetooth LE 1M PHY mask.
+ * Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available
+ * options in a bitmask.
*/
public static final int PHY_LE_1M_MASK = 1;
/**
- * Bluetooth LE 2M PHY mask.
+ * Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available
+ * options in a bitmask.
*/
public static final int PHY_LE_2M_MASK = 2;
/**
- * Bluetooth LE Coded PHY mask.
+ * Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many
+ * available options in a bitmask.
*/
public static final int PHY_LE_CODED_MASK = 4;
@@ -1679,12 +1687,45 @@
* {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
* @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
* {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
- * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if
- * {@code autoConnect} is set to true.
- * @throws IllegalArgumentException if callback is null
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect
+ * if {@code autoConnect} is set to true.
+ * @throws NullPointerException if callback is null
*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport, int phy) {
+ return connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M_MASK, null);
+ }
+
+ /**
+ * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as any further GATT client operations.
+ * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+ * GATT client operations.
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @param autoConnect Whether to directly connect to the remote device (false)
+ * or to automatically connect as soon as the remote
+ * device becomes available (true).
+ * @param transport preferred transport for GATT connections to remote dual-mode devices
+ * {@link BluetoothDevice#TRANSPORT_AUTO} or
+ * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+ * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect
+ * if {@code autoConnect} is set to true.
+ * @param handler The handler to use for the callback. If {@code null}, callbacks will happen
+ * on the service's main thread.
+ * @throws NullPointerException if callback is null
+ */
+ public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+ BluetoothGattCallback callback, int transport, int phy,
+ Handler handler) {
+ if (callback == null)
+ throw new NullPointerException("callback is null");
+
+ if (handler == null)
+ handler = new Handler(Looper.getMainLooper());
+
// TODO(Bluetooth) check whether platform support BLE
// Do the check here or in GattServer?
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1696,7 +1737,7 @@
return null;
}
BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, phy);
- gatt.connect(autoConnect, callback);
+ gatt.connect(autoConnect, callback, handler);
return gatt;
} catch (RemoteException e) {Log.e(TAG, "", e);}
return null;
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 9144ae7..7806e31 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.content.Context;
+import android.os.Handler;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;
@@ -43,6 +44,7 @@
private IBluetoothGatt mService;
private BluetoothGattCallback mCallback;
+ private Handler mHandler;
private int mClientIf;
private BluetoothDevice mDevice;
private boolean mAutoConnect;
@@ -154,8 +156,14 @@
}
mClientIf = clientIf;
if (status != GATT_SUCCESS) {
- mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
- BluetoothProfile.STATE_DISCONNECTED);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
+ BluetoothProfile.STATE_DISCONNECTED);
+ }
+ });
+
synchronized(mStateLock) {
mConnState = CONN_STATE_IDLE;
}
@@ -181,11 +189,12 @@
return;
}
- try {
- mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
+ }
+ });
}
/**
@@ -200,11 +209,12 @@
return;
}
- try {
- mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
+ }
+ });
}
/**
@@ -221,11 +231,13 @@
}
int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
BluetoothProfile.STATE_DISCONNECTED;
- try {
- mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onConnectionStateChange(BluetoothGatt.this, status, profileState);
+ }
+ });
synchronized(mStateLock) {
if (connected) {
@@ -279,11 +291,12 @@
}
}
- try {
- mCallback.onServicesDiscovered(BluetoothGatt.this, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onServicesDiscovered(BluetoothGatt.this, status);
+ }
+ });
}
/**
@@ -328,11 +341,12 @@
if (status == 0) characteristic.setValue(value);
- try {
- mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic, status);
+ }
+ });
}
/**
@@ -373,11 +387,12 @@
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- try {
- mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
+ }
+ });
}
/**
@@ -398,11 +413,12 @@
characteristic.setValue(value);
- try {
- mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
+ }
+ });
}
/**
@@ -442,11 +458,12 @@
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- try {
- mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
+ }
+ });
}
/**
@@ -485,11 +502,12 @@
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
- try {
- mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
+ }
+ });
}
/**
@@ -508,11 +526,12 @@
mDeviceBusy = false;
}
- try {
- mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
+ }
+ });
}
/**
@@ -526,11 +545,12 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
- try {
- mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
+ }
+ });
}
/**
@@ -544,11 +564,13 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
- try {
- mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
+ }
+ });
}
/**
@@ -564,12 +586,14 @@
if (!address.equals(mDevice.getAddress())) {
return;
}
- try {
- mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
- timeout, status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception in callback", ex);
- }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
+ timeout, status);
+ }
+ });
}
};
@@ -659,11 +683,12 @@
* @return If true, the callback will be called to notify success or failure,
* false on immediate error
*/
- private boolean registerApp(BluetoothGattCallback callback) {
+ private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
if (DBG) Log.d(TAG, "registerApp()");
if (mService == null) return false;
mCallback = callback;
+ mHandler = handler;
UUID uuid = UUID.randomUUID();
if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
@@ -716,7 +741,8 @@
* device becomes available (true).
* @return true, if the connection attempt was initiated successfully
*/
- /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
+ /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
+ Handler handler) {
if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
synchronized(mStateLock) {
if (mConnState != CONN_STATE_IDLE) {
@@ -727,7 +753,7 @@
mAutoConnect = autoConnect;
- if (!registerApp(callback)) {
+ if (!registerApp(callback, handler)) {
synchronized(mStateLock) {
mConnState = CONN_STATE_IDLE;
}
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 11a15c6..c6f82ff 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -30,7 +30,8 @@
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
* @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param status status of the operation
+ * @param status Status of the PHY update operation.
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
*/
public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
}
@@ -43,7 +44,8 @@
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
* @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
- * @param status status of the operation
+ * @param status Status of the PHY read operation.
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
*/
public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
}
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 3b8f962..02307bd 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -167,7 +167,8 @@
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
* @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param status status of the operation
+ * @param status Status of the PHY update operation.
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
*/
public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
}
@@ -180,7 +181,8 @@
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
* @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
* {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
- * @param status status of the operation
+ * @param status Status of the PHY read operation.
+ * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
*/
public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
}
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 87a2b05..9ce2a5b 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -33,4 +33,20 @@
* @hide
*/
public abstract boolean satisfiedBy(NetworkSpecifier other);
+
+ /**
+ * Optional method which can be overriden by concrete implementations of NetworkSpecifier to
+ * check a self-reported UID. A concrete implementation may contain a UID which would be self-
+ * reported by the caller (since NetworkSpecifier implementations should be non-mutable). This
+ * function is called by ConnectivityService and is passed the actual UID of the caller -
+ * allowing the verification of the self-reported UID. In cases of mismatch the implementation
+ * should throw a SecurityException.
+ *
+ * @param requestorUid The UID of the requestor as obtained from its binder.
+ *
+ * @hide
+ */
+ public void assertValidFromUid(int requestorUid) {
+ // empty
+ }
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 616a8c0..88bc54d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -49,7 +49,6 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.PacketKeepalive;
@@ -70,6 +69,7 @@
import android.net.NetworkMisc;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.Proxy;
@@ -110,7 +110,6 @@
import android.util.LocalLog;
import android.util.LocalLog.ReadOnlyLocalLog;
import android.util.Log;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -4131,6 +4130,18 @@
0, 0, thresholds);
}
+ private void ensureValidNetworkSpecifier(NetworkCapabilities nc) {
+ if (nc == null) {
+ return;
+ }
+ NetworkSpecifier ns = nc.getNetworkSpecifier();
+ if (ns == null) {
+ return;
+ }
+ MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns);
+ ns.assertValidFromUid(Binder.getCallingUid());
+ }
+
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
@@ -4156,9 +4167,7 @@
if (timeoutMs < 0) {
throw new IllegalArgumentException("Bad timeout specified");
}
-
- MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
- networkCapabilities.getNetworkSpecifier());
+ ensureValidNetworkSpecifier(networkCapabilities);
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId(), type);
@@ -4230,9 +4239,7 @@
enforceNetworkRequestPermissions(networkCapabilities);
enforceMeteredApnPolicy(networkCapabilities);
ensureRequestableCapabilities(networkCapabilities);
-
- MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
- networkCapabilities.getNetworkSpecifier());
+ ensureValidNetworkSpecifier(networkCapabilities);
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
@@ -4294,9 +4301,7 @@
// can't request networks.
nc.addCapability(NET_CAPABILITY_FOREGROUND);
}
-
- MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
- networkCapabilities.getNetworkSpecifier());
+ ensureValidNetworkSpecifier(networkCapabilities);
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
@@ -4314,9 +4319,7 @@
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
-
- MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(
- networkCapabilities.getNetworkSpecifier());
+ ensureValidNetworkSpecifier(networkCapabilities);
NetworkRequest networkRequest = new NetworkRequest(
new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(),
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fb07478..5d222d4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5037,32 +5037,46 @@
/* <p>Requires permission:
* @link android.Manifest.permission#CALL_PHONE}
+ * @param ussdRequest the USSD command to be executed.
+ * @param wrappedCallback receives a callback result.
*/
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public void sendUssdRequest(String ussdRequest,
final OnReceiveUssdResponseCallback callback, Handler handler) {
- checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
+ sendUssdRequest(ussdRequest, getSubId(), callback, handler);
+ }
- ResultReceiver wrappedCallback = new ResultReceiver(handler) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
- Rlog.d(TAG, "USSD:" + resultCode);
- checkNotNull(ussdResponse, "ussdResponse cannot be null.");
- UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
+ /* <p>Requires permission:
+ * @link android.Manifest.permission#CALL_PHONE}
+ * @param subId The subscription to use.
+ * @param ussdRequest the USSD command to be executed.
+ * @param wrappedCallback receives a callback result.
+ */
+ @RequiresPermission(android.Manifest.permission.CALL_PHONE)
+ public void sendUssdRequest(String ussdRequest, int subId,
+ final OnReceiveUssdResponseCallback callback, Handler handler) {
+ checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
- if (resultCode == USSD_RETURN_SUCCESS) {
- callback.onReceiveUssdResponse(response.getUssdRequest(),
- response.getReturnMessage());
- } else {
- callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
- }
- }
+ ResultReceiver wrappedCallback = new ResultReceiver(handler) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
+ Rlog.d(TAG, "USSD:" + resultCode);
+ checkNotNull(ussdResponse, "ussdResponse cannot be null.");
+ UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
+
+ if (resultCode == USSD_RETURN_SUCCESS) {
+ callback.onReceiveUssdResponse(response.getUssdRequest(),
+ response.getReturnMessage());
+ } else {
+ callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
+ }
+ }
};
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- telephony.handleUssdRequest(ussdRequest, wrappedCallback);
+ telephony.handleUssdRequest(subId, ussdRequest, wrappedCallback);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#sendUSSDCode", e);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2be0597..6b9c81d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -278,10 +278,11 @@
/**
* Handles USSD commands.
*
+ * @param subId The subscription to use.
* @param ussdRequest the USSD command to be executed.
* @param wrappedCallback receives a callback result.
*/
- void handleUssdRequest(String ussdRequest, in ResultReceiver wrappedCallback);
+ void handleUssdRequest(int subId, String ussdRequest, in ResultReceiver wrappedCallback);
/**
* Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1be8d5e..5173278 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -1993,6 +1993,40 @@
}
@SmallTest
+ public void testNetworkSpecifierUidSpoofSecurityException() {
+ class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+ @Override
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ return true;
+ }
+
+ @Override
+ public void assertValidFromUid(int requestorUid) {
+ throw new SecurityException("failure");
+ }
+
+ @Override
+ public int describeContents() { return 0; }
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {}
+ }
+
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+
+ UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
+ NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
+ networkSpecifier).build();
+ TestNetworkCallback networkCallback = new TestNetworkCallback();
+ try {
+ mCm.requestNetwork(networkRequest, networkCallback);
+ fail("Network request with spoofed UID did not throw a SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @SmallTest
public void testRegisterDefaultNetworkCallback() throws Exception {
final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 3fcbd4b..b9ce61c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -31,6 +31,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
@@ -453,7 +454,8 @@
peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
null, // peerMac (not used in this method)
pmk,
- passphrase);
+ passphrase,
+ Process.myUid());
}
/** @hide */
@@ -490,7 +492,8 @@
0, // 0 is an invalid peer ID
peer,
pmk,
- passphrase);
+ passphrase,
+ Process.myUid());
}
private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub {
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index 5993480..e152f6c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -19,6 +19,7 @@
import android.net.NetworkSpecifier;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Log;
import java.util.Arrays;
import java.util.Objects;
@@ -115,9 +116,18 @@
*/
public final String passphrase;
+ /**
+ * The UID of the process initializing this network specifier. Validated by receiver using
+ * checkUidIfNecessary() and is used by satisfiedBy() to determine whether matches the
+ * offered network.
+ *
+ * @hide
+ */
+ public final int requestorUid;
+
/** @hide */
public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId,
- byte[] peerMac, byte[] pmk, String passphrase) {
+ byte[] peerMac, byte[] pmk, String passphrase, int requestorUid) {
this.type = type;
this.role = role;
this.clientId = clientId;
@@ -126,6 +136,7 @@
this.peerMac = peerMac;
this.pmk = pmk;
this.passphrase = passphrase;
+ this.requestorUid = requestorUid;
}
public static final Creator<WifiAwareNetworkSpecifier> CREATOR =
@@ -140,7 +151,8 @@
in.readInt(), // peerId
in.createByteArray(), // peerMac
in.createByteArray(), // pmk
- in.readString()); // passphrase
+ in.readString(), // passphrase
+ in.readInt()); // requestorUid
}
@Override
@@ -164,6 +176,7 @@
dest.writeByteArray(peerMac);
dest.writeByteArray(pmk);
dest.writeString(passphrase);
+ dest.writeInt(requestorUid);
}
/** @hide */
@@ -186,6 +199,7 @@
result = 31 * result + Arrays.hashCode(peerMac);
result = 31 * result + Arrays.hashCode(pmk);
result = 31 * result + Objects.hashCode(passphrase);
+ result = 31 * result + requestorUid;
return result;
}
@@ -210,7 +224,8 @@
&& peerId == lhs.peerId
&& Arrays.equals(peerMac, lhs.peerMac)
&& Arrays.equals(pmk, lhs.pmk)
- && Objects.equals(passphrase, lhs.passphrase);
+ && Objects.equals(passphrase, lhs.passphrase)
+ && requestorUid == lhs.requestorUid;
}
/** @hide */
@@ -228,7 +243,16 @@
.append(", pmk=").append((pmk == null) ? "<null>" : "<non-null>")
// masking PII
.append(", passphrase=").append((passphrase == null) ? "<null>" : "<non-null>")
+ .append(", requestorUid=").append(requestorUid)
.append("]");
return sb.toString();
}
+
+ /** @hide */
+ @Override
+ public void assertValidFromUid(int requestorUid) {
+ if (this.requestorUid != requestorUid) {
+ throw new SecurityException("mismatched UIDs");
+ }
+ }
}