summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt16
-rw-r--r--api/system-current.txt20
-rw-r--r--api/test-current.txt16
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java35
-rw-r--r--core/java/android/bluetooth/IBluetoothGatt.aidl3
-rw-r--r--core/java/android/bluetooth/le/AdvertisingSet.java18
-rw-r--r--core/java/android/bluetooth/le/AdvertisingSetCallback.java11
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeAdvertiser.java11
-rw-r--r--core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl1
-rw-r--r--core/java/android/net/ConnectivityManager.java122
-rw-r--r--core/java/android/net/IConnectivityManager.aidl11
-rw-r--r--core/java/android/net/IpSecManager.java17
-rw-r--r--media/java/android/media/session/ICallback.aidl34
-rw-r--r--media/java/android/media/session/ISessionManager.aidl5
-rw-r--r--media/java/android/media/session/MediaSessionManager.java135
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java113
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java42
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java46
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java151
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java22
-rw-r--r--tests/net/java/com/android/server/connectivity/TetheringTest.java58
-rw-r--r--wifi/java/android/net/wifi/aware/DiscoverySession.java33
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java142
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java234
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareSession.java50
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java109
27 files changed, 990 insertions, 466 deletions
diff --git a/Android.mk b/Android.mk
index 1aaa09a40ffd..77ab10bfe94d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -404,6 +404,7 @@ LOCAL_SRC_FILES += \
media/java/android/media/projection/IMediaProjectionManager.aidl \
media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl \
media/java/android/media/session/IActiveSessionsListener.aidl \
+ media/java/android/media/session/ICallback.aidl \
media/java/android/media/session/ISessionController.aidl \
media/java/android/media/session/ISessionControllerCallback.aidl \
media/java/android/media/session/ISession.aidl \
diff --git a/api/current.txt b/api/current.txt
index 22583b3600ea..883d9866f1d5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23888,14 +23888,10 @@ package android.net {
}
public final class IpSecManager {
- method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
- method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
- method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
- method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
- method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+ method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -23914,7 +23910,7 @@ package android.net {
}
public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
- method public void close();
+ method public void close() throws java.io.IOException;
method public int getPort();
method public java.io.FileDescriptor getSocket();
}
@@ -25124,8 +25120,8 @@ package android.net.wifi.aware {
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
- method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -25211,8 +25207,8 @@ package android.net.wifi.aware {
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
- method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
diff --git a/api/system-current.txt b/api/system-current.txt
index 1cb83f19ae34..3b61bdd08cb1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -25726,14 +25726,10 @@ package android.net {
}
public final class IpSecManager {
- method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
- method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
- method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
- method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
- method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+ method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -25752,7 +25748,7 @@ package android.net {
}
public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
- method public void close();
+ method public void close() throws java.io.IOException;
method public int getPort();
method public java.io.FileDescriptor getSocket();
}
@@ -27680,9 +27676,9 @@ package android.net.wifi.aware {
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
- method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
- method public java.lang.String createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -27768,9 +27764,9 @@ package android.net.wifi.aware {
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
- method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
- method public java.lang.String createNetworkSpecifierPmk(int, byte[], byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, byte[], byte[]);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
diff --git a/api/test-current.txt b/api/test-current.txt
index b7e86131375f..61a65d8bf456 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -23962,14 +23962,10 @@ package android.net {
}
public final class IpSecManager {
- method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
- method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
- method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
- method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
- method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+ method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -23988,7 +23984,7 @@ package android.net {
}
public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
- method public void close();
+ method public void close() throws java.io.IOException;
method public int getPort();
method public java.io.FileDescriptor getSocket();
}
@@ -25198,8 +25194,8 @@ package android.net.wifi.aware {
}
public class DiscoverySession {
- method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
- method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
method public void destroy();
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -25285,8 +25281,8 @@ package android.net.wifi.aware {
}
public class WifiAwareSession {
- method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
- method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
method public void destroy();
method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 1a969b9ca722..9144ae722911 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -947,6 +947,41 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
+ * Reads the characteristic using its UUID from the associated remote device.
+ *
+ * <p>This is an asynchronous operation. The result of the read operation
+ * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
+ * callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param uuid UUID of characteristic to read from the remote device
+ * @return true, if the read operation was initiated successfully
+ * @hide
+ */
+ public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) {
+ if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid);
+ if (mService == null || mClientIf == 0) return false;
+
+ synchronized(mDeviceBusy) {
+ if (mDeviceBusy) return false;
+ mDeviceBusy = true;
+ }
+
+ try {
+ mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(),
+ new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ mDeviceBusy = false;
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
* Writes a given characteristic and its values to the associated remote device.
*
* <p>Once the write operation has been completed, the
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 334e88b69fde..a2066cb4991e 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -56,6 +56,7 @@ interface IBluetoothGatt {
in IAdvertisingSetCallback callback);
void stopAdvertisingSet(in IAdvertisingSetCallback callback);
+ void getOwnAddress(in int advertiserId);
void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents);
void setAdvertisingData(in int advertiserId, in AdvertiseData data);
void setScanResponseData(in int advertiserId, in AdvertiseData data);
@@ -77,6 +78,8 @@ interface IBluetoothGatt {
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
+ void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
+ in int startHandle, in int endHandle, in int authReq);
void writeCharacteristic(in int clientIf, in String address, in int handle,
in int writeType, in int authReq, in byte[] value);
void readDescriptor(in int clientIf, in String address, in int handle, in int authReq);
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index 51571b2746a4..3021be1f8c02 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -181,7 +181,23 @@ public final class AdvertisingSet {
}
/**
- * Returns advertiserId associated with thsi advertising set.
+ * Returns address associated with this advertising set.
+ * This method is exposed only for Bluetooth PTS tests, no app or system service
+ * should ever use it.
+ *
+ * This method requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission.
+ * @hide
+ */
+ public void getOwnAddress(){
+ try {
+ gatt.getOwnAddress(this.advertiserId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "remote exception - ", e);
+ }
+ }
+
+ /**
+ * Returns advertiserId associated with this advertising set.
*
* @hide
*/
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
index fe3b1cdd63a0..2c46e856db4a 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
@@ -143,4 +143,15 @@ public abstract class AdvertisingSetCallback {
*/
public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable,
int status) {}
+
+ /**
+ * Callback triggered in response to {@link AdvertisingSet#getOwnAddress()}
+ * indicating result of the operation.
+ *
+ * @param advertisingSet The advertising set.
+ * @param addressType type of address.
+ * @param address advertising set bluetooth address.
+ * @hide
+ */
+ public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, String address) {}
} \ No newline at end of file
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index ea3031b20177..21e9497daa62 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -545,6 +545,17 @@ public final class BluetoothLeAdvertiser {
}
@Override
+ public void onOwnAddressRead(int advertiserId, int addressType, String address) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
+ callback.onOwnAddressRead(advertisingSet, addressType, address);
+ }
+ });
+ }
+
+ @Override
public void onAdvertisingSetStopped(int advertiserId) {
handler.post(new Runnable() {
@Override
diff --git a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
index 2c9f4baad520..3628c775b798 100644
--- a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
+++ b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
@@ -21,6 +21,7 @@ package android.bluetooth.le;
*/
oneway interface IAdvertisingSetCallback {
void onAdvertisingSetStarted(in int advertiserId, in int tx_power, in int status);
+ void onOwnAddressRead(in int advertiserId, in int addressType, in String address);
void onAdvertisingSetStopped(in int advertiserId);
void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
void onAdvertisingDataSet(in int advertiserId, in int status);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 0e5d049c7891..efa195983f94 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -48,7 +48,6 @@ import android.util.SparseIntArray;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.util.MessageUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Protocol;
@@ -302,7 +301,8 @@ public class ConnectivityManager {
/**
* Broadcast Action: A tetherable connection has come or gone.
* Uses {@code ConnectivityManager.EXTRA_AVAILABLE_TETHER},
- * {@code ConnectivityManager.EXTRA_ACTIVE_TETHER} and
+ * {@code ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY},
+ * {@code ConnectivityManager.EXTRA_ACTIVE_TETHER}, and
* {@code ConnectivityManager.EXTRA_ERRORED_TETHER} to indicate
* the current state of tethering. Each include a list of
* interface names in that state (may be empty).
@@ -321,10 +321,17 @@ public class ConnectivityManager {
/**
* @hide
+ * gives a String[] listing all the interfaces currently in local-only
+ * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
+ */
+ public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
+
+ /**
+ * @hide
* gives a String[] listing all the interfaces currently tethered
- * (ie, has dhcp support and packets potentially forwarded/NATed)
+ * (ie, has DHCPv4 support and packets potentially forwarded/NATed)
*/
- public static final String EXTRA_ACTIVE_TETHER = "activeArray";
+ public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
/**
* @hide
@@ -1863,8 +1870,12 @@ public class ConnectivityManager {
.getPackageNameForUid(context, uid), true /* throwException */);
}
- /** {@hide */
- public static final void enforceTetherChangePermission(Context context) {
+ /** {@hide} */
+ public static final void enforceTetherChangePermission(Context context, String callingPkg) {
+ if (null == context || null == callingPkg) {
+ throw new IllegalArgumentException("arguments should not be null");
+ }
+
if (context.getResources().getStringArray(
com.android.internal.R.array.config_mobile_hotspot_provision_app).length == 2) {
// Have a provisioning app - must only let system apps (which check this app)
@@ -1873,8 +1884,10 @@ public class ConnectivityManager {
android.Manifest.permission.TETHER_PRIVILEGED, "ConnectivityService");
} else {
int uid = Binder.getCallingUid();
- Settings.checkAndNoteWriteSettingsOperation(context, uid, Settings
- .getPackageNameForUid(context, uid), true /* throwException */);
+ // If callingPkg's uid is not same as Binder.getCallingUid(),
+ // AppOpsService throws SecurityException.
+ Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPkg,
+ true /* throwException */);
}
}
@@ -1997,7 +2010,9 @@ public class ConnectivityManager {
*/
public int tether(String iface) {
try {
- return mService.tether(iface);
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "tether caller:" + pkgName);
+ return mService.tether(iface, pkgName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2023,7 +2038,9 @@ public class ConnectivityManager {
*/
public int untether(String iface) {
try {
- return mService.untether(iface);
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "untether caller:" + pkgName);
+ return mService.untether(iface, pkgName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2114,7 +2131,9 @@ public class ConnectivityManager {
};
try {
- mService.startTethering(type, wrappedCallback, showProvisioningUi);
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "startTethering caller:" + pkgName);
+ mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName);
} catch (RemoteException e) {
Log.e(TAG, "Exception trying to start tethering.", e);
wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);
@@ -2134,7 +2153,9 @@ public class ConnectivityManager {
@SystemApi
public void stopTethering(int type) {
try {
- mService.stopTethering(type);
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "stopTethering caller:" + pkgName);
+ mService.stopTethering(type, pkgName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2219,7 +2240,9 @@ public class ConnectivityManager {
*/
public int setUsbTethering(boolean enable) {
try {
- return mService.setUsbTethering(enable);
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "setUsbTethering caller:" + pkgName);
+ return mService.setUsbTethering(enable, pkgName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2693,18 +2716,12 @@ public class ConnectivityManager {
public static final int CALLBACK_CAP_CHANGED = BASE + 6;
/** @hide */
public static final int CALLBACK_IP_CHANGED = BASE + 7;
- // TODO: consider deleting CALLBACK_RELEASED and shifting following enum codes down by 1.
- /** @hide */
- public static final int CALLBACK_RELEASED = BASE + 8;
- // TODO: consider deleting CALLBACK_EXIT and shifting following enum codes down by 1.
- /** @hide */
- public static final int CALLBACK_EXIT = BASE + 9;
/** @hide obj = NetworkCapabilities, arg1 = seq number */
- private static final int EXPIRE_LEGACY_REQUEST = BASE + 10;
+ private static final int EXPIRE_LEGACY_REQUEST = BASE + 8;
/** @hide */
- public static final int CALLBACK_SUSPENDED = BASE + 11;
+ public static final int CALLBACK_SUSPENDED = BASE + 9;
/** @hide */
- public static final int CALLBACK_RESUMED = BASE + 12;
+ public static final int CALLBACK_RESUMED = BASE + 10;
/** @hide */
public static String getCallbackName(int whichCallback) {
@@ -2716,8 +2733,6 @@ public class ConnectivityManager {
case CALLBACK_UNAVAIL: return "CALLBACK_UNAVAIL";
case CALLBACK_CAP_CHANGED: return "CALLBACK_CAP_CHANGED";
case CALLBACK_IP_CHANGED: return "CALLBACK_IP_CHANGED";
- case CALLBACK_RELEASED: return "CALLBACK_RELEASED";
- case CALLBACK_EXIT: return "CALLBACK_EXIT";
case EXPIRE_LEGACY_REQUEST: return "EXPIRE_LEGACY_REQUEST";
case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED";
case CALLBACK_RESUMED: return "CALLBACK_RESUMED";
@@ -2743,46 +2758,46 @@ public class ConnectivityManager {
NetworkRequest request = getObject(message, NetworkRequest.class);
Network network = getObject(message, Network.class);
if (DBG) {
- Log.d(TAG, whatToString(message.what) + " for network " + network);
+ Log.d(TAG, getCallbackName(message.what) + " for network " + network);
}
switch (message.what) {
case CALLBACK_PRECHECK: {
- NetworkCallback callback = getCallback(request, "PRECHECK");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
callback.onPreCheck(network);
}
break;
}
case CALLBACK_AVAILABLE: {
- NetworkCallback callback = getCallback(request, "AVAILABLE");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
callback.onAvailable(network);
}
break;
}
case CALLBACK_LOSING: {
- NetworkCallback callback = getCallback(request, "LOSING");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
callback.onLosing(network, message.arg1);
}
break;
}
case CALLBACK_LOST: {
- NetworkCallback callback = getCallback(request, "LOST");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
callback.onLost(network);
}
break;
}
case CALLBACK_UNAVAIL: {
- NetworkCallback callback = getCallback(request, "UNAVAIL");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
callback.onUnavailable();
}
break;
}
case CALLBACK_CAP_CHANGED: {
- NetworkCallback callback = getCallback(request, "CAP_CHANGED");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
callback.onCapabilitiesChanged(network, cap);
@@ -2790,7 +2805,7 @@ public class ConnectivityManager {
break;
}
case CALLBACK_IP_CHANGED: {
- NetworkCallback callback = getCallback(request, "IP_CHANGED");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
LinkProperties lp = getObject(message, LinkProperties.class);
callback.onLinkPropertiesChanged(network, lp);
@@ -2798,25 +2813,19 @@ public class ConnectivityManager {
break;
}
case CALLBACK_SUSPENDED: {
- NetworkCallback callback = getCallback(request, "SUSPENDED");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
callback.onNetworkSuspended(network);
}
break;
}
case CALLBACK_RESUMED: {
- NetworkCallback callback = getCallback(request, "RESUMED");
+ NetworkCallback callback = getCallback(message);
if (callback != null) {
callback.onNetworkResumed(network);
}
break;
}
- case CALLBACK_RELEASED: {
- break;
- }
- case CALLBACK_EXIT: {
- break;
- }
case EXPIRE_LEGACY_REQUEST: {
expireRequest((NetworkCapabilities)message.obj, message.arg1);
break;
@@ -2828,13 +2837,14 @@ public class ConnectivityManager {
return (T) msg.getData().getParcelable(c.getSimpleName());
}
- private NetworkCallback getCallback(NetworkRequest req, String name) {
+ private NetworkCallback getCallback(Message msg) {
+ final NetworkRequest req = getObject(msg, NetworkRequest.class);
final NetworkCallback callback;
synchronized(sCallbacks) {
callback = sCallbacks.get(req);
}
if (callback == null) {
- Log.w(TAG, "callback not found for " + name + " message");
+ Log.w(TAG, "callback not found for " + getCallbackName(msg.what) + " message");
}
return callback;
}
@@ -3721,32 +3731,4 @@ public class ConnectivityManager {
throw e.rethrowFromSystemServer();
}
}
-
- /**
- * A holder class for debug info (mapping CALLBACK values to field names). This is stored
- * in a holder for two reasons:
- * 1) The reflection necessary to establish the map can't be run at compile-time. Thus, this
- * code will make the enclosing class not compile-time initializeable, deferring its
- * initialization to zygote startup. This leads to dirty (but shared) memory.
- * As this is debug info, use a holder that isn't initialized by default. This way the map
- * will be created on demand, while ConnectivityManager can be compile-time initialized.
- * 2) Static initialization is still preferred for its strong thread safety guarantees without
- * requiring a lock.
- */
- private static class NoPreloadHolder {
- public static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
- new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"});
- }
-
- static {
- // When debug is enabled, aggressively initialize the holder by touching the field (which
- // will guarantee static initialization).
- if (CallbackHandler.DBG) {
- Object dummy = NoPreloadHolder.sMagicDecoderRing;
- }
- }
-
- private static final String whatToString(int what) {
- return NoPreloadHolder.sMagicDecoderRing.get(what, Integer.toString(what));
- }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 425e49407827..63a1f0513e20 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -69,17 +69,18 @@ interface IConnectivityManager
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
- int tether(String iface);
+ int tether(String iface, String callerPkg);
- int untether(String iface);
+ int untether(String iface, String callerPkg);
int getLastTetherError(String iface);
boolean isTetheringSupported();
- void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi);
+ void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
+ String callerPkg);
- void stopTethering(int type);
+ void stopTethering(int type, String callerPkg);
String[] getTetherableIfaces();
@@ -95,7 +96,7 @@ interface IConnectivityManager
String[] getTetherableBluetoothRegexs();
- int setUsbTethering(boolean enable);
+ int setUsbTethering(boolean enable, String callerPkg);
void reportInetCondition(int networkType, int percentage);
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index f8702e2e00e7..375b7eeb013a 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -245,6 +245,7 @@ public final class IpSecManager {
*
* @param socket a stream socket
* @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+ * @hide
*/
public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
throws IOException {
@@ -262,6 +263,7 @@ public final class IpSecManager {
*
* @param socket a datagram socket
* @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+ * @hide
*/
public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
throws IOException {
@@ -284,7 +286,7 @@ public final class IpSecManager {
* address associated with that transform will throw an IOException. In addition, if the
* IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
* send() or receive() until the transform is removed from the socket by calling {@link
- * #removeTransportModeTransform(Socket, IpSecTransform)};
+ * #removeTransportModeTransform(FileDescriptor, IpSecTransform)};
*
* @param socket a socket file descriptor
* @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
@@ -316,8 +318,10 @@ public final class IpSecManager {
*
* @param socket a socket that previously had a transform applied to it.
* @param transform the IPsec Transform that was previously applied to the given socket
+ * @hide
*/
- public void removeTransportModeTransform(Socket socket, IpSecTransform transform) {
+ public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
+ throws IOException {
removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
}
@@ -330,8 +334,10 @@ public final class IpSecManager {
*
* @param socket a socket that previously had a transform applied to it.
* @param transform the IPsec Transform that was previously applied to the given socket
+ * @hide
*/
- public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) {
+ public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
+ throws IOException {
removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
}
@@ -345,7 +351,8 @@ public final class IpSecManager {
* @param socket a socket file descriptor that previously had a transform applied to it.
* @param transform the IPsec Transform that was previously applied to the given socket
*/
- public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) {
+ public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
+ throws IOException {
removeTransportModeTransform(new ParcelFileDescriptor(socket), transform);
}
@@ -419,7 +426,7 @@ public final class IpSecManager {
*
* @param fd a file descriptor previously returned as a UDP Encapsulation socket.
*/
- public void close() {
+ public void close() throws IOException {
// TODO: Go close the socket
mCloseGuard.close();
}
diff --git a/media/java/android/media/session/ICallback.aidl b/media/java/android/media/session/ICallback.aidl
new file mode 100644
index 000000000000..bb8a3cc9b139
--- /dev/null
+++ b/media/java/android/media/session/ICallback.aidl
@@ -0,0 +1,34 @@
+/* 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.media.session;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.media.session.MediaSession;
+import android.view.KeyEvent;
+
+/**
+ * @hide
+ */
+oneway interface ICallback {
+ void onMediaKeyEventDispatchedToMediaSession(in KeyEvent event,
+ in MediaSession.Token sessionToken);
+ void onMediaKeyEventDispatchedToMediaButtonReceiver(in KeyEvent event,
+ in ComponentName mediaButtonReceiver);
+
+ void onAddressedPlayerChangedToMediaSession(in MediaSession.Token sessionToken);
+ void onAddressedPlayerChangedToMediaButtonReceiver(in ComponentName mediaButtonReceiver);
+}
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index bb59e5b4be35..575e7d784a3f 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -18,6 +18,7 @@ package android.media.session;
import android.content.ComponentName;
import android.media.IRemoteVolumeController;
import android.media.session.IActiveSessionsListener;
+import android.media.session.ICallback;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.os.Bundle;
@@ -41,4 +42,6 @@ interface ISessionManager {
// For PhoneWindowManager to precheck media keys
boolean isGlobalPriorityActive();
-} \ No newline at end of file
+
+ void setCallback(in ICallback callback);
+}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 2364a13e6385..31e60da7fb7a 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -57,6 +57,8 @@ public final class MediaSessionManager {
private Context mContext;
+ private CallbackImpl mCallback;
+
/**
* @hide
*/
@@ -313,6 +315,36 @@ public final class MediaSessionManager {
}
/**
+ * Set a {@link Callback}.
+ *
+ * <p>System can only have a single callback, and the callback can only be set by
+ * Bluetooth service process.
+ *
+ * @param callback A {@link Callback}. {@code null} to reset.
+ * @param handler The handler on which the callback should be invoked, or {@code null}
+ * if the callback should be invoked on the calling thread's looper.
+ * @hide
+ */
+ public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
+ synchronized (mLock) {
+ try {
+ if (callback == null) {
+ mCallback = null;
+ mService.setCallback(null);
+ } else {
+ if (handler == null) {
+ handler = new Handler();
+ }
+ mCallback = new CallbackImpl(callback, handler);
+ mService.setCallback(mCallback);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set media key callback", e);
+ }
+ }
+ }
+
+ /**
* Listens for changes to the list of active sessions. This can be added
* using {@link #addOnActiveSessionsChangedListener}.
*/
@@ -320,6 +352,56 @@ public final class MediaSessionManager {
public void onActiveSessionsChanged(@Nullable List<MediaController> controllers);
}
+ /**
+ * Callbacks for the media session service.
+ *
+ * <p>Called when a media key event is dispatched or the addressed player is changed.
+ * The addressed player is either the media session or the media button receiver that will
+ * receive media key events.
+ * @hide
+ */
+ public static abstract class Callback {
+ /**
+ * Called when a media key event is dispatched to the media session
+ * through the media session service.
+ *
+ * @param event Dispatched media key event.
+ * @param sessionToken The media session's token.
+ */
+ public abstract void onMediaKeyEventDispatched(KeyEvent event,
+ MediaSession.Token sessionToken);
+
+ /**
+ * Called when a media key event is dispatched to the media button receiver
+ * through the media session service.
+ * <p>MediaSessionService may broadcast key events to the media button receiver
+ * when reviving playback after the media session is released.
+ *
+ * @param event Dispatched media key event.
+ * @param mediaButtonReceiver The media button receiver.
+ */
+ public abstract void onMediaKeyEventDispatched(KeyEvent event,
+ ComponentName mediaButtonReceiver);
+
+ /**
+ * Called when the addressed player is changed to a media session.
+ * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
+ * {@link #setCallback} if the addressed player exists.
+ *
+ * @param sessionToken The media session's token.
+ */
+ public abstract void onAddressedPlayerChanged(MediaSession.Token sessionToken);
+
+ /**
+ * Called when the addressed player is changed to the media button receiver.
+ * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
+ * {@link #setCallback} if the addressed player exists.
+ *
+ * @param mediaButtonReceiver The media button receiver.
+ */
+ public abstract void onAddressedPlayerChanged(ComponentName mediaButtonReceiver);
+ }
+
private static final class SessionsChangedWrapper {
private Context mContext;
private OnActiveSessionsChangedListener mListener;
@@ -360,4 +442,57 @@ public final class MediaSessionManager {
mHandler = null;
}
}
+
+ private static final class CallbackImpl extends ICallback.Stub {
+ private final Callback mCallback;
+ private final Handler mHandler;
+
+ public CallbackImpl(@NonNull Callback callback, @NonNull Handler handler) {
+ mCallback = callback;
+ mHandler = handler;
+ }
+
+ @Override
+ public void onMediaKeyEventDispatchedToMediaSession(KeyEvent event,
+ MediaSession.Token sessionToken) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onMediaKeyEventDispatched(event, sessionToken);
+ }
+ });
+ }
+
+ @Override
+ public void onMediaKeyEventDispatchedToMediaButtonReceiver(KeyEvent event,
+ ComponentName mediaButtonReceiver) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onMediaKeyEventDispatched(event, mediaButtonReceiver);
+ }
+ });
+ }
+
+ @Override
+ public void onAddressedPlayerChangedToMediaSession(MediaSession.Token sessionToken) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onAddressedPlayerChanged(sessionToken);
+ }
+ });
+ }
+
+ @Override
+ public void onAddressedPlayerChangedToMediaButtonReceiver(
+ ComponentName mediaButtonReceiver) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mCallback.onAddressedPlayerChanged(mediaButtonReceiver);
+ }
+ });
+ }
+ }
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a2293a777afc..56fa420aa7d4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -36,6 +36,7 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.uidRulesToString;
+import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.Nullable;
import android.app.BroadcastOptions;
@@ -92,6 +93,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -2549,25 +2551,32 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) {
- if (mNetworkRequests.get(nri.request) != null && mNetworkForRequestId.get(
- nri.request.requestId) == null) {
- handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_UNAVAIL);
+ if (mNetworkRequests.get(nri.request) == null) {
+ return;
+ }
+ if (mNetworkForRequestId.get(nri.request.requestId) != null) {
+ return;
}
+ if (VDBG || (DBG && nri.request.isRequest())) {
+ log("releasing " + nri.request + " (timeout)");
+ }
+ handleRemoveNetworkRequest(nri);
+ callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
}
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
- final NetworkRequestInfo nri = getNriForAppRequest(
- request, callingUid, "release NetworkRequest");
- if (nri != null) {
- handleRemoveNetworkRequest(nri, ConnectivityManager.CALLBACK_RELEASED);
+ final NetworkRequestInfo nri =
+ getNriForAppRequest(request, callingUid, "release NetworkRequest");
+ if (nri == null) {
+ return;
}
- }
-
- private void handleRemoveNetworkRequest(final NetworkRequestInfo nri, final int whichCallback) {
- final String logCallbackType = ConnectivityManager.getCallbackName(whichCallback);
if (VDBG || (DBG && nri.request.isRequest())) {
- log("releasing " + nri.request + " (" + logCallbackType + ")");
+ log("releasing " + nri.request + " (release request)");
}
+ handleRemoveNetworkRequest(nri);
+ }
+
+ private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
nri.unlinkDeathRecipient();
mNetworkRequests.remove(nri.request);
synchronized (mUidToNetworkRequestCount) {
@@ -2663,7 +2672,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
}
- callCallbackForRequest(nri, null, whichCallback, 0);
}
@Override
@@ -2948,8 +2956,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// javadoc from interface
@Override
- public int tether(String iface) {
- ConnectivityManager.enforceTetherChangePermission(mContext);
+ public int tether(String iface, String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
if (isTetheringSupported()) {
final int status = mTethering.tether(iface);
return status;
@@ -2960,8 +2968,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// javadoc from interface
@Override
- public int untether(String iface) {
- ConnectivityManager.enforceTetherChangePermission(mContext);
+ public int untether(String iface, String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
if (isTetheringSupported()) {
final int status = mTethering.untether(iface);
@@ -3015,8 +3023,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
- public int setUsbTethering(boolean enable) {
- ConnectivityManager.enforceTetherChangePermission(mContext);
+ public int setUsbTethering(boolean enable, String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
if (isTetheringSupported()) {
return mTethering.setUsbTethering(enable);
} else {
@@ -3075,8 +3083,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
- public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
- ConnectivityManager.enforceTetherChangePermission(mContext);
+ public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
+ String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
if (!isTetheringSupported()) {
receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
return;
@@ -3085,8 +3094,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
- public void stopTethering(int type) {
- ConnectivityManager.enforceTetherChangePermission(mContext);
+ public void stopTethering(int type, String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
mTethering.stopTethering(type);
}
@@ -3450,13 +3459,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
Slog.e(TAG, s);
}
- private static <T> T checkNotNull(T value, String message) {
- if (value == null) {
- throw new NullPointerException(message);
- }
- return value;
- }
-
/**
* Prepare for a VPN application.
* VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
@@ -4728,16 +4730,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
releasePendingNetworkRequestWithDelay(pendingIntent);
}
- private void callCallbackForRequest(NetworkRequestInfo nri,
+ private static void callCallbackForRequest(NetworkRequestInfo nri,
NetworkAgentInfo networkAgent, int notificationType, int arg1) {
- if (nri.messenger == null) return; // Default request has no msgr
+ if (nri.messenger == null) {
+ return; // Default request has no msgr
+ }
Bundle bundle = new Bundle();
- bundle.putParcelable(NetworkRequest.class.getSimpleName(),
- new NetworkRequest(nri.request));
+ // TODO: check if defensive copies of data is needed.
+ putParcelable(bundle, new NetworkRequest(nri.request));
Message msg = Message.obtain();
- if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL &&
- notificationType != ConnectivityManager.CALLBACK_RELEASED) {
- bundle.putParcelable(Network.class.getSimpleName(), networkAgent.network);
+ if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) {
+ putParcelable(bundle, networkAgent.network);
}
switch (notificationType) {
case ConnectivityManager.CALLBACK_LOSING: {
@@ -4745,13 +4748,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case ConnectivityManager.CALLBACK_CAP_CHANGED: {
- bundle.putParcelable(NetworkCapabilities.class.getSimpleName(),
- new NetworkCapabilities(networkAgent.networkCapabilities));
+ putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities));
break;
}
case ConnectivityManager.CALLBACK_IP_CHANGED: {
- bundle.putParcelable(LinkProperties.class.getSimpleName(),
- new LinkProperties(networkAgent.linkProperties));
+ putParcelable(bundle, new LinkProperties(networkAgent.linkProperties));
break;
}
}
@@ -4759,8 +4760,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
msg.setData(bundle);
try {
if (VDBG) {
- log("sending notification " + notifyTypeToName(notificationType) +
- " for " + nri.request);
+ String notification = ConnectivityManager.getCallbackName(notificationType);
+ log("sending notification " + notification + " for " + nri.request);
}
nri.messenger.send(msg);
} catch (RemoteException e) {
@@ -4769,6 +4770,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ private static <T extends Parcelable> void putParcelable(Bundle bundle, T t) {
+ bundle.putParcelable(t.getClass().getSimpleName(), t);
+ }
+
private void teardownUnneededNetwork(NetworkAgentInfo nai) {
if (nai.numRequestNetworkRequests() != 0) {
for (int i = 0; i < nai.numNetworkRequests(); i++) {
@@ -5370,7 +5375,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
- if (VDBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
+ if (VDBG) {
+ String notification = ConnectivityManager.getCallbackName(notifyType);
+ log("notifyType " + notification + " for " + networkAgent.name());
+ }
for (int i = 0; i < networkAgent.numNetworkRequests(); i++) {
NetworkRequest nr = networkAgent.requestAt(i);
NetworkRequestInfo nri = mNetworkRequests.get(nr);
@@ -5389,20 +5397,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
notifyNetworkCallbacks(networkAgent, notifyType, 0);
}
- private String notifyTypeToName(int notifyType) {
- switch (notifyType) {
- case ConnectivityManager.CALLBACK_PRECHECK: return "PRECHECK";
- case ConnectivityManager.CALLBACK_AVAILABLE: return "AVAILABLE";
- case ConnectivityManager.CALLBACK_LOSING: return "LOSING";
- case ConnectivityManager.CALLBACK_LOST: return "LOST";
- case ConnectivityManager.CALLBACK_UNAVAIL: return "UNAVAILABLE";
- case ConnectivityManager.CALLBACK_CAP_CHANGED: return "CAP_CHANGED";
- case ConnectivityManager.CALLBACK_IP_CHANGED: return "IP_CHANGED";
- case ConnectivityManager.CALLBACK_RELEASED: return "RELEASED";
- }
- return "UNKNOWN";
- }
-
/**
* Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
* properties tracked by NetworkStatsService on an active iface has changed.
@@ -5482,8 +5476,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
// Untether
+ String pkgName = mContext.getOpPackageName();
for (String tether : getTetheredIfaces()) {
- untether(tether);
+ untether(tether, pkgName);
}
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 1ed0c408e99b..3ae0e2065b7b 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -624,9 +624,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
private void sendTetherStateChangedBroadcast() {
if (!getConnectivityManager().isTetheringSupported()) return;
- ArrayList<String> availableList = new ArrayList<String>();
- ArrayList<String> activeList = new ArrayList<String>();
- ArrayList<String> erroredList = new ArrayList<String>();
+ final ArrayList<String> availableList = new ArrayList<>();
+ final ArrayList<String> tetherList = new ArrayList<>();
+ final ArrayList<String> localOnlyList = new ArrayList<>();
+ final ArrayList<String> erroredList = new ArrayList<>();
boolean wifiTethered = false;
boolean usbTethered = false;
@@ -642,6 +643,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
erroredList.add(iface);
} else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
availableList.add(iface);
+ } else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_HOTSPOT) {
+ localOnlyList.add(iface);
} else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
if (cfg.isUsb(iface)) {
usbTethered = true;
@@ -650,25 +653,25 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
} else if (cfg.isBluetooth(iface)) {
bluetoothTethered = true;
}
- activeList.add(iface);
+ tetherList.add(iface);
}
}
}
- Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
- broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+ final Intent bcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+ bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
- availableList);
- broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
- broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
- erroredList);
- mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
+ bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, availableList);
+ bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
+ bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, tetherList);
+ bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList);
+ mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL);
if (DBG) {
Log.d(TAG, String.format(
- "sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]",
- TextUtils.join(",", availableList),
- TextUtils.join(",", activeList),
- TextUtils.join(",", erroredList)));
+ "sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]",
+ "avail", TextUtils.join(",", availableList),
+ "local_only", TextUtils.join(",", localOnlyList),
+ "tether", TextUtils.join(",", tetherList),
+ "error", TextUtils.join(",", erroredList)));
}
if (usbTethered) {
@@ -1339,7 +1342,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
mForwardedDownstreams.remove(who);
}
- class InitialState extends TetherMasterUtilState {
+ class InitialState extends State {
@Override
public boolean processMessage(Message message) {
maybeLogMessage(this, message.what);
@@ -1517,7 +1520,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
class ErrorState extends State {
- int mErrorNotification;
+ private int mErrorNotification;
+
@Override
public boolean processMessage(Message message) {
boolean retValue = true;
@@ -1535,6 +1539,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
return retValue;
}
+
void notify(int msgType) {
mErrorNotification = msgType;
for (TetherInterfaceStateMachine sm : mNotifyList) {
@@ -1543,6 +1548,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
}
+
class SetIpForwardingEnabledErrorState extends ErrorState {
@Override
public void enter() {
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 1ffa86440ae2..601ed010a696 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -78,7 +78,6 @@ public class TetherInterfaceStateMachine extends StateMachine {
public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13;
private final State mInitialState;
- private final State mServingState;
private final State mLocalHotspotState;
private final State mTetheredState;
private final State mUnavailableState;
@@ -107,14 +106,12 @@ public class TetherInterfaceStateMachine extends StateMachine {
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
mInitialState = new InitialState();
- mServingState = new ServingState();
mLocalHotspotState = new LocalHotspotState();
mTetheredState = new TetheredState();
mUnavailableState = new UnavailableState();
addState(mInitialState);
- addState(mServingState);
- addState(mLocalHotspotState, mServingState);
- addState(mTetheredState, mServingState);
+ addState(mLocalHotspotState);
+ addState(mTetheredState);
addState(mUnavailableState);
setInitialState(mInitialState);
@@ -222,12 +219,11 @@ public class TetherInterfaceStateMachine extends StateMachine {
}
}
- class ServingState extends State {
+ class BaseServingState extends State {
@Override
public void enter() {
if (!configureIfaceIp(true)) {
mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR;
- transitionTo(mInitialState);
return;
}
@@ -236,12 +232,13 @@ public class TetherInterfaceStateMachine extends StateMachine {
} catch (Exception e) {
Log.e(TAG, "Error Tethering: " + e.toString());
mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
- transitionTo(mInitialState);
return;
}
if (!mIPv6TetherSvc.start()) {
Log.e(TAG, "Failed to start IPv6TetheringInterfaceServices");
+ // TODO: Make this a fatal error once Bluetooth IPv6 is sorted.
+ return;
}
}
@@ -254,9 +251,9 @@ public class TetherInterfaceStateMachine extends StateMachine {
try {
mNMService.untetherInterface(mIfaceName);
- } catch (Exception ee) {
+ } catch (Exception e) {
mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
- Log.e(TAG, "Failed to untether interface: " + ee.toString());
+ Log.e(TAG, "Failed to untether interface: " + e.toString());
}
configureIfaceIp(false);
@@ -293,15 +290,27 @@ public class TetherInterfaceStateMachine extends StateMachine {
}
}
- class LocalHotspotState extends State {
+ // Handling errors in BaseServingState.enter() by transitioning is
+ // problematic because transitioning during a multi-state jump yields
+ // a Log.wtf(). Ultimately, there should be only one ServingState,
+ // and forwarding and NAT rules should be handled by a coordinating
+ // functional element outside of TetherInterfaceStateMachine.
+ class LocalHotspotState extends BaseServingState {
@Override
public void enter() {
+ super.enter();
+ if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ transitionTo(mInitialState);
+ }
+
if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName);
sendInterfaceState(IControlsTethering.STATE_LOCAL_HOTSPOT);
}
@Override
public boolean processMessage(Message message) {
+ if (super.processMessage(message)) return true;
+
maybeLogMessage(this, message.what);
switch (message.what) {
case CMD_TETHER_REQUESTED:
@@ -317,9 +326,19 @@ public class TetherInterfaceStateMachine extends StateMachine {
}
}
- class TetheredState extends State {
+ // Handling errors in BaseServingState.enter() by transitioning is
+ // problematic because transitioning during a multi-state jump yields
+ // a Log.wtf(). Ultimately, there should be only one ServingState,
+ // and forwarding and NAT rules should be handled by a coordinating
+ // functional element outside of TetherInterfaceStateMachine.
+ class TetheredState extends BaseServingState {
@Override
public void enter() {
+ super.enter();
+ if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ transitionTo(mInitialState);
+ }
+
if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
sendInterfaceState(IControlsTethering.STATE_TETHERED);
}
@@ -327,6 +346,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
@Override
public void exit() {
cleanupUpstream();
+ super.exit();
}
private void cleanupUpstream() {
@@ -361,6 +381,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
@Override
public boolean processMessage(Message message) {
+ if (super.processMessage(message)) return true;
+
maybeLogMessage(this, message.what);
boolean retValue = true;
switch (message.what) {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 4c58ffd5dc83..cc41060a55eb 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -36,6 +36,7 @@ import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.IRemoteVolumeController;
import android.media.session.IActiveSessionsListener;
+import android.media.session.ICallback;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.media.session.ISessionManager;
@@ -101,6 +102,7 @@ public class MediaSessionService extends SystemService implements Monitor {
private AudioManagerInternal mAudioManagerInternal;
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
+ private ICallback mCallback;
// List of user IDs running in the foreground.
// Multiple users can be in the foreground if the work profile is on.
@@ -485,6 +487,7 @@ public class MediaSessionService extends SystemService implements Monitor {
if (size > 0 && records.get(0).isPlaybackActive(false)) {
rememberMediaButtonReceiverLocked(records.get(0));
}
+ pushAddressedPlayerChangedLocked();
ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
for (int i = 0; i < size; i++) {
tokens.add(new MediaSession.Token(records.get(i).getControllerBinder()));
@@ -516,6 +519,52 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
+ private MediaSessionRecord getMediaButtonSessionLocked() {
+ // If we don't have a media button receiver to fall back on
+ // include non-playing sessions for dispatching.
+ boolean useNotPlayingSessions = true;
+ for (int userId : mCurrentUserIdList) {
+ UserRecord ur = mUserRecords.get(userId);
+ if (ur.mLastMediaButtonReceiver != null
+ || ur.mRestoredMediaButtonReceiver != null) {
+ useNotPlayingSessions = false;
+ break;
+ }
+ }
+ return mPriorityStack.getDefaultMediaButtonSession(
+ mCurrentUserIdList, useNotPlayingSessions);
+ }
+
+ private void pushAddressedPlayerChangedLocked() {
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
+ if (mediaButtonSession != null) {
+ mCallback.onAddressedPlayerChangedToMediaSession(
+ new MediaSession.Token(mediaButtonSession.getControllerBinder()));
+ } else {
+ for (int userId : mCurrentUserIdList) {
+ UserRecord user = mUserRecords.get(userId);
+ if (user.mLastMediaButtonReceiver == null
+ && user.mRestoredMediaButtonReceiver == null) {
+ continue;
+ }
+ ComponentName componentName = user.mLastMediaButtonReceiver != null
+ ? user.mLastMediaButtonReceiver.getIntent().getComponent()
+ : user.mRestoredMediaButtonReceiver;
+ mCallback.onAddressedPlayerChangedToMediaButtonReceiver(componentName);
+ return;
+ }
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
+ }
+ }
+
+ // Remember media button receiver and keep it in the persistent storage.
+ // This should be called whenever there's no media session to receive media button event.
private void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
PendingIntent receiver = record.getMediaButtonReceiver();
UserRecord user = mUserRecords.get(record.getUserId());
@@ -530,6 +579,14 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
+ private String getCallingPackageName(int uid) {
+ String[] packages = getContext().getPackageManager().getPackagesForUid(uid);
+ if (packages != null && packages.length > 0) {
+ return packages[0];
+ }
+ return "";
+ }
+
/**
* Information about a particular user. The contents of this object is
* guarded by mLock.
@@ -792,12 +849,10 @@ public class MediaSessionService extends SystemService implements Monitor {
Log.d(TAG, "dispatchMediaKeyEvent, useNotPlayingSessions="
+ useNotPlayingSessions);
}
- MediaSessionRecord session = mPriorityStack.getDefaultMediaButtonSession(
- mCurrentUserIdList, useNotPlayingSessions);
if (isVoiceKey(keyEvent.getKeyCode())) {
- handleVoiceKeyEventLocked(keyEvent, needWakeLock, session);
+ handleVoiceKeyEventLocked(keyEvent, needWakeLock);
} else {
- dispatchMediaKeyEventLocked(keyEvent, needWakeLock, session);
+ dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
}
}
} finally {
@@ -806,6 +861,45 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@Override
+ public void setCallback(ICallback callback) {
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (uid != Process.BLUETOOTH_UID) {
+ throw new SecurityException("Only Bluetooth service processes can set"
+ + " Callback");
+ }
+ synchronized (mLock) {
+ Log.d(TAG, "Callback + " + mCallback
+ + " is set by " + getCallingPackageName(uid));
+ mCallback = callback;
+ if (mCallback == null) {
+ return;
+ }
+ try {
+ mCallback.asBinder().linkToDeath(
+ new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ mCallback = null;
+ }
+ }
+ }, 0);
+ pushAddressedPlayerChangedLocked();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set callback", e);
+ mCallback = null;
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+
+ @Override
public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
final long token = Binder.clearCallingIdentity();
try {
@@ -932,13 +1026,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
- private void handleVoiceKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock,
- MediaSessionRecord session) {
- if (session != null && session.hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
- // If the phone app has priority just give it the event
- dispatchMediaKeyEventLocked(keyEvent, needWakeLock, session);
- return;
- }
+ private void handleVoiceKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock) {
int action = keyEvent.getAction();
boolean isLongPress = (keyEvent.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0;
if (action == KeyEvent.ACTION_DOWN) {
@@ -955,15 +1043,15 @@ public class MediaSessionService extends SystemService implements Monitor {
if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
// Resend the down then send this event through
KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
- dispatchMediaKeyEventLocked(downEvent, needWakeLock, session);
- dispatchMediaKeyEventLocked(keyEvent, needWakeLock, session);
+ dispatchMediaKeyEventLocked(downEvent, needWakeLock);
+ dispatchMediaKeyEventLocked(keyEvent, needWakeLock);
}
}
}
}
- private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock,
- MediaSessionRecord session) {
+ private void dispatchMediaKeyEventLocked(KeyEvent keyEvent, boolean needWakeLock) {
+ MediaSessionRecord session = getMediaButtonSessionLocked();
if (session != null) {
if (DEBUG_MEDIA_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent + " to " + session);
@@ -977,6 +1065,14 @@ public class MediaSessionService extends SystemService implements Monitor {
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
mKeyEventReceiver, Process.SYSTEM_UID,
getContext().getPackageName());
+ if (mCallback != null) {
+ try {
+ mCallback.onMediaKeyEventDispatchedToMediaSession(keyEvent,
+ new MediaSession.Token(session.getControllerBinder()));
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send callback", e);
+ }
+ }
} else {
// Launch the last PendingIntent we had with priority
for (int userId : mCurrentUserIdList) {
@@ -993,26 +1089,41 @@ public class MediaSessionService extends SystemService implements Monitor {
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
try {
if (user.mLastMediaButtonReceiver != null) {
+ PendingIntent receiver = user.mLastMediaButtonReceiver;
if (DEBUG_MEDIA_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent
- + " to the last known pendingIntent "
- + user.mLastMediaButtonReceiver);
+ + " to the last known pendingIntent " + receiver);
}
- user.mLastMediaButtonReceiver.send(getContext(),
+ receiver.send(getContext(),
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
mediaButtonIntent, mKeyEventReceiver, mHandler);
+ if (mCallback != null) {
+ ComponentName componentName =
+ user.mLastMediaButtonReceiver.getIntent().getComponent();
+ if (componentName != null) {
+ mCallback.onMediaKeyEventDispatchedToMediaButtonReceiver(
+ keyEvent, componentName);
+ }
+ }
} else {
+ ComponentName receiver = user.mRestoredMediaButtonReceiver;
if (DEBUG_MEDIA_KEY_EVENT) {
Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
- + user.mRestoredMediaButtonReceiver);
+ + receiver);
}
- mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
+ mediaButtonIntent.setComponent(receiver);
getContext().sendBroadcastAsUser(mediaButtonIntent,
UserHandle.of(userId));
+ if (mCallback != null) {
+ mCallback.onMediaKeyEventDispatchedToMediaButtonReceiver(
+ keyEvent, receiver);
+ }
}
} catch (CanceledException e) {
Log.i(TAG, "Error sending key event to media button receiver "
+ user.mLastMediaButtonReceiver, e);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send callback", e);
}
return;
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index d9ea7284616d..d696f49173fc 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -150,10 +150,14 @@ public class PackageDexOptimizer {
// TODO(calin,jeffhao): shared library paths should be adjusted to include previous code
// paths (b/34169257).
- final String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
+ String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
+ // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags.
final int dexoptFlags = getDexFlags(pkg, compilerFilter);
int result = DEX_OPT_SKIPPED;
+ // TODO: Iterate based on dependency hierarchy (currently alphabetically by name)
+ // (b/37480811).
+ String basePathCheck = null;
for (String path : paths) {
for (String dexCodeIsa : dexCodeInstructionSets) {
int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter, profileUpdated,
@@ -165,6 +169,22 @@ public class PackageDexOptimizer {
if ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) {
result = newResult;
}
+ // Add the relative path of code we just compiled to the shared libraries.
+ int slashIndex = path.lastIndexOf('/') + 1;
+ String relativePath = path.substring(slashIndex);
+ if (sharedLibrariesPath == null) {
+ sharedLibrariesPath = relativePath;
+ } else {
+ sharedLibrariesPath += ":" + relativePath;
+ }
+ // Sanity check that the base paths are all the same.
+ String basePath = path.substring(0, slashIndex);
+ if (basePathCheck == null) {
+ basePathCheck = basePath;
+ } else if (!basePath.equals(basePathCheck)) {
+ Slog.wtf(TAG, "Split paths have different base paths: " + basePath + " and " +
+ basePathCheck);
+ }
}
}
return result;
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 35f3fcf1ee3b..b2c1244af708 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -29,9 +29,11 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
@@ -53,12 +55,16 @@ import android.telephony.CarrierConfigManager;
import com.android.internal.util.test.BroadcastInterceptingContext;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.Vector;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class TetheringTest {
@@ -81,7 +87,9 @@ public class TetheringTest {
private final TestLooper mLooper = new TestLooper();
private final String mTestIfname = "test_wlan0";
+ private Vector<Intent> mIntents;
private BroadcastInterceptingContext mServiceContext;
+ private BroadcastReceiver mBroadcastReceiver;
private Tethering mTethering;
private class MockContext extends BroadcastInterceptingContext {
@@ -100,7 +108,8 @@ public class TetheringTest {
}
}
- @Before public void setUp() throws Exception {
+ @Before
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
.thenReturn(new String[0]);
@@ -118,10 +127,24 @@ public class TetheringTest {
.thenReturn(new InterfaceConfiguration());
mServiceContext = new MockContext(mContext);
+ mIntents = new Vector<>();
+ mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mIntents.addElement(intent);
+ }
+ };
+ mServiceContext.registerReceiver(mBroadcastReceiver,
+ new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
mLooper.getLooper(), mSystemProperties);
}
+ @After
+ public void tearDown() {
+ mServiceContext.unregisterReceiver(mBroadcastReceiver);
+ }
+
private void setupForRequiredProvisioning() {
// Produce some acceptable looking provision app setting if requested.
when(mResources.getStringArray(
@@ -180,6 +203,23 @@ public class TetheringTest {
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+ private void verifyInterfaceServingModeStarted() throws Exception {
+ verify(mNMService, times(1)).listInterfaces();
+ verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
+ verify(mNMService, times(1))
+ .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
+ verify(mNMService, times(1)).tetherInterface(mTestIfname);
+ }
+
+ private void verifyTetheringBroadcast(String ifname, String whichExtra) {
+ // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
+ final Intent bcast = mIntents.get(0);
+ assertEquals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, bcast.getAction());
+ final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
+ assertTrue(ifnames.contains(ifname));
+ mIntents.remove(bcast);
+ }
+
@Test
public void workingLocalOnlyHotspot() throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
@@ -191,14 +231,12 @@ public class TetheringTest {
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
mLooper.dispatchAll();
- verify(mNMService, times(1)).listInterfaces();
- verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
- verify(mNMService, times(1))
- .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).tetherInterface(mTestIfname);
+ verifyInterfaceServingModeStarted();
+ verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
verify(mNMService, times(1)).setIpForwardingEnabled(true);
verify(mNMService, times(1)).startTethering(any(String[].class));
verifyNoMoreInteractions(mNMService);
+ verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY);
// UpstreamNetworkMonitor will be started, and will register two callbacks:
// a "listen all" and a "track default".
verify(mConnectivityManager, times(1)).registerNetworkCallback(
@@ -249,14 +287,12 @@ public class TetheringTest {
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
mLooper.dispatchAll();
- verify(mNMService, times(1)).listInterfaces();
- verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
- verify(mNMService, times(1))
- .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
- verify(mNMService, times(1)).tetherInterface(mTestIfname);
+ verifyInterfaceServingModeStarted();
+ verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
verify(mNMService, times(1)).setIpForwardingEnabled(true);
verify(mNMService, times(1)).startTethering(any(String[].class));
verifyNoMoreInteractions(mNMService);
+ verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_TETHER);
// UpstreamNetworkMonitor will be started, and will register two callbacks:
// a "listen all" and a "track default".
verify(mConnectivityManager, times(1)).registerNetworkCallback(
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 82b3792a331c..bf5c42b8ca1c 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -19,6 +19,7 @@ package android.net.wifi.aware;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.NetworkSpecifier;
import android.net.wifi.RttManager;
import android.util.Log;
@@ -250,8 +251,8 @@ public class DiscoverySession {
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * unencrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an unencrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -276,13 +277,13 @@ public class DiscoverySession {
* request from only that peer. A RESPONDER may specify a {@code null} -
* indicating that it will accept connection requests from any device.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
+ public NetworkSpecifier createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
if (mTerminated) {
Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
return null;
@@ -302,8 +303,8 @@ public class DiscoverySession {
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -329,14 +330,14 @@ public class DiscoverySession {
* {@link #createNetworkSpecifierOpen(PeerHandle)} API to
* specify an open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierPassphrase(@Nullable PeerHandle peerHandle,
- @NonNull String passphrase) {
+ public NetworkSpecifier createNetworkSpecifierPassphrase(
+ @Nullable PeerHandle peerHandle, @NonNull String passphrase) {
if (passphrase == null || passphrase.length() == 0) {
throw new IllegalArgumentException("Passphrase must not be null or empty");
}
@@ -361,8 +362,8 @@ public class DiscoverySession {
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -389,8 +390,8 @@ public class DiscoverySession {
* Passphrase or {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an
* open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
@@ -398,7 +399,7 @@ public class DiscoverySession {
* @hide
*/
@SystemApi
- public String createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
+ public NetworkSpecifier createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
@NonNull byte[] pmk) {
if (pmk == null || pmk.length == 0) {
throw new IllegalArgumentException("PMK must not be null or empty");
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 4d3957aece91..3fcbd4b60259 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -24,6 +24,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
import android.net.wifi.RttManager;
import android.os.Binder;
import android.os.Bundle;
@@ -31,7 +32,6 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.util.Base64;
import android.util.Log;
import android.util.SparseArray;
@@ -39,9 +39,6 @@ import com.android.internal.annotations.GuardedBy;
import libcore.util.HexEncoding;
-import org.json.JSONException;
-import org.json.JSONObject;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -129,65 +126,6 @@ public class WifiAwareManager {
private static final boolean VDBG = false; // STOPSHIP if true
/**
- * Keys used to generate a Network Specifier for the Aware network request. The network
- * specifier is formatted as a JSON string.
- */
-
- /**
- * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
-
- /**
- * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
- * [only permitted for RESPONDER]
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
-
- /**
- * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
-
- /**
- * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
- * [only permitted for RESPONDER]
- * @hide
- */
- public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;
-
-
- /** @hide */
- public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_TYPE = "type";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_ROLE = "role";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_CLIENT_ID = "client_id";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_SESSION_ID = "session_id";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PEER_ID = "peer_id";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PEER_MAC = "peer_mac";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PMK = "pmk";
-
- /** @hide */
- public static final String NETWORK_SPECIFIER_KEY_PASSPHRASE = "passphrase";
-
- /**
* Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed.
* Use the {@link #isAvailable()} to query the current status.
* This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
@@ -483,7 +421,7 @@ public class WifiAwareManager {
}
/** @hide */
- public String createNetworkSpecifier(int clientId, int role, int sessionId,
+ public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
@@ -492,9 +430,6 @@ public class WifiAwareManager {
+ ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
}
- int type = (peerHandle == null) ? NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
- : NETWORK_SPECIFIER_TYPE_IB;
-
if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
&& role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
throw new IllegalArgumentException(
@@ -509,35 +444,20 @@ public class WifiAwareManager {
}
}
- JSONObject json;
- try {
- json = new JSONObject();
- json.put(NETWORK_SPECIFIER_KEY_TYPE, type);
- json.put(NETWORK_SPECIFIER_KEY_ROLE, role);
- json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
- json.put(NETWORK_SPECIFIER_KEY_SESSION_ID, sessionId);
- if (peerHandle != null) {
- json.put(NETWORK_SPECIFIER_KEY_PEER_ID, peerHandle.peerId);
- }
- if (pmk == null) {
- pmk = new byte[0];
- }
- json.put(NETWORK_SPECIFIER_KEY_PMK,
- Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
- if (passphrase == null) {
- passphrase = new String();
- }
- json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
-
- } catch (JSONException e) {
- return "";
- }
-
- return json.toString();
+ return new WifiAwareNetworkSpecifier(
+ (peerHandle == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
+ : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB,
+ role,
+ clientId,
+ sessionId,
+ peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
+ null, // peerMac (not used in this method)
+ pmk,
+ passphrase);
}
/** @hide */
- public String createNetworkSpecifier(int clientId, @DataPathRole int role,
+ public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role,
@Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
Log.v(TAG, "createNetworkSpecifier: role=" + role
@@ -545,9 +465,6 @@ public class WifiAwareManager {
+ ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
}
- int type = (peer == null) ?
- NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER : NETWORK_SPECIFIER_TYPE_OOB;
-
if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
&& role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
throw new IllegalArgumentException(
@@ -564,29 +481,16 @@ public class WifiAwareManager {
throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
}
- JSONObject json;
- try {
- json = new JSONObject();
- json.put(NETWORK_SPECIFIER_KEY_TYPE, type);
- json.put(NETWORK_SPECIFIER_KEY_ROLE, role);
- json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
- if (peer != null) {
- json.put(NETWORK_SPECIFIER_KEY_PEER_MAC, new String(HexEncoding.encode(peer)));
- }
- if (pmk == null) {
- pmk = new byte[0];
- }
- json.put(NETWORK_SPECIFIER_KEY_PMK,
- Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
- if (passphrase == null) {
- passphrase = new String();
- }
- json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
- } catch (JSONException e) {
- return "";
- }
-
- return json.toString();
+ return new WifiAwareNetworkSpecifier(
+ (peer == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER
+ : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
+ role,
+ clientId,
+ 0, // 0 is an invalid session ID
+ 0, // 0 is an invalid peer ID
+ peer,
+ pmk,
+ passphrase);
}
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
new file mode 100644
index 000000000000..59934806f398
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.aware;
+
+import android.net.NetworkSpecifier;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Network specifier object used to request a Wi-Fi Aware network. Apps do not create these objects
+ * directly but obtain them using
+ * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} or
+ * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)} or their secure (Passphrase)
+ * versions.
+ *
+ * @hide
+ */
+public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+ /**
+ * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
+
+ /**
+ * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
+ * [only permitted for RESPONDER]
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
+
+ /**
+ * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
+
+ /**
+ * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
+ * [only permitted for RESPONDER]
+ * @hide
+ */
+ public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;
+
+ /** @hide */
+ public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
+
+ /**
+ * One of the NETWORK_SPECIFIER_TYPE_* constants. The type of the network specifier object.
+ * @hide
+ */
+ public final int type;
+
+ /**
+ * The role of the device: WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR or
+ * WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER.
+ * @hide
+ */
+ public final int role;
+
+ /**
+ * The client ID of the device.
+ * @hide
+ */
+ public final int clientId;
+
+ /**
+ * The session ID in which context to request a data-path. Only relevant for IB requests.
+ * @hide
+ */
+ public final int sessionId;
+
+ /**
+ * The peer ID of the device which the data-path should be connected to. Only relevant for
+ * IB requests (i.e. not IB_ANY_PEER or OOB*).
+ * @hide
+ */
+ public final int peerId;
+
+ /**
+ * The peer MAC address of the device which the data-path should be connected to. Only relevant
+ * for OB requests (i.e. not OOB_ANY_PEER or IB*).
+ * @hide
+ */
+ public final byte[] peerMac;
+
+ /**
+ * The PMK of the requested data-path. Can be null. Only one or none of pmk or passphrase should
+ * be specified.
+ * @hide
+ */
+ public final byte[] pmk;
+
+ /**
+ * The Passphrase of the requested data-path. Can be null. Only one or none of the pmk or
+ * passphrase should be specified.
+ * @hide
+ */
+ public final String passphrase;
+
+ /** @hide */
+ public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId,
+ byte[] peerMac, byte[] pmk, String passphrase) {
+ this.type = type;
+ this.role = role;
+ this.clientId = clientId;
+ this.sessionId = sessionId;
+ this.peerId = peerId;
+ this.peerMac = peerMac;
+ this.pmk = pmk;
+ this.passphrase = passphrase;
+ }
+
+ public static final Creator<WifiAwareNetworkSpecifier> CREATOR =
+ new Creator<WifiAwareNetworkSpecifier>() {
+ @Override
+ public WifiAwareNetworkSpecifier createFromParcel(Parcel in) {
+ return new WifiAwareNetworkSpecifier(
+ in.readInt(), // type
+ in.readInt(), // role
+ in.readInt(), // clientId
+ in.readInt(), // sessionId
+ in.readInt(), // peerId
+ in.createByteArray(), // peerMac
+ in.createByteArray(), // pmk
+ in.readString()); // passphrase
+ }
+
+ @Override
+ public WifiAwareNetworkSpecifier[] newArray(int size) {
+ return new WifiAwareNetworkSpecifier[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(type);
+ dest.writeInt(role);
+ dest.writeInt(clientId);
+ dest.writeInt(sessionId);
+ dest.writeInt(peerId);
+ dest.writeByteArray(peerMac);
+ dest.writeByteArray(pmk);
+ dest.writeString(passphrase);
+ }
+
+ /** @hide */
+ @Override
+ public boolean satisfiedBy(NetworkSpecifier other) {
+ // MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier.
+ return equals(other);
+ }
+
+ /** @hide */
+ @Override
+ public int hashCode() {
+ int result = 17;
+
+ result = 31 * result + type;
+ result = 31 * result + role;
+ result = 31 * result + clientId;
+ result = 31 * result + sessionId;
+ result = 31 * result + peerId;
+ result = 31 * result + Arrays.hashCode(peerMac);
+ result = 31 * result + Arrays.hashCode(pmk);
+ result = 31 * result + Objects.hashCode(passphrase);
+
+ return result;
+ }
+
+ /** @hide */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof WifiAwareNetworkSpecifier)) {
+ return false;
+ }
+
+ WifiAwareNetworkSpecifier lhs = (WifiAwareNetworkSpecifier) obj;
+
+ return type == lhs.type
+ && role == lhs.role
+ && clientId == lhs.clientId
+ && sessionId == lhs.sessionId
+ && peerId == lhs.peerId
+ && Arrays.equals(peerMac, lhs.peerMac)
+ && Arrays.equals(pmk, lhs.pmk)
+ && Objects.equals(passphrase, lhs.passphrase);
+ }
+
+ /** @hide */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("WifiAwareNetworkSpecifier [");
+ sb.append("type=").append(type)
+ .append(", role=").append(role)
+ .append(", clientId=").append(clientId)
+ .append(", sessionId=").append(sessionId)
+ .append(", peerId=").append(peerId)
+ // masking potential PII (although low impact information)
+ .append(", peerMac=").append((peerMac == null) ? "<null>" : "<non-null>")
+ // masking PII
+ .append(", pmk=").append((pmk == null) ? "<null>" : "<non-null>")
+ // masking PII
+ .append(", passphrase=").append((passphrase == null) ? "<null>" : "<non-null>")
+ .append("]");
+ return sb.toString();
+ }
+}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 895defb9a540..ac3a6bba052c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -19,6 +19,7 @@ package android.net.wifi.aware;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.NetworkSpecifier;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
@@ -184,8 +185,8 @@ public class WifiAwareSession {
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * unencrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an unencrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -205,29 +206,29 @@ public class WifiAwareSession {
* peer. A RESPONDER may specify a {@code null} - indicating that it will accept
* connection requests from any device.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierOpen(@WifiAwareManager.DataPathRole int role,
- @Nullable byte[] peer) {
+ public NetworkSpecifier createNetworkSpecifierOpen(
+ @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
- return "";
+ return null;
}
if (mTerminated) {
Log.e(TAG, "createNetworkSpecifierOpen: called after termination");
- return "";
+ return null;
}
return mgr.createNetworkSpecifier(mClientId, role, peer, null, null);
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -247,22 +248,23 @@ public class WifiAwareSession {
* the passphrase. Use {@link #createNetworkSpecifierOpen(int, byte[])} to
* specify an open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
*/
- public String createNetworkSpecifierPassphrase(@WifiAwareManager.DataPathRole int role,
- @Nullable byte[] peer, @NonNull String passphrase) {
+ public NetworkSpecifier createNetworkSpecifierPassphrase(
+ @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer,
+ @NonNull String passphrase) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
- return "";
+ return null;
}
if (mTerminated) {
Log.e(TAG, "createNetworkSpecifierPassphrase: called after termination");
- return "";
+ return null;
}
if (passphrase == null || passphrase.length() == 0) {
throw new IllegalArgumentException("Passphrase must not be null or empty");
@@ -271,8 +273,8 @@ public class WifiAwareSession {
}
/**
- * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
- * encrypted WiFi Aware connection (link) to the specified peer. The
+ * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+ * an encrypted WiFi Aware connection (link) to the specified peer. The
* {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
* {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
* <p>
@@ -294,8 +296,8 @@ public class WifiAwareSession {
* Passphrase or {@link #createNetworkSpecifierOpen(int, byte[])} to specify an
* open (unencrypted) link.
*
- * @return A string to be used to construct
- * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+ * @return A {@link NetworkSpecifier} to be used to construct
+ * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
* {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
* android.net.ConnectivityManager.NetworkCallback)}
* [or other varieties of that API].
@@ -303,16 +305,16 @@ public class WifiAwareSession {
* @hide
*/
@SystemApi
- public String createNetworkSpecifierPmk(@WifiAwareManager.DataPathRole int role,
- @Nullable byte[] peer, @NonNull byte[] pmk) {
+ public NetworkSpecifier createNetworkSpecifierPmk(
+ @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer, @NonNull byte[] pmk) {
WifiAwareManager mgr = mMgr.get();
if (mgr == null) {
Log.e(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
- return "";
+ return null;
}
if (mTerminated) {
Log.e(TAG, "createNetworkSpecifierPmk: called after termination");
- return "";
+ return null;
}
if (pmk == null || pmk.length == 0) {
throw new IllegalArgumentException("PMK must not be null or empty");
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 830db22929e8..72a6a7a7b46b 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -34,11 +34,9 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Base64;
import libcore.util.HexEncoding;
-import org.json.JSONObject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -959,8 +957,6 @@ public class WifiAwareManagerTest {
final ConfigRequest configRequest = new ConfigRequest.Builder().build();
final PublishConfig publishConfig = new PublishConfig.Builder().build();
- String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
-
ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
WifiAwareSession.class);
ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
@@ -991,51 +987,37 @@ public class WifiAwareManagerTest {
inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
// (3) request an open (unencrypted) network specifier from the session
- String networkSpecifier = publishSession.getValue().createNetworkSpecifierOpen(peerHandle);
+ WifiAwareNetworkSpecifier ns =
+ (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierOpen(
+ peerHandle);
// validate format
- JSONObject jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("session_id", sessionId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
- collector.checkThat("peer_id", peerHandle.peerId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+ collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
// (4) request an encrypted (PMK) network specifier from the session
- networkSpecifier = publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
+ ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPmk(
+ peerHandle, pmk);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("session_id", sessionId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
- collector.checkThat("peer_id", peerHandle.peerId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
- collector.checkThat("pmk", pmkB64 ,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+ collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
+ collector.checkThat("pmk", pmk , equalTo(ns.pmk));
// (5) request an encrypted (Passphrase) network specifier from the session
- networkSpecifier = publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle,
- passphrase);
+ ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPassphrase(
+ peerHandle, passphrase);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("session_id", sessionId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
- collector.checkThat("peer_id", peerHandle.peerId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
- collector.checkThat("passphrase", passphrase,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+ collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
+ collector.checkThat("passphrase", passphrase, equalTo(ns.passphrase));
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);
@@ -1054,8 +1036,6 @@ public class WifiAwareManagerTest {
final byte[] pmk = "Some arbitrary pmk data".getBytes();
final String passphrase = "A really bad password";
- String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
-
ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
WifiAwareSession.class);
ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
@@ -1074,47 +1054,32 @@ public class WifiAwareManagerTest {
WifiAwareSession session = sessionCaptor.getValue();
// (2) request an open (unencrypted) direct network specifier
- String networkSpecifier = session.createNetworkSpecifierOpen(role, someMac);
+ WifiAwareNetworkSpecifier ns =
+ (WifiAwareNetworkSpecifier) session.createNetworkSpecifierOpen(role, someMac);
// validate format
- JSONObject jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
- jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
- false)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
// (3) request an encrypted (PMK) direct network specifier
- networkSpecifier = session.createNetworkSpecifierPmk(role, someMac, pmk);
+ ns = (WifiAwareNetworkSpecifier) session.createNetworkSpecifierPmk(role, someMac, pmk);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
- jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
- false)));
- collector.checkThat("pmk", pmkB64,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
+ collector.checkThat("pmk", pmk, equalTo(ns.pmk));
// (4) request an encrypted (Passphrase) direct network specifier
- networkSpecifier = session.createNetworkSpecifierPassphrase(role, someMac, passphrase);
+ ns = (WifiAwareNetworkSpecifier) session.createNetworkSpecifierPassphrase(role, someMac,
+ passphrase);
// validate format
- jsonObject = new JSONObject(networkSpecifier);
- collector.checkThat("role", role,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
- collector.checkThat("client_id", clientId,
- equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
- collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
- jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
- false)));
- collector.checkThat("passphrase", passphrase,
- equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+ collector.checkThat("role", role, equalTo(ns.role));
+ collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+ collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
+ collector.checkThat("passphrase", passphrase, equalTo(ns.passphrase));
verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
mockPublishSession, mockRttListener);