diff options
49 files changed, 1723 insertions, 730 deletions
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp index 524db14f7aab..f415f8f5dd75 100644 --- a/cmds/idmap/create.cpp +++ b/cmds/idmap/create.cpp @@ -104,13 +104,17 @@ fail: } } - uint32_t cached_target_crc, cached_overlay_crc; + uint32_t version, cached_target_crc, cached_overlay_crc; String8 cached_target_path, cached_overlay_path; - if (!ResTable::getIdmapInfo(buf, N, NULL, &cached_target_crc, &cached_overlay_crc, + if (!ResTable::getIdmapInfo(buf, N, &version, &cached_target_crc, &cached_overlay_crc, &cached_target_path, &cached_overlay_path)) { return true; } + if (version != ResTable::IDMAP_CURRENT_VERSION) { + return true; + } + if (cached_target_path != target_apk_path) { return true; } diff --git a/cmds/idmap/inspect.cpp b/cmds/idmap/inspect.cpp index 154cb25a02a1..20005e2766d8 100644 --- a/cmds/idmap/inspect.cpp +++ b/cmds/idmap/inspect.cpp @@ -284,7 +284,9 @@ namespace { if (err != NO_ERROR) { return err; } - print("", "entry", data32, "%s/%s", type.string(), name.string()); + if (data32 != ResTable_type::NO_ENTRY) { + print("", "entry", data32, "%s/%s", type.string(), name.string()); + } } } diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java index 611531c4f7c4..faab000a8997 100755 --- a/core/java/android/bluetooth/BluetoothA2dpSink.java +++ b/core/java/android/bluetooth/BluetoothA2dpSink.java @@ -125,7 +125,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private IBluetoothA2dpSink mService; + private volatile IBluetoothA2dpSink mService; private BluetoothAdapter mAdapter; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -240,15 +240,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -279,15 +280,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -297,15 +299,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -315,15 +318,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -333,16 +337,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -359,16 +363,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) { if (VDBG) log("getAudioConfig(" + device + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getAudioConfig(device); + return service.getAudioConfig(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return null; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return null; } @@ -389,20 +393,20 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -421,16 +425,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.PRIORITY_OFF; } @@ -442,16 +446,16 @@ public final class BluetoothA2dpSink implements BluetoothProfile { * @param device BluetoothDevice device */ public boolean isA2dpPlaying(BluetoothDevice device) { - if (mService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothA2dpSink service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.isA2dpPlaying(device); + return service.isA2dpPlaying(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -485,7 +489,6 @@ public final class BluetoothA2dpSink implements BluetoothProfile { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service)); - if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK, BluetoothA2dpSink.this); @@ -502,15 +505,11 @@ public final class BluetoothA2dpSink implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_ON; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java index 7528aa972109..5f0e5d97447e 100644 --- a/core/java/android/bluetooth/BluetoothAvrcpController.java +++ b/core/java/android/bluetooth/BluetoothAvrcpController.java @@ -81,7 +81,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private IBluetoothAvrcpController mService; + private volatile IBluetoothAvrcpController mService; private BluetoothAdapter mAdapter; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -179,15 +179,16 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothAvrcpController service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -197,15 +198,16 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothAvrcpController service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -215,16 +217,16 @@ public final class BluetoothAvrcpController implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - if (mService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothAvrcpController service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -236,9 +238,10 @@ public final class BluetoothAvrcpController implements BluetoothProfile { public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) { if (DBG) Log.d(TAG, "getPlayerSettings"); BluetoothAvrcpPlayerSettings settings = null; - if (mService != null && isEnabled()) { + final IBluetoothAvrcpController service = mService; + if (service != null && isEnabled()) { try { - settings = mService.getPlayerSettings(device); + settings = service.getPlayerSettings(device); } catch (RemoteException e) { Log.e(TAG, "Error talking to BT service in getMetadata() " + e); return null; @@ -253,15 +256,16 @@ public final class BluetoothAvrcpController implements BluetoothProfile { */ public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) { if (DBG) Log.d(TAG, "setPlayerApplicationSetting"); - if (mService != null && isEnabled()) { + final IBluetoothAvrcpController service = mService; + if (service != null && isEnabled()) { try { - return mService.setPlayerApplicationSetting(plAppSetting); + return service.setPlayerApplicationSetting(plAppSetting); } catch (RemoteException e) { Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting() " + e); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -272,23 +276,23 @@ public final class BluetoothAvrcpController implements BluetoothProfile { public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) { Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = " + keyState); - if (mService != null && isEnabled()) { + final IBluetoothAvrcpController service = mService; + if (service != null && isEnabled()) { try { - mService.sendGroupNavigationCmd(device, keyCode, keyState); + service.sendGroupNavigationCmd(device, keyCode, keyState); return; } catch (RemoteException e) { Log.e(TAG, "Error talking to BT service in sendGroupNavigationCmd()", e); return; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); } private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service)); - if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER, BluetoothAvrcpController.this); @@ -305,15 +309,11 @@ public final class BluetoothAvrcpController implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_ON; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 3ab2c4a8f44d..d982bb7ffb43 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -712,7 +712,7 @@ public final class BluetoothDevice implements Parcelable { * getService() called. * TODO: Unify implementation of sService amongst BluetoothFoo API's */ - private static IBluetooth sService; + private static volatile IBluetooth sService; private final String mAddress; @@ -839,12 +839,13 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public String getName() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot get Remote Device name"); return null; } try { - return sService.getRemoteName(this); + return service.getRemoteName(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -859,12 +860,13 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getType() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot get Remote Device type"); return DEVICE_TYPE_UNKNOWN; } try { - return sService.getRemoteType(this); + return service.getRemoteType(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -879,12 +881,13 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public String getAlias() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias"); return null; } try { - return sService.getRemoteAlias(this); + return service.getRemoteAlias(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -902,12 +905,13 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean setAlias(String alias) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot set Remote Device name"); return false; } try { - return sService.setRemoteAlias(this, alias); + return service.setRemoteAlias(this, alias); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -942,12 +946,13 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getBatteryLevel() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level"); return BATTERY_LEVEL_UNKNOWN; } try { - return sService.getBatteryLevel(this); + return service.getBatteryLevel(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -966,7 +971,8 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); return false; } @@ -974,7 +980,7 @@ public final class BluetoothDevice implements Parcelable { Log.i(TAG, "createBond() for device " + getAddress() + " called by pid: " + Process.myPid() + " tid: " + Process.myTid()); - return sService.createBond(this, TRANSPORT_AUTO); + return service.createBond(this, TRANSPORT_AUTO); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -998,7 +1004,8 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean createBond(int transport) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); return false; } @@ -1009,7 +1016,7 @@ public final class BluetoothDevice implements Parcelable { Log.i(TAG, "createBond() for device " + getAddress() + " called by pid: " + Process.myPid() + " tid: " + Process.myTid()); - return sService.createBond(this, transport); + return service.createBond(this, transport); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1035,8 +1042,13 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean createBondOutOfBand(int transport, OobData oobData) { + final IBluetooth service = sService; + if (service == null) { + Log.w(TAG, "BT not enabled, createBondOutOfBand failed"); + return false; + } try { - return sService.createBondOutOfBand(this, transport, oobData); + return service.createBondOutOfBand(this, transport, oobData); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1045,8 +1057,13 @@ public final class BluetoothDevice implements Parcelable { /** @hide */ public boolean isBondingInitiatedLocally() { + final IBluetooth service = sService; + if (service == null) { + Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed"); + return false; + } try { - return sService.isBondingInitiatedLocally(this); + return service.isBondingInitiatedLocally(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1082,7 +1099,8 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean cancelBondProcess() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond"); return false; } @@ -1090,7 +1108,7 @@ public final class BluetoothDevice implements Parcelable { Log.i(TAG, "cancelBondProcess() for device " + getAddress() + " called by pid: " + Process.myPid() + " tid: " + Process.myTid()); - return sService.cancelBondProcess(this); + return service.cancelBondProcess(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1108,7 +1126,8 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean removeBond() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond"); return false; } @@ -1116,7 +1135,7 @@ public final class BluetoothDevice implements Parcelable { Log.i(TAG, "removeBond() for device " + getAddress() + " called by pid: " + Process.myPid() + " tid: " + Process.myTid()); - return sService.removeBond(this); + return service.removeBond(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1134,19 +1153,15 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public int getBondState() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot get bond state"); return BOND_NONE; } try { - return sService.getBondState(this); + return service.getBondState(this); } catch (RemoteException e) { Log.e(TAG, "", e); - } catch (NullPointerException npe) { - // Handle case where bluetooth service proxy - // is already null. - Log.e(TAG, "NullPointerException for getBondState() of device (" - + getAddress() + ")", npe); } return BOND_NONE; } @@ -1160,12 +1175,13 @@ public final class BluetoothDevice implements Parcelable { */ @SystemApi public boolean isConnected() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { // BT is not enabled, we cannot be connected. return false; } try { - return sService.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED; + return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED; } catch (RemoteException e) { Log.e(TAG, "", e); return false; @@ -1182,12 +1198,13 @@ public final class BluetoothDevice implements Parcelable { */ @SystemApi public boolean isEncrypted() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { // BT is not enabled, we cannot be connected. return false; } try { - return sService.getConnectionState(this) > CONNECTION_STATE_CONNECTED; + return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED; } catch (RemoteException e) { Log.e(TAG, "", e); return false; @@ -1201,12 +1218,13 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public BluetoothClass getBluetoothClass() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class"); return null; } try { - int classInt = sService.getRemoteClass(this); + int classInt = service.getRemoteClass(this); if (classInt == BluetoothClass.ERROR) return null; return new BluetoothClass(classInt); } catch (RemoteException e) { @@ -1227,12 +1245,13 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public ParcelUuid[] getUuids() { - if (sService == null || !isBluetoothEnabled()) { + final IBluetooth service = sService; + if (service == null || !isBluetoothEnabled()) { Log.e(TAG, "BT not enabled. Cannot get remote device Uuids"); return null; } try { - return sService.getRemoteUuids(this); + return service.getRemoteUuids(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1254,7 +1273,7 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp() { - IBluetooth service = sService; + final IBluetooth service = sService; if (service == null || !isBluetoothEnabled()) { Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp"); return false; @@ -1289,12 +1308,13 @@ public final class BluetoothDevice implements Parcelable { */ /** @hide */ public boolean sdpSearch(ParcelUuid uuid) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); return false; } try { - return sService.sdpSearch(this, uuid); + return service.sdpSearch(this, uuid); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1308,12 +1328,13 @@ public final class BluetoothDevice implements Parcelable { * @return true pin has been set false for error */ public boolean setPin(byte[] pin) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot set Remote Device pin"); return false; } try { - return sService.setPin(this, true, pin.length, pin); + return service.setPin(this, true, pin.length, pin); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1337,12 +1358,13 @@ public final class BluetoothDevice implements Parcelable { */ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPairingConfirmation(boolean confirm) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot set pairing confirmation"); return false; } try { - return sService.setPairingConfirmation(this, confirm); + return service.setPairingConfirmation(this, confirm); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1361,12 +1383,13 @@ public final class BluetoothDevice implements Parcelable { /** @hide */ public boolean cancelPairingUserInput() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { Log.e(TAG, "BT not enabled. Cannot create pairing user input"); return false; } try { - return sService.cancelBondProcess(this); + return service.cancelBondProcess(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1400,11 +1423,12 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public int getPhonebookAccessPermission() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { return ACCESS_UNKNOWN; } try { - return sService.getPhonebookAccessPermission(this); + return service.getPhonebookAccessPermission(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1421,11 +1445,12 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean setPhonebookAccessPermission(int value) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { return false; } try { - return sService.setPhonebookAccessPermission(this, value); + return service.setPhonebookAccessPermission(this, value); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1440,11 +1465,12 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public int getMessageAccessPermission() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { return ACCESS_UNKNOWN; } try { - return sService.getMessageAccessPermission(this); + return service.getMessageAccessPermission(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1461,11 +1487,12 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean setMessageAccessPermission(int value) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { return false; } try { - return sService.setMessageAccessPermission(this, value); + return service.setMessageAccessPermission(this, value); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1480,11 +1507,12 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public int getSimAccessPermission() { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { return ACCESS_UNKNOWN; } try { - return sService.getSimAccessPermission(this); + return service.getSimAccessPermission(this); } catch (RemoteException e) { Log.e(TAG, "", e); } @@ -1501,11 +1529,12 @@ public final class BluetoothDevice implements Parcelable { * @hide */ public boolean setSimAccessPermission(int value) { - if (sService == null) { + final IBluetooth service = sService; + if (service == null) { return false; } try { - return sService.setSimAccessPermission(this, value); + return service.setSimAccessPermission(this, value); } catch (RemoteException e) { Log.e(TAG, "", e); } diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index be1ce63cadc2..85550c7720a6 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -306,7 +306,7 @@ public final class BluetoothHeadset implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private IBluetoothHeadset mService; + private volatile IBluetoothHeadset mService; private BluetoothAdapter mAdapter; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -418,15 +418,16 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -457,15 +458,16 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -475,15 +477,16 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -493,15 +496,16 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -511,15 +515,16 @@ public final class BluetoothHeadset implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -540,19 +545,20 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -571,15 +577,16 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return PRIORITY_OFF; } @@ -605,14 +612,15 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean startVoiceRecognition(BluetoothDevice device) { if (DBG) log("startVoiceRecognition()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.startVoiceRecognition(device); + return service.startVoiceRecognition(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -627,14 +635,15 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean stopVoiceRecognition(BluetoothDevice device) { if (DBG) log("stopVoiceRecognition()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.stopVoiceRecognition(device); + return service.stopVoiceRecognition(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -648,14 +657,15 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean isAudioConnected(BluetoothDevice device) { if (VDBG) log("isAudioConnected()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.isAudioConnected(device); + return service.isAudioConnected(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -674,14 +684,15 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public int getBatteryUsageHint(BluetoothDevice device) { if (VDBG) log("getBatteryUsageHint()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getBatteryUsageHint(device); + return service.getBatteryUsageHint(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return -1; } @@ -704,9 +715,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean acceptIncomingConnect(BluetoothDevice device) { if (DBG) log("acceptIncomingConnect"); - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.acceptIncomingConnect(device); + return service.acceptIncomingConnect(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -724,9 +736,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean rejectIncomingConnect(BluetoothDevice device) { if (DBG) log("rejectIncomingConnect"); - if (mService != null) { + final IBluetoothHeadset service = mService; + if (service != null) { try { - return mService.rejectIncomingConnect(device); + return service.rejectIncomingConnect(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -745,9 +758,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public int getAudioState(BluetoothDevice device) { if (VDBG) log("getAudioState"); - if (mService != null && !isDisabled()) { + final IBluetoothHeadset service = mService; + if (service != null && !isDisabled()) { try { - return mService.getAudioState(device); + return service.getAudioState(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -770,9 +784,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public void setAudioRouteAllowed(boolean allowed) { if (VDBG) log("setAudioRouteAllowed"); - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - mService.setAudioRouteAllowed(allowed); + service.setAudioRouteAllowed(allowed); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -790,9 +805,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean getAudioRouteAllowed() { if (VDBG) log("getAudioRouteAllowed"); - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.getAudioRouteAllowed(); + return service.getAudioRouteAllowed(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -812,9 +828,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public void setForceScoAudio(boolean forced) { if (VDBG) log("setForceScoAudio " + String.valueOf(forced)); - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - mService.setForceScoAudio(forced); + service.setForceScoAudio(forced); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -834,14 +851,15 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean isAudioOn() { if (VDBG) log("isAudioOn()"); - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.isAudioOn(); + return service.isAudioOn(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -855,9 +873,10 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ public boolean connectAudio() { - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.connectAudio(); + return service.connectAudio(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -877,9 +896,10 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ public boolean disconnectAudio() { - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.disconnectAudio(); + return service.disconnectAudio(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -903,9 +923,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) { if (DBG) log("startScoUsingVirtualVoiceCall()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.startScoUsingVirtualVoiceCall(device); + return service.startScoUsingVirtualVoiceCall(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -926,9 +947,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) { if (DBG) log("stopScoUsingVirtualVoiceCall()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.stopScoUsingVirtualVoiceCall(device); + return service.stopScoUsingVirtualVoiceCall(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -949,9 +971,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type) { - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - mService.phoneStateChanged(numActive, numHeld, callState, number, type); + service.phoneStateChanged(numActive, numHeld, callState, number, type); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -968,9 +991,10 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public void clccResponse(int index, int direction, int status, int mode, boolean mpty, String number, int type) { - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - mService.clccResponse(index, direction, status, mode, mpty, number, type); + service.clccResponse(index, direction, status, mode, mpty, number, type); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1006,14 +1030,15 @@ public final class BluetoothHeadset implements BluetoothProfile { if (command == null) { throw new IllegalArgumentException("command is null"); } - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.sendVendorSpecificResultCode(device, command, arg); + return service.sendVendorSpecificResultCode(device, command, arg); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return false; @@ -1027,9 +1052,10 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ public boolean enableWBS() { - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.enableWBS(); + return service.enableWBS(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1048,9 +1074,10 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ public boolean disableWBS() { - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - return mService.disableWBS(); + return service.disableWBS(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1083,9 +1110,10 @@ public final class BluetoothHeadset implements BluetoothProfile { * @hide */ public void bindResponse(int indId, boolean indStatus) { - if (mService != null && isEnabled()) { + final IBluetoothHeadset service = mService; + if (service != null && isEnabled()) { try { - mService.bindResponse(indId, indStatus); + service.bindResponse(indId, indStatus); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1115,20 +1143,15 @@ public final class BluetoothHeadset implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_ON; } private boolean isDisabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_OFF; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 7ed2d2e98f7f..031287f5ee12 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -76,8 +76,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * Intent sent whenever audio state changes. * * <p>It includes two mandatory extras: - * {@link BluetoothProfile.EXTRA_STATE}, - * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE}, + * {@link BluetoothProfile#EXTRA_STATE}, + * {@link BluetoothProfile#EXTRA_PREVIOUS_STATE}, * with possible values: * {@link #STATE_AUDIO_CONNECTING}, * {@link #STATE_AUDIO_CONNECTED}, @@ -367,7 +367,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private IBluetoothHeadsetClient mService; + private volatile IBluetoothHeadsetClient mService; private BluetoothAdapter mAdapter; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = @@ -478,15 +478,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -499,15 +500,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -519,15 +521,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -541,15 +544,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -562,15 +566,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -581,19 +586,20 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -602,15 +608,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return PRIORITY_OFF; } @@ -627,14 +634,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean startVoiceRecognition(BluetoothDevice device) { if (DBG) log("startVoiceRecognition()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.startVoiceRecognition(device); + return service.startVoiceRecognition(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -651,14 +659,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean stopVoiceRecognition(BluetoothDevice device) { if (DBG) log("stopVoiceRecognition()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.stopVoiceRecognition(device); + return service.stopVoiceRecognition(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -670,14 +679,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) { if (DBG) log("getCurrentCalls()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getCurrentCalls(device); + return service.getCurrentCalls(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return null; } @@ -689,14 +699,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public Bundle getCurrentAgEvents(BluetoothDevice device) { if (DBG) log("getCurrentCalls()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getCurrentAgEvents(device); + return service.getCurrentAgEvents(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return null; } @@ -711,14 +722,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean acceptCall(BluetoothDevice device, int flag) { if (DBG) log("acceptCall()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.acceptCall(device, flag); + return service.acceptCall(device, flag); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -731,14 +743,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean holdCall(BluetoothDevice device) { if (DBG) log("holdCall()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.holdCall(device); + return service.holdCall(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -755,14 +768,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean rejectCall(BluetoothDevice device) { if (DBG) log("rejectCall()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.rejectCall(device); + return service.rejectCall(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -784,14 +798,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) { if (DBG) log("terminateCall()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.terminateCall(device, call); + return service.terminateCall(device, call); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -811,14 +826,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean enterPrivateMode(BluetoothDevice device, int index) { if (DBG) log("enterPrivateMode()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.enterPrivateMode(device, index); + return service.enterPrivateMode(device, index); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -837,14 +853,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean explicitCallTransfer(BluetoothDevice device) { if (DBG) log("explicitCallTransfer()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.explicitCallTransfer(device); + return service.explicitCallTransfer(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -859,14 +876,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) { if (DBG) log("dial()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.dial(device, number); + return service.dial(device, number); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return null; } @@ -882,14 +900,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean sendDTMF(BluetoothDevice device, byte code) { if (DBG) log("sendDTMF()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.sendDTMF(device, code); + return service.sendDTMF(device, code); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -907,14 +926,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean getLastVoiceTagNumber(BluetoothDevice device) { if (DBG) log("getLastVoiceTagNumber()"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getLastVoiceTagNumber(device); + return service.getLastVoiceTagNumber(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -925,9 +945,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public int getAudioState(BluetoothDevice device) { if (VDBG) log("getAudioState"); - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getAudioState(device); + return service.getAudioState(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -947,9 +968,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) { if (VDBG) log("setAudioRouteAllowed"); - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - mService.setAudioRouteAllowed(device, allowed); + service.setAudioRouteAllowed(device, allowed); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -968,9 +990,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { */ public boolean getAudioRouteAllowed(BluetoothDevice device) { if (VDBG) log("getAudioRouteAllowed"); - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getAudioRouteAllowed(device); + return service.getAudioRouteAllowed(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -991,9 +1014,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent; */ public boolean connectAudio(BluetoothDevice device) { - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - return mService.connectAudio(device); + return service.connectAudio(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1014,9 +1038,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent; */ public boolean disconnectAudio(BluetoothDevice device) { - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - return mService.disconnectAudio(device); + return service.disconnectAudio(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1034,9 +1059,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { * @return bundle of AG features; null if no service or AG not connected */ public Bundle getCurrentAgFeatures(BluetoothDevice device) { - if (mService != null && isEnabled()) { + final IBluetoothHeadsetClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getCurrentAgFeatures(device); + return service.getCurrentAgFeatures(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -1048,7 +1074,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); @@ -1071,15 +1097,11 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_ON; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java index dc5f38135aaf..57a019755f8f 100644 --- a/core/java/android/bluetooth/BluetoothHealth.java +++ b/core/java/android/bluetooth/BluetoothHealth.java @@ -176,9 +176,10 @@ public final class BluetoothHealth implements BluetoothProfile { BluetoothHealthAppConfiguration config = new BluetoothHealthAppConfiguration(name, dataType, role, channelType); - if (mService != null) { + final IBluetoothHealth service = mService; + if (service != null) { try { - result = mService.registerAppConfiguration(config, wrapper); + result = service.registerAppConfiguration(config, wrapper); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -200,9 +201,10 @@ public final class BluetoothHealth implements BluetoothProfile { */ public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) { boolean result = false; - if (mService != null && isEnabled() && config != null) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled() && config != null) { try { - result = mService.unregisterAppConfiguration(config); + result = service.unregisterAppConfiguration(config); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -228,9 +230,10 @@ public final class BluetoothHealth implements BluetoothProfile { */ public boolean connectChannelToSource(BluetoothDevice device, BluetoothHealthAppConfiguration config) { - if (mService != null && isEnabled() && isValidDevice(device) && config != null) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled() && isValidDevice(device) && config != null) { try { - return mService.connectChannelToSource(device, config); + return service.connectChannelToSource(device, config); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -256,9 +259,10 @@ public final class BluetoothHealth implements BluetoothProfile { */ public boolean connectChannelToSink(BluetoothDevice device, BluetoothHealthAppConfiguration config, int channelType) { - if (mService != null && isEnabled() && isValidDevice(device) && config != null) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled() && isValidDevice(device) && config != null) { try { - return mService.connectChannelToSink(device, config, channelType); + return service.connectChannelToSink(device, config, channelType); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -284,9 +288,10 @@ public final class BluetoothHealth implements BluetoothProfile { */ public boolean disconnectChannel(BluetoothDevice device, BluetoothHealthAppConfiguration config, int channelId) { - if (mService != null && isEnabled() && isValidDevice(device) && config != null) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled() && isValidDevice(device) && config != null) { try { - return mService.disconnectChannel(device, config, channelId); + return service.disconnectChannel(device, config, channelId); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -312,9 +317,10 @@ public final class BluetoothHealth implements BluetoothProfile { */ public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device, BluetoothHealthAppConfiguration config) { - if (mService != null && isEnabled() && isValidDevice(device) && config != null) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled() && isValidDevice(device) && config != null) { try { - return mService.getMainChannelFd(device, config); + return service.getMainChannelFd(device, config); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -341,9 +347,10 @@ public final class BluetoothHealth implements BluetoothProfile { */ @Override public int getConnectionState(BluetoothDevice device) { - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getHealthDeviceConnectionState(device); + return service.getHealthDeviceConnectionState(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -370,15 +377,16 @@ public final class BluetoothHealth implements BluetoothProfile { */ @Override public List<BluetoothDevice> getConnectedDevices() { - if (mService != null && isEnabled()) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedHealthDevices(); + return service.getConnectedHealthDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -401,15 +409,16 @@ public final class BluetoothHealth implements BluetoothProfile { */ @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { - if (mService != null && isEnabled()) { + final IBluetoothHealth service = mService; + if (service != null && isEnabled()) { try { - return mService.getHealthDevicesMatchingConnectionStates(states); + return service.getHealthDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -455,7 +464,7 @@ public final class BluetoothHealth implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; - private IBluetoothHealth mService; + private volatile IBluetoothHealth mService; BluetoothAdapter mAdapter; /** @@ -540,11 +549,8 @@ public final class BluetoothHealth implements BluetoothProfile { return false; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } private boolean checkAppParam(String name, int role, int channelType, diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java index a9a9010c7edb..32615761cf8c 100644 --- a/core/java/android/bluetooth/BluetoothInputDevice.java +++ b/core/java/android/bluetooth/BluetoothInputDevice.java @@ -222,7 +222,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; - private IBluetoothInputDevice mService; + private volatile IBluetoothInputDevice mService; private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { @@ -331,15 +331,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -370,15 +371,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -388,15 +390,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -406,15 +409,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -424,15 +428,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -453,19 +458,20 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -484,15 +490,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.PRIORITY_OFF; } @@ -517,18 +524,13 @@ public final class BluetoothInputDevice implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_ON; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } - /** * Initiate virtual unplug for a HID input device. * @@ -540,16 +542,17 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean virtualUnplug(BluetoothDevice device) { if (DBG) log("virtualUnplug(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.virtualUnplug(device); + return service.virtualUnplug(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -565,15 +568,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean getProtocolMode(BluetoothDevice device) { if (VDBG) log("getProtocolMode(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getProtocolMode(device); + return service.getProtocolMode(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -588,15 +592,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean setProtocolMode(BluetoothDevice device, int protocolMode) { if (DBG) log("setProtocolMode(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.setProtocolMode(device, protocolMode); + return service.setProtocolMode(device, protocolMode); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -615,19 +620,19 @@ public final class BluetoothInputDevice implements BluetoothProfile { public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) { if (VDBG) { - log( - "getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId - + "bufferSize=" + bufferSize); + log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + + "bufferSize=" + bufferSize); } - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getReport(device, reportType, reportId, bufferSize); + return service.getReport(device, reportType, reportId, bufferSize); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -644,15 +649,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean setReport(BluetoothDevice device, byte reportType, String report) { if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.setReport(device, reportType, report); + return service.setReport(device, reportType, report); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -668,15 +674,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean sendData(BluetoothDevice device, String report) { if (DBG) log("sendData(" + device + "), report=" + report); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.sendData(device, report); + return service.sendData(device, report); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -691,15 +698,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean getIdleTime(BluetoothDevice device) { if (DBG) log("getIdletime(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getIdleTime(device); + return service.getIdleTime(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -715,15 +723,16 @@ public final class BluetoothInputDevice implements BluetoothProfile { */ public boolean setIdleTime(BluetoothDevice device, byte idleTime) { if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothInputDevice service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.setIdleTime(device, idleTime); + return service.setIdleTime(device, idleTime); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java index 15303dc79448..37f04278d461 100644 --- a/core/java/android/bluetooth/BluetoothInputHost.java +++ b/core/java/android/bluetooth/BluetoothInputHost.java @@ -113,7 +113,7 @@ public final class BluetoothInputHost implements BluetoothProfile { private ServiceListener mServiceListener; - private IBluetoothInputHost mService; + private volatile IBluetoothInputHost mService; private BluetoothAdapter mAdapter; @@ -202,24 +202,18 @@ public final class BluetoothInputHost implements BluetoothProfile { } }; - private ServiceConnection mConnection = new ServiceConnection() { - + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { Log.d(TAG, "onServiceConnected()"); - mService = IBluetoothInputHost.Stub.asInterface(service); - if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST, BluetoothInputHost.this); } } - public void onServiceDisconnected(ComponentName className) { Log.d(TAG, "onServiceDisconnected()"); - mService = null; - if (mServiceListener != null) { mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST); } @@ -291,9 +285,10 @@ public final class BluetoothInputHost implements BluetoothProfile { public List<BluetoothDevice> getConnectedDevices() { Log.v(TAG, "getConnectedDevices()"); - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -311,9 +306,10 @@ public final class BluetoothInputHost implements BluetoothProfile { public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states)); - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -331,9 +327,10 @@ public final class BluetoothInputHost implements BluetoothProfile { public int getConnectionState(BluetoothDevice device) { Log.v(TAG, "getConnectionState(): device=" + device); - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -370,13 +367,14 @@ public final class BluetoothInputHost implements BluetoothProfile { return false; } - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { BluetoothHidDeviceAppConfiguration config = new BluetoothHidDeviceAppConfiguration(); BluetoothHidDeviceCallbackWrapper cbw = new BluetoothHidDeviceCallbackWrapper(callback); - result = mService.registerApp(config, sdp, inQos, outQos, cbw); + result = service.registerApp(config, sdp, inQos, outQos, cbw); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -403,9 +401,10 @@ public final class BluetoothInputHost implements BluetoothProfile { boolean result = false; - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - result = mService.unregisterApp(config); + result = service.unregisterApp(config); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -427,9 +426,10 @@ public final class BluetoothInputHost implements BluetoothProfile { public boolean sendReport(BluetoothDevice device, int id, byte[] data) { boolean result = false; - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - result = mService.sendReport(device, id, data); + result = service.sendReport(device, id, data); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -454,9 +454,10 @@ public final class BluetoothInputHost implements BluetoothProfile { boolean result = false; - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - result = mService.replyReport(device, type, id, data); + result = service.replyReport(device, type, id, data); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -479,9 +480,10 @@ public final class BluetoothInputHost implements BluetoothProfile { boolean result = false; - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - result = mService.reportError(device, error); + result = service.reportError(device, error); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -502,9 +504,10 @@ public final class BluetoothInputHost implements BluetoothProfile { boolean result = false; - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - result = mService.unplug(device); + result = service.unplug(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -526,9 +529,10 @@ public final class BluetoothInputHost implements BluetoothProfile { boolean result = false; - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - result = mService.connect(device); + result = service.connect(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -549,9 +553,10 @@ public final class BluetoothInputHost implements BluetoothProfile { boolean result = false; - if (mService != null) { + final IBluetoothInputHost service = mService; + if (service != null) { try { - result = mService.disconnect(device); + result = service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java index 26a9106f49f5..5b55b23680c3 100644 --- a/core/java/android/bluetooth/BluetoothMap.java +++ b/core/java/android/bluetooth/BluetoothMap.java @@ -43,7 +43,7 @@ public final class BluetoothMap implements BluetoothProfile { public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; - private IBluetoothMap mService; + private volatile IBluetoothMap mService; private final Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; @@ -161,9 +161,10 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getState() { if (VDBG) log("getState()"); - if (mService != null) { + final IBluetoothMap service = mService; + if (service != null) { try { - return mService.getState(); + return service.getState(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -182,9 +183,10 @@ public final class BluetoothMap implements BluetoothProfile { */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); - if (mService != null) { + final IBluetoothMap service = mService; + if (service != null) { try { - return mService.getClient(); + return service.getClient(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -202,9 +204,10 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); - if (mService != null) { + final IBluetoothMap service = mService; + if (service != null) { try { - return mService.isConnected(device); + return service.isConnected(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -232,15 +235,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -272,15 +276,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public List<BluetoothDevice> getConnectedDevices() { if (DBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothMap service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -291,15 +296,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothMap service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -310,15 +316,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -335,19 +342,20 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -363,15 +371,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return PRIORITY_OFF; } @@ -403,13 +412,8 @@ public final class BluetoothMap implements BluetoothProfile { log("Bluetooth is Not enabled"); return false; } - - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } - } diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java index 3e0c36548c41..af3b662d6a49 100644 --- a/core/java/android/bluetooth/BluetoothMapClient.java +++ b/core/java/android/bluetooth/BluetoothMapClient.java @@ -59,7 +59,7 @@ public final class BluetoothMapClient implements BluetoothProfile { public static final String EXTRA_SENDER_CONTACT_NAME = "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME"; - private IBluetoothMapClient mService; + private volatile IBluetoothMapClient mService; private final Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; @@ -176,9 +176,10 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public boolean isConnected(BluetoothDevice device) { if (VDBG) Log.d(TAG, "isConnected(" + device + ")"); - if (mService != null) { + final IBluetoothMapClient service = mService; + if (service != null) { try { - return mService.isConnected(device); + return service.isConnected(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -195,9 +196,10 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE"); - if (mService != null) { + final IBluetoothMapClient service = mService; + if (service != null) { try { - return mService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -216,14 +218,15 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) Log.d(TAG, "disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -235,15 +238,16 @@ public final class BluetoothMapClient implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (DBG) Log.d(TAG, "getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<>(); } @@ -255,15 +259,16 @@ public final class BluetoothMapClient implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (DBG) Log.d(TAG, "getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<>(); } @@ -275,15 +280,16 @@ public final class BluetoothMapClient implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (DBG) Log.d(TAG, "getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -298,19 +304,20 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -326,15 +333,16 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) Log.d(TAG, "getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return PRIORITY_OFF; } @@ -353,9 +361,10 @@ public final class BluetoothMapClient implements BluetoothProfile { public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message, PendingIntent sentIntent, PendingIntent deliveredIntent) { if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent); + return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; @@ -372,9 +381,10 @@ public final class BluetoothMapClient implements BluetoothProfile { */ public boolean getUnreadMessages(BluetoothDevice device) { if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getUnreadMessages(device); + return service.getUnreadMessages(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; @@ -409,12 +419,8 @@ public final class BluetoothMapClient implements BluetoothProfile { return false; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } - } diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index 63e83d22178d..866b06308354 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -123,7 +123,7 @@ public final class BluetoothPan implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; - private IBluetoothPan mPanService; + private volatile IBluetoothPan mPanService; /** * Create a BluetoothPan proxy object for interacting with the local @@ -238,15 +238,16 @@ public final class BluetoothPan implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mPanService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mPanService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -277,15 +278,16 @@ public final class BluetoothPan implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mPanService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mPanService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -295,15 +297,16 @@ public final class BluetoothPan implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - return mPanService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -313,15 +316,16 @@ public final class BluetoothPan implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - return mPanService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -331,25 +335,25 @@ public final class BluetoothPan implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - if (mPanService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mPanService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } public void setBluetoothTethering(boolean value) { if (DBG) log("setBluetoothTethering(" + value + ")"); - - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - mPanService.setBluetoothTethering(value); + service.setBluetoothTethering(value); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); } @@ -358,10 +362,10 @@ public final class BluetoothPan implements BluetoothProfile { public boolean isTetheringOn() { if (VDBG) log("isTetheringOn()"); - - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - return mPanService.isTetheringOn(); + return service.isTetheringOn(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); } @@ -373,7 +377,6 @@ public final class BluetoothPan implements BluetoothProfile { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected"); mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service)); - if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.PAN, BluetoothPan.this); @@ -390,15 +393,11 @@ public final class BluetoothPan implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_ON; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } private static void log(String msg) { diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java index 78b7c7b7a70b..19f5198ca71a 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -68,7 +68,7 @@ public class BluetoothPbap { public static final String PBAP_STATE_CHANGED_ACTION = "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED"; - private IBluetoothPbap mService; + private volatile IBluetoothPbap mService; private final Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; @@ -214,9 +214,10 @@ public class BluetoothPbap { */ public int getState() { if (VDBG) log("getState()"); - if (mService != null) { + final IBluetoothPbap service = mService; + if (service != null) { try { - return mService.getState(); + return service.getState(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -235,9 +236,10 @@ public class BluetoothPbap { */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); - if (mService != null) { + final IBluetoothPbap service = mService; + if (service != null) { try { - return mService.getClient(); + return service.getClient(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -255,9 +257,10 @@ public class BluetoothPbap { */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); - if (mService != null) { + final IBluetoothPbap service = mService; + if (service != null) { try { - return mService.isConnected(device); + return service.isConnected(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -275,9 +278,10 @@ public class BluetoothPbap { */ public boolean disconnect() { if (DBG) log("disconnect()"); - if (mService != null) { + final IBluetoothPbap service = mService; + if (service != null) { try { - mService.disconnect(); + service.disconnect(); return true; } catch (RemoteException e) { Log.e(TAG, e.toString()); diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java index b9b372c84843..00a15f3f7087 100644 --- a/core/java/android/bluetooth/BluetoothPbapClient.java +++ b/core/java/android/bluetooth/BluetoothPbapClient.java @@ -42,7 +42,7 @@ public final class BluetoothPbapClient implements BluetoothProfile { public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED"; - private IBluetoothPbapClient mService; + private volatile IBluetoothPbapClient mService; private final Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; @@ -173,15 +173,16 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (DBG) { log("connect(" + device + ") for PBAP Client."); } - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPbapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return false; @@ -197,16 +198,17 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (DBG) { log("disconnect(" + device + ")" + new Exception()); } - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPbapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - mService.disconnect(device); + service.disconnect(device); return true; } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return false; @@ -223,15 +225,16 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (DBG) { log("getConnectedDevices()"); } - if (mService != null && isEnabled()) { + final IBluetoothPbapClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return new ArrayList<BluetoothDevice>(); @@ -247,15 +250,16 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (DBG) { log("getDevicesMatchingStates()"); } - if (mService != null && isEnabled()) { + final IBluetoothPbapClient service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return new ArrayList<BluetoothDevice>(); @@ -271,15 +275,16 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (DBG) { log("getConnectionState(" + device + ")"); } - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPbapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return BluetoothProfile.STATE_DISCONNECTED; @@ -321,14 +326,8 @@ public final class BluetoothPbapClient implements BluetoothProfile { return false; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) { - return false; - } - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - return true; - } - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } /** @@ -339,26 +338,27 @@ public final class BluetoothPbapClient implements BluetoothProfile { * {@link #PRIORITY_OFF}, * * @param device Paired bluetooth device - * @param priority + * @param priority Priority of this profile * @return true if priority is set, false on error */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) { log("setPriority(" + device + ", " + priority + ")"); } - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPbapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return false; @@ -378,15 +378,16 @@ public final class BluetoothPbapClient implements BluetoothProfile { if (VDBG) { log("getPriority(" + device + ")"); } - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPbapClient service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } - if (mService == null) { + if (service == null) { Log.w(TAG, "Proxy not attached to service"); } return PRIORITY_OFF; diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java index bcdf4938fe2f..48481620c97f 100644 --- a/core/java/android/bluetooth/BluetoothSap.java +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -68,7 +68,7 @@ public final class BluetoothSap implements BluetoothProfile { public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; - private IBluetoothSap mService; + private volatile IBluetoothSap mService; private final Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; @@ -202,9 +202,10 @@ public final class BluetoothSap implements BluetoothProfile { */ public int getState() { if (VDBG) log("getState()"); - if (mService != null) { + final IBluetoothSap service = mService; + if (service != null) { try { - return mService.getState(); + return service.getState(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -224,9 +225,10 @@ public final class BluetoothSap implements BluetoothProfile { */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); - if (mService != null) { + final IBluetoothSap service = mService; + if (service != null) { try { - return mService.getClient(); + return service.getClient(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -246,9 +248,10 @@ public final class BluetoothSap implements BluetoothProfile { */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); - if (mService != null) { + final IBluetoothSap service = mService; + if (service != null) { try { - return mService.isConnected(device); + return service.isConnected(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -279,15 +282,16 @@ public final class BluetoothSap implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothSap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -299,15 +303,16 @@ public final class BluetoothSap implements BluetoothProfile { */ public List<BluetoothDevice> getConnectedDevices() { if (DBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothSap service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -319,15 +324,16 @@ public final class BluetoothSap implements BluetoothProfile { */ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothSap service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -339,15 +345,16 @@ public final class BluetoothSap implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothSap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -363,19 +370,20 @@ public final class BluetoothSap implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothSap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -388,19 +396,20 @@ public final class BluetoothSap implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothSap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return PRIORITY_OFF; } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) log("Proxy object connected"); mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service)); @@ -432,15 +441,8 @@ public final class BluetoothSap implements BluetoothProfile { return false; } - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) { - return false; - } - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - return true; - } - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } } diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 1bb0fbb74a53..f527f77ddd7c 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -18,14 +18,13 @@ package android.net; import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.ProxyInfo; -import android.os.Parcelable; import android.os.Parcel; +import android.os.Parcelable; import android.text.TextUtils; -import java.net.InetAddress; import java.net.Inet4Address; import java.net.Inet6Address; +import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; @@ -504,11 +503,22 @@ public final class LinkProperties implements Parcelable { } /** + * Make sure this LinkProperties instance contains routes that cover the local subnet + * of its link addresses. Add any route that is missing. + * @hide + */ + public void ensureDirectlyConnectedRoutes() { + for (LinkAddress addr: mLinkAddresses) { + addRoute(new RouteInfo(addr, null, mIfaceName)); + } + } + + /** * Returns all the routes on this link and all the links stacked above it. * @hide */ public List<RouteInfo> getAllRoutes() { - List<RouteInfo> routes = new ArrayList(); + List<RouteInfo> routes = new ArrayList<>(); routes.addAll(mRoutes); for (LinkProperties stacked: mStackedLinks.values()) { routes.addAll(stacked.getAllRoutes()); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 0780af602be2..171adc054bbe 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -677,36 +677,33 @@ public class NetworkStats implements Parcelable { entry.tag = left.tag[i]; entry.metered = left.metered[i]; entry.roaming = left.roaming[i]; + entry.rxBytes = left.rxBytes[i]; + entry.rxPackets = left.rxPackets[i]; + entry.txBytes = left.txBytes[i]; + entry.txPackets = left.txPackets[i]; + entry.operations = left.operations[i]; // find remote row that matches, and subtract final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, entry.roaming, i); - if (j == -1) { - // newly appearing row, return entire value - entry.rxBytes = left.rxBytes[i]; - entry.rxPackets = left.rxPackets[i]; - entry.txBytes = left.txBytes[i]; - entry.txPackets = left.txPackets[i]; - entry.operations = left.operations[i]; - } else { - // existing row, subtract remote value - entry.rxBytes = left.rxBytes[i] - right.rxBytes[j]; - entry.rxPackets = left.rxPackets[i] - right.rxPackets[j]; - entry.txBytes = left.txBytes[i] - right.txBytes[j]; - entry.txPackets = left.txPackets[i] - right.txPackets[j]; - entry.operations = left.operations[i] - right.operations[j]; - - if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 - || entry.txPackets < 0 || entry.operations < 0) { - if (observer != null) { - observer.foundNonMonotonic(left, i, right, j, cookie); - } - entry.rxBytes = Math.max(entry.rxBytes, 0); - entry.rxPackets = Math.max(entry.rxPackets, 0); - entry.txBytes = Math.max(entry.txBytes, 0); - entry.txPackets = Math.max(entry.txPackets, 0); - entry.operations = Math.max(entry.operations, 0); + if (j != -1) { + // Found matching row, subtract remote value. + entry.rxBytes -= right.rxBytes[j]; + entry.rxPackets -= right.rxPackets[j]; + entry.txBytes -= right.txBytes[j]; + entry.txPackets -= right.txPackets[j]; + entry.operations -= right.operations[j]; + } + + if (entry.isNegative()) { + if (observer != null) { + observer.foundNonMonotonic(left, i, right, j, cookie); } + entry.rxBytes = Math.max(entry.rxBytes, 0); + entry.rxPackets = Math.max(entry.rxPackets, 0); + entry.txBytes = Math.max(entry.txBytes, 0); + entry.txPackets = Math.max(entry.txPackets, 0); + entry.operations = Math.max(entry.operations, 0); } result.addValues(entry); diff --git a/core/jni/Android.bp b/core/jni/Android.bp index abd6278b056a..c5279e10d93f 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -231,6 +231,7 @@ cc_library_shared { "libutils", "libbinder", "libui", + "libgraphicsenv", "libgui", "libsensor", "libinput", diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp index 399dec8fc9cf..f749488f39b0 100644 --- a/core/jni/android_os_GraphicsEnvironment.cpp +++ b/core/jni/android_os_GraphicsEnvironment.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "GraphicsEnvironment" -#include <ui/GraphicsEnv.h> +#include <graphicsenv/GraphicsEnv.h> #include <nativehelper/ScopedUtfChars.h> #include "core_jni_helpers.h" diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index 7ec4b8ea0799..5ef2a9e6465c 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -56,7 +56,7 @@ static inline jobjectArray toJavaStringArray(JNIEnv* env, const V& v) { } template<typename T> -static void tryAddSchema(const T* object, const XmlConverter<T>& converter, +static void tryAddSchema(const std::shared_ptr<const T>& object, const XmlConverter<T>& converter, const std::string& description, std::vector<std::string>* cStrings) { if (object == nullptr) { @@ -66,7 +66,7 @@ static void tryAddSchema(const T* object, const XmlConverter<T>& converter, } } -static void tryAddHalNamesAndVersions(const HalManifest *manifest, +static void tryAddHalNamesAndVersions(const std::shared_ptr<const HalManifest>& manifest, const std::string& description, std::set<std::string> *output) { if (manifest == nullptr) { @@ -119,7 +119,7 @@ static jobjectArray android_os_VintfObject_getHalNamesAndVersions(JNIEnv* env, j } static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) { - const HalManifest *manifest = VintfObject::GetDeviceHalManifest(); + std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest(); if (manifest == nullptr || manifest->type() != SchemaType::DEVICE) { LOG(WARNING) << __FUNCTION__ << "Cannot get device manifest"; return nullptr; @@ -129,7 +129,7 @@ static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) { } static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) { - const HalManifest *manifest = VintfObject::GetFrameworkHalManifest(); + std::shared_ptr<const HalManifest> manifest = VintfObject::GetFrameworkHalManifest(); if (manifest == nullptr || manifest->type() != SchemaType::FRAMEWORK) { LOG(WARNING) << __FUNCTION__ << "Cannot get framework manifest"; return nullptr; diff --git a/core/jni/android_os_VintfRuntimeInfo.cpp b/core/jni/android_os_VintfRuntimeInfo.cpp index 19220cf05adb..315eac1b9414 100644 --- a/core/jni/android_os_VintfRuntimeInfo.cpp +++ b/core/jni/android_os_VintfRuntimeInfo.cpp @@ -32,7 +32,7 @@ using vintf::VintfObject; #define MAP_STRING_METHOD(javaMethod, cppString) \ static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) \ { \ - const RuntimeInfo *info = VintfObject::GetRuntimeInfo(); \ + std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(); \ if (info == nullptr) return nullptr; \ return env->NewStringUTF((cppString).c_str()); \ } \ @@ -50,7 +50,7 @@ MAP_STRING_METHOD(getBootVbmetaAvbVersion, vintf::to_string(info->bootVbmetaAvbV static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv *env, jclass clazz) { - const RuntimeInfo *info = VintfObject::GetRuntimeInfo(); + std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(); if (info == nullptr) return 0; return static_cast<jlong>(info->kernelSepolicyVersion()); } diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java index d5f632190d06..9686dd9e57a0 100644 --- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java +++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java @@ -24,10 +24,15 @@ import android.net.RouteInfo; import android.system.OsConstants; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.Suppress; +import android.util.ArraySet; + import junit.framework.TestCase; import java.net.InetAddress; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; public class LinkPropertiesTest extends TestCase { @@ -678,4 +683,76 @@ public class LinkPropertiesTest extends TestCase { stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress)); assertTrue(v6lp.isReachable(DNS1)); } + + @SmallTest + public void testLinkPropertiesEnsureDirectlyConnectedRoutes() { + // IPv4 case: no route added initially + LinkProperties rmnet0 = new LinkProperties(); + rmnet0.setInterfaceName("rmnet0"); + rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8")); + RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null, + rmnet0.getInterfaceName()); + + // Since no routes is added explicitly, getAllRoutes() should return empty. + assertTrue(rmnet0.getAllRoutes().isEmpty()); + rmnet0.ensureDirectlyConnectedRoutes(); + // ensureDirectlyConnectedRoutes() should have added the missing local route. + assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes()); + + // IPv4 case: both direct and default routes added initially + LinkProperties rmnet1 = new LinkProperties(); + rmnet1.setInterfaceName("rmnet1"); + rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8")); + RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null, + NetworkUtils.numericToInetAddress("10.0.0.1"), rmnet1.getInterfaceName()); + RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null, + rmnet1.getInterfaceName()); + rmnet1.addRoute(defaultRoute1); + rmnet1.addRoute(directRoute1); + + // Check added routes + assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes()); + // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected + // route is already part of the configuration. + rmnet1.ensureDirectlyConnectedRoutes(); + assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes()); + + // IPv6 case: only default routes added initially + LinkProperties rmnet2 = new LinkProperties(); + rmnet2.setInterfaceName("rmnet2"); + rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64")); + rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64")); + RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null, + NetworkUtils.numericToInetAddress("2001:db8::1"), rmnet2.getInterfaceName()); + RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null, + rmnet2.getInterfaceName()); + RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null, + rmnet2.getInterfaceName()); + rmnet2.addRoute(defaultRoute2); + + assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes()); + rmnet2.ensureDirectlyConnectedRoutes(); + assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2), + rmnet2.getAllRoutes()); + + // Corner case: no interface name + LinkProperties rmnet3 = new LinkProperties(); + rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24")); + RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null, + rmnet3.getInterfaceName()); + + assertTrue(rmnet3.getAllRoutes().isEmpty()); + rmnet3.ensureDirectlyConnectedRoutes(); + assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes()); + + } + + private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) { + Set<RouteInfo> expectedSet = new ArraySet<>(expected); + Set<RouteInfo> actualSet = new ArraySet<>(actual); + // Duplicated entries in actual routes are considered failures + assertEquals(actual.size(), actualSet.size()); + + assertEquals(expectedSet, actualSet); + } } diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 0782269d7de1..7a0ef2b770ce 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -59,7 +59,6 @@ namespace android { #endif #define IDMAP_MAGIC 0x504D4449 -#define IDMAP_CURRENT_VERSION 0x00000001 #define APP_PACKAGE_ID 0x7f #define SYS_PACKAGE_ID 0x01 @@ -246,11 +245,11 @@ static bool assertIdmapHeader(const void* idmap, size_t size) { } const uint32_t version = htodl(*(reinterpret_cast<const uint32_t*>(idmap) + 1)); - if (version != IDMAP_CURRENT_VERSION) { + if (version != ResTable::IDMAP_CURRENT_VERSION) { // We are strict about versions because files with this format are // auto-generated and don't need backwards compatibility. ALOGW("idmap: version mismatch in header (is 0x%08x, expected 0x%08x)", - version, IDMAP_CURRENT_VERSION); + version, ResTable::IDMAP_CURRENT_VERSION); return false; } return true; @@ -6855,7 +6854,7 @@ status_t ResTable::createIdmap(const ResTable& overlay, uint32_t* data = (uint32_t*)*outData; *data++ = htodl(IDMAP_MAGIC); - *data++ = htodl(IDMAP_CURRENT_VERSION); + *data++ = htodl(ResTable::IDMAP_CURRENT_VERSION); *data++ = htodl(targetCrc); *data++ = htodl(overlayCrc); const char* paths[] = { targetPath, overlayPath }; diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 7a6e37d41b7c..66c66c251d9b 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1933,6 +1933,7 @@ public: void** outData, size_t* outSize) const; static const size_t IDMAP_HEADER_SIZE_BYTES = 4 * sizeof(uint32_t) + 2 * 256; + static const uint32_t IDMAP_CURRENT_VERSION = 0x00000001; // Retrieve idmap meta-data. // diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java index c1f03fd81151..c79c018d34a6 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java @@ -170,7 +170,8 @@ public class CaptivePortalLoginActivity extends Activity { } private void done(boolean success) { - if (DBG) logd(String.format("Result success %b for %s", success, mUrl.toString())); + if (DBG) logd(String.format("Result success %b for %s", success, + mUrl != null ? mUrl.toString() : "null")); if (success) { // Trigger re-evaluation upon success http response code CarrierActionUtils.applyCarrierAction( @@ -226,7 +227,8 @@ public class CaptivePortalLoginActivity extends Activity { int httpResponseCode = 500; int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE); try { - urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl); + urlConnection = (HttpURLConnection) mNetwork.openConnection( + new URL(mCm.getCaptivePortalServerUrl())); urlConnection.setInstanceFollowRedirects(false); urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS); urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS); @@ -234,6 +236,7 @@ public class CaptivePortalLoginActivity extends Activity { urlConnection.getInputStream(); httpResponseCode = urlConnection.getResponseCode(); } catch (IOException e) { + loge(e.getMessage()); } finally { if (urlConnection != null) urlConnection.disconnect(); TrafficStats.setThreadStatsTag(oldTag); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index e279a09c2bd2..5f302c6a5035 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -332,8 +332,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } public int getProfileConnectionState(LocalBluetoothProfile profile) { - if (mProfileConnectionState == null || - mProfileConnectionState.get(profile) == null) { + if (mProfileConnectionState.get(profile) == null) { // If cache is empty make the binder call to get the state int state = profile.getConnectionStatus(mDevice); mProfileConnectionState.put(profile, state); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 672f2c2df06e..3495f570cc2c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -439,15 +439,22 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { public static class DrawableIcon extends Icon { protected final Drawable mDrawable; + protected final Drawable mInvisibleDrawable; public DrawableIcon(Drawable drawable) { mDrawable = drawable; + mInvisibleDrawable = drawable.getConstantState().newDrawable(); } @Override public Drawable getDrawable(Context context) { return mDrawable; } + + @Override + public Drawable getInvisibleDrawable(Context context) { + return mInvisibleDrawable; + } } public static class DrawableIconWithRes extends DrawableIcon { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index f58fe8290a43..55498af7a54b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -4486,7 +4486,7 @@ public class StatusBar extends SystemUI implements DemoMode, animateCollapsePanels(); return true; } - if (mKeyguardUserSwitcher.hideIfNotSimple(true)) { + if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) { return true; } return false; diff --git a/proto/src/ipconnectivity.proto b/proto/src/ipconnectivity.proto index 76c54185a774..01fb860e92d6 100644 --- a/proto/src/ipconnectivity.proto +++ b/proto/src/ipconnectivity.proto @@ -23,7 +23,7 @@ message NetworkId { // It is not intended to map one to one to the TRANSPORT_* constants defined in // android.net.NetworkCapabilities. Instead it is intended to be used as // a dimension field for metrics events and aggregated metrics. -// Next tag: 7 +// Next tag: 10 enum LinkLayer { // An unknown link layer technology. UNKNOWN = 0; @@ -32,6 +32,9 @@ enum LinkLayer { CELLULAR = 2; ETHERNET = 3; WIFI = 4; + WIFI_P2P = 7; + WIFI_NAN = 8; // Also known as WiFi Aware + LOWPAN = 9; // Indicates that the link layer dimension is not relevant for the metrics or // event considered. @@ -47,16 +50,18 @@ message Pair { optional int32 value = 2; }; -// Logs changes in the system default network. Changes can be 1) acquiring a -// default network with no previous default, 2) a switch of the system default -// network to a new default network, 3) a loss of the system default network. -// This message is associated to android.net.metrics.DefaultNetworkEvent. +// An event record when the system default network disconnects or the system +// switches to a new default network. +// Next tag: 10. message DefaultNetworkEvent { - // A value of 0 means this is a loss of the system default network. - optional NetworkId network_id = 1; - // A value of 0 means there was no previous default network. - optional NetworkId previous_network_id = 2; + // Reason why this network stopped being the default. + enum LostReason { + UNKNOWN = 0; + OUTSCORED = 1; + INVALIDATION = 2; + DISCONNECT = 3; + }; // Whether the network supports IPv4, IPv6, or both. enum IPSupport { @@ -66,17 +71,52 @@ message DefaultNetworkEvent { DUAL = 3; }; + // Duration in milliseconds when this network was the default. + // Since version 4 + optional int64 default_network_duration_ms = 5; + + // Duration in milliseconds without a default network before this network + // became the default. + // Since version 4 + optional int64 no_default_network_duration_ms = 6; + + // Network score of this network when it became the default network. + // Since version 4 + optional int64 initial_score = 7; + + // Network score of this network when it stopped being the default network. + // Since version 4 + optional int64 final_score = 8; + + // Best available information about IP support of this default network. + // Since version 4 + optional IPSupport ip_support = 9; + + + // Deprecated fields + + // A value of 0 means this is a loss of the system default network. + // Deprecated since version 3. Replaced by top level network_id. + optional NetworkId network_id = 1 [deprecated = true]; + + // A value of 0 means there was no previous default network. + // Deprecated since version 3. Replaced by previous_default_network_id. + optional NetworkId previous_network_id = 2 [deprecated = true]; + // Best available information about IP support of the previous network when // disconnecting or switching to a new default network. - optional IPSupport previous_network_ip_support = 3; + // Deprecated since version 3. Replaced by ip_support field. + optional IPSupport previous_network_ip_support = 3 [deprecated = true]; // The transport types of the new default network, represented by // TRANSPORT_* constants as defined in NetworkCapabilities. - repeated int32 transport_types = 4; + // Deprecated since version 3. Replaced by top-level transports field. + repeated int32 transport_types = 4 [deprecated = true]; }; // Logs IpReachabilityMonitor probe events and NUD_FAILED events. // This message is associated to android.net.metrics.IpReachabilityEvent. +// Next tag: 3. message IpReachabilityEvent { // The interface name (wlan, rmnet, lo, ...) on which the probe was sent. // Deprecated since version 2, to be replaced by link_layer field. @@ -91,6 +131,7 @@ message IpReachabilityEvent { // Logs NetworkMonitor and ConnectivityService events related to the state of // a network: connection, evaluation, validation, lingering, and disconnection. // This message is associated to android.net.metrics.NetworkEvent. +// Next tag: 4. message NetworkEvent { // The id of the network on which this event happened. // Deprecated since version 3. @@ -108,6 +149,7 @@ message NetworkEvent { // Logs individual captive portal probing events that are performed when // evaluating or reevaluating networks for Internet connectivity. // This message is associated to android.net.metrics.ValidationProbeEvent. +// Next tag: 5. message ValidationProbeEvent { // The id of the network for which the probe was sent. // Deprecated since version 3. @@ -124,26 +166,64 @@ message ValidationProbeEvent { optional int32 probe_result = 4; } -// Logs DNS lookup latencies. Repeated fields must have the same length. +// Logs DNS lookup latencies. // This message is associated to android.net.metrics.DnsEvent. -// Deprecated since version 2. +// Next tag: 11 message DNSLookupBatch { + + // The time it took for successful DNS lookups to complete. + // The number of repeated values can be less than getaddrinfo_query_count + // + gethostbyname_query_count in case of event rate-limiting. + repeated int32 latencies_ms = 4; + + // The total number of getaddrinfo queries. + // Since version 4. + optional int64 getaddrinfo_query_count = 5; + + // The total number of gethostbyname queries. + // Since version 4. + optional int64 gethostbyname_query_count = 6; + + // The total number of getaddrinfo errors. + // Since version 4. + optional int64 getaddrinfo_error_count = 7; + + // The total number of gethostbyname errors. + // Since version 4. + optional int64 gethostbyname_error_count = 8; + + // Counts of all errors returned by getaddrinfo. + // The Pair key field is the getaddrinfo error value. + // The value field is the count for that return value. + // Since version 4 + repeated Pair getaddrinfo_errors = 9; + + // Counts of all errors returned by gethostbyname. + // The Pair key field is the gethostbyname errno value. + // the Pair value field is the count for that errno code. + // Since version 4 + repeated Pair gethostbyname_errors = 10; + + + // Deprecated fields + // The id of the network on which the DNS lookups took place. - optional NetworkId network_id = 1; + // Deprecated since version 3. + optional NetworkId network_id = 1 [deprecated = true]; // The types of the DNS lookups, as defined in android.net.metrics.DnsEvent. - repeated int32 event_types = 2; + // Deprecated since version 3. + repeated int32 event_types = 2 [deprecated = true]; // The return values of the DNS resolver for each DNS lookups. - repeated int32 return_codes = 3; - - // The time it took for each DNS lookups to complete. - repeated int32 latencies_ms = 4; + // Deprecated since version 3. + repeated int32 return_codes = 3 [deprecated = true]; }; // Represents a collections of DNS lookup latencies and counters for a // particular combination of DNS query type and return code. // Since version 2. +// Next tag: 7. message DNSLatencies { // The type of the DNS lookups, as defined in android.net.metrics.DnsEvent. // Acts as a key for a set of DNS query results. @@ -203,6 +283,7 @@ message ConnectStatistics { // state transition or a response packet parsing error. // This message is associated to android.net.metrics.DhcpClientEvent and // android.net.metrics.DhcpErrorEvent. +// Next tag: 5 message DHCPEvent { // The interface name (wlan, rmnet, lo, ...) on which the event happened. // Deprecated since version 2, to be replaced by link_layer field. @@ -255,7 +336,7 @@ message ApfProgramEvent { // Represents Router Advertisement listening statistics for an interface with // Android Packet Filter enabled. // Since version 1. -// Next tag: 12 +// Next tag: 15 message ApfStatistics { // The time interval in milliseconds these stastistics cover. optional int64 duration_ms = 1; @@ -288,12 +369,28 @@ message ApfStatistics { // The total number of APF program updates triggered when disabling the // multicast filter. Since version 3. + // Since version 4. optional int32 program_updates_allowing_multicast = 11; + + // The total number of packets processed by the APF interpreter. + // Since version 4. + optional int32 total_packet_processed = 12; + + // The total number of packets dropped by the APF interpreter. + // Since version 4. + optional int32 total_packet_dropped = 13; + + // List of hardware counters collected by the APF interpreter. + // The Pair key is the counter id, defined in android.net.metrics.ApfStats. + // The Pair value is the counter value. + // Since version 4. + repeated Pair hardware_counters = 14; } // Represents the reception of a Router Advertisement packet for an interface // with Android Packet Filter enabled. // Since version 1. +// Next tag: 7. message RaEvent { // All lifetime values are expressed in seconds. The default value for an // option lifetime that was not present in the RA option list is -1. @@ -322,6 +419,7 @@ message RaEvent { // Represents an IP provisioning event in IpManager and how long the // provisioning action took. // This message is associated to android.net.metrics.IpManagerEvent. +// Next tag: 4. message IpProvisioningEvent { // The interface name (wlan, rmnet, lo, ...) on which the probe was sent. // Deprecated since version 2, to be replaced by link_layer field. @@ -335,8 +433,48 @@ message IpProvisioningEvent { optional int32 latency_ms = 3; } +// Represents statistics from a single android Network. +// Since version 4. Replace NetworkEvent. +// Next tag: 9. +message NetworkStats { + + // Duration of this Network lifecycle in milliseconds. + optional int64 duration_ms = 1; + + // Information about IP support of this network. + optional DefaultNetworkEvent.IPSupport ip_support = 2; + + // True if the network was validated at least once. + optional bool ever_validated = 3; + + // True if a captive portal was found at least once on this network. + optional bool portal_found = 4; + + // Total number of times no connectivity was reported for this network. + optional int32 no_connectivity_reports = 5; + + // Total number of validation attempts. + optional int32 validation_attempts = 6; + + // Results from all validation attempts. + // The Pair key is the result: + // 0 -> unvalidated + // 1 -> validated + // 2 -> captive portal + // The Pair value is the duration of the validation attempts in milliseconds. + repeated Pair validation_events = 7; + + // Time series of validation states in time order. + // The Pair key is the state: + // 0 -> unvalidated + // 1 -> validated + // 2 -> captive portal, + // The Pair value is the duration of that state in milliseconds. + repeated Pair validation_states = 8; +} + // Represents one of the IP connectivity event defined in this file. -// Next tag: 19 +// Next tag: 20 message IpConnectivityEvent { // Time in ms when the event was recorded. optional int64 time_ms = 1; @@ -370,14 +508,13 @@ message IpConnectivityEvent { oneof event { // An event about the system default network. - // The link_layer field is not relevant for this event and set to NONE. DefaultNetworkEvent default_network_event = 2; // An IP reachability probe event. IpReachabilityEvent ip_reachability_event = 3; // A network lifecycle event. - NetworkEvent network_event = 4; + NetworkEvent network_event = 4 [deprecated = true]; // A batch of DNS lookups. // Deprecated in the nyc-mr2 release since version 2,and replaced by @@ -407,10 +544,14 @@ message IpConnectivityEvent { // An RA packet reception event. RaEvent ra_event = 11; + + // Network statistics. + NetworkStats network_stats = 19; }; }; // The information about IP connectivity events. +// Next tag: 4. message IpConnectivityLog { // An array of IP connectivity events. repeated IpConnectivityEvent events = 1; @@ -424,5 +565,6 @@ message IpConnectivityLog { // nyc-mr1: not populated, implicitly 1. // nyc-mr2: 2. // oc: 3. + // oc-dr1: 4. optional int32 version = 3; }; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 60476447ca49..1703bd55d667 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4335,11 +4335,13 @@ public class ConnectivityService extends IConnectivityManager.Stub int currentScore, NetworkMisc networkMisc) { enforceConnectivityInternalPermission(); + LinkProperties lp = new LinkProperties(linkProperties); + lp.ensureDirectlyConnectedRoutes(); // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // satisfies mDefaultRequest. final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), - new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties( - linkProperties), new NetworkCapabilities(networkCapabilities), currentScore, + new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, + new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this); synchronized (this) { nai.networkMonitor.systemReady = mSystemReady; @@ -4649,6 +4651,8 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized (nai) { nai.linkProperties = newLp; } + // msg.obj is already a defensive copy. + nai.linkProperties.ensureDirectlyConnectedRoutes(); if (nai.everConnected) { updateLinkProperties(nai, oldLp); } diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java index 3c8c699a65bb..1517887efec2 100644 --- a/services/core/java/com/android/server/RecoverySystemService.java +++ b/services/core/java/com/android/server/RecoverySystemService.java @@ -285,8 +285,9 @@ public final class RecoverySystemService extends SystemService { // Send the BCB commands if it's to setup BCB. if (isSetup) { - dos.writeInt(command.length()); - dos.writeBytes(command); + byte[] cmdUtf8 = command.getBytes("UTF-8"); + dos.writeInt(cmdUtf8.length); + dos.write(cmdUtf8, 0, cmdUtf8.length); dos.flush(); } diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java index 5dee91de0e77..ee382199438b 100644 --- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java +++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java @@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.MAX_TRANSPORT; import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; +import static android.net.NetworkCapabilities.TRANSPORT_LOWPAN; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; @@ -362,29 +363,46 @@ final public class IpConnectivityEventBuilder { TRANSPORT_LINKLAYER_MAP[TRANSPORT_BLUETOOTH] = IpConnectivityLogClass.BLUETOOTH; TRANSPORT_LINKLAYER_MAP[TRANSPORT_ETHERNET] = IpConnectivityLogClass.ETHERNET; TRANSPORT_LINKLAYER_MAP[TRANSPORT_VPN] = IpConnectivityLogClass.UNKNOWN; - // TODO: change mapping TRANSPORT_WIFI_AWARE -> WIFI_AWARE - TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI_AWARE] = IpConnectivityLogClass.UNKNOWN; + TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI_AWARE] = IpConnectivityLogClass.WIFI_NAN; + TRANSPORT_LINKLAYER_MAP[TRANSPORT_LOWPAN] = IpConnectivityLogClass.LOWPAN; }; private static int ifnameToLinkLayer(String ifname) { // Do not try to catch all interface names with regexes, instead only catch patterns that // are cheap to check, and otherwise fallback on postprocessing in aggregation layer. - for (int i = 0; i < IFNAME_LINKLAYER_MAP.size(); i++) { - String pattern = IFNAME_LINKLAYER_MAP.valueAt(i); + for (int i = 0; i < KNOWN_PREFIX; i++) { + String pattern = IFNAME_PREFIXES[i]; if (ifname.startsWith(pattern)) { - return IFNAME_LINKLAYER_MAP.keyAt(i); + return IFNAME_LINKLAYERS[i]; } } return IpConnectivityLogClass.UNKNOWN; } - private static final SparseArray<String> IFNAME_LINKLAYER_MAP = new SparseArray<String>(); + private static final int KNOWN_PREFIX = 7; + private static final String[] IFNAME_PREFIXES = new String[KNOWN_PREFIX]; + private static final int[] IFNAME_LINKLAYERS = new int[KNOWN_PREFIX]; static { - IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.CELLULAR, "rmnet"); - IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.WIFI, "wlan"); - IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.BLUETOOTH, "bt-pan"); - // TODO: rekey to USB - IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.ETHERNET, "usb"); - // TODO: add mappings for nan -> WIFI_AWARE and p2p -> WIFI_P2P + // Ordered from most likely link layer to least likely. + IFNAME_PREFIXES[0] = "rmnet"; + IFNAME_LINKLAYERS[0] = IpConnectivityLogClass.CELLULAR; + + IFNAME_PREFIXES[1] = "wlan"; + IFNAME_LINKLAYERS[1] = IpConnectivityLogClass.WIFI; + + IFNAME_PREFIXES[2] = "bt-pan"; + IFNAME_LINKLAYERS[2] = IpConnectivityLogClass.BLUETOOTH; + + IFNAME_PREFIXES[3] = "p2p"; + IFNAME_LINKLAYERS[3] = IpConnectivityLogClass.WIFI_P2P; + + IFNAME_PREFIXES[4] = "aware"; + IFNAME_LINKLAYERS[4] = IpConnectivityLogClass.WIFI_NAN; + + IFNAME_PREFIXES[5] = "eth"; + IFNAME_LINKLAYERS[5] = IpConnectivityLogClass.ETHERNET; + + IFNAME_PREFIXES[6] = "wpan"; + IFNAME_LINKLAYERS[6] = IpConnectivityLogClass.LOWPAN; } } diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java index 788867f9137e..5eafe5f9f64f 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java +++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java @@ -30,6 +30,10 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkStats; import android.net.RouteInfo; +import android.net.netlink.ConntrackMessage; +import android.net.netlink.NetlinkConstants; +import android.net.netlink.NetlinkSocket; +import android.net.util.IpUtils; import android.net.util.SharedLog; import android.os.Handler; import android.os.Looper; @@ -37,10 +41,12 @@ import android.os.INetworkManagementService; import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; +import android.system.ErrnoException; +import android.system.OsConstants; import android.text.TextUtils; -import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats; import java.net.Inet4Address; import java.net.Inet6Address; @@ -63,6 +69,7 @@ import java.util.concurrent.TimeUnit; */ public class OffloadController { private static final String TAG = OffloadController.class.getSimpleName(); + private static final boolean DBG = false; private static final String ANYIP = "0.0.0.0"; private static final ForwardedStats EMPTY_STATS = new ForwardedStats(); @@ -96,6 +103,9 @@ public class OffloadController { // includes upstream interfaces that have a quota set. private HashMap<String, Long> mInterfaceQuotas = new HashMap<>(); + private int mNatUpdateCallbacksReceived; + private int mNatUpdateNetlinkErrors; + public OffloadController(Handler h, OffloadHardwareInterface hwi, ContentResolver contentResolver, INetworkManagementService nms, SharedLog log) { mHandler = h; @@ -115,12 +125,12 @@ public class OffloadController { } } - public void start() { - if (started()) return; + public boolean start() { + if (started()) return true; if (isOffloadDisabled()) { mLog.i("tethering offload disabled"); - return; + return false; } if (!mConfigInitialized) { @@ -128,11 +138,14 @@ public class OffloadController { if (!mConfigInitialized) { mLog.i("tethering offload config not supported"); stop(); - return; + return false; } } mControlInitialized = mHwInterface.initOffloadControl( + // OffloadHardwareInterface guarantees that these callback + // methods are called on the handler passed to it, which is the + // same as mHandler, as coordinated by the setup in Tethering. new OffloadHardwareInterface.ControlCallback() { @Override public void onStarted() { @@ -203,15 +216,20 @@ public class OffloadController { String srcAddr, int srcPort, String dstAddr, int dstPort) { if (!started()) return; - mLog.log(String.format("NAT timeout update: %s (%s,%s) -> (%s,%s)", - proto, srcAddr, srcPort, dstAddr, dstPort)); + updateNatTimeout(proto, srcAddr, srcPort, dstAddr, dstPort); } }); - if (!mControlInitialized) { + + final boolean isStarted = started(); + if (!isStarted) { mLog.i("tethering offload control not supported"); stop(); + } else { + mLog.log("tethering offload started"); + mNatUpdateCallbacksReceived = 0; + mNatUpdateNetlinkErrors = 0; } - mLog.log("tethering offload started"); + return isStarted; } public void stop() { @@ -227,6 +245,10 @@ public class OffloadController { if (wasStarted) mLog.log("tethering offload stopped"); } + private boolean started() { + return mConfigInitialized && mControlInitialized; + } + private class OffloadTetheringStatsProvider extends ITetheringStatsProvider.Stub { @Override public NetworkStats getTetherStats(int how) { @@ -402,10 +424,6 @@ public class OffloadController { mContentResolver, TETHER_OFFLOAD_DISABLED, defaultDisposition) != 0); } - private boolean started() { - return mConfigInitialized && mControlInitialized; - } - private boolean pushUpstreamParameters(String prevUpstream) { final String iface = currentUpstreamInterface(); @@ -516,10 +534,113 @@ public class OffloadController { pw.println("Offload disabled"); return; } - pw.println("Offload HALs " + (started() ? "started" : "not started")); + final boolean isStarted = started(); + pw.println("Offload HALs " + (isStarted ? "started" : "not started")); LinkProperties lp = mUpstreamLinkProperties; String upstream = (lp != null) ? lp.getInterfaceName() : null; pw.println("Current upstream: " + upstream); pw.println("Exempt prefixes: " + mLastLocalPrefixStrs); + pw.println("NAT timeout update callbacks received during the " + + (isStarted ? "current" : "last") + + " offload session: " + + mNatUpdateCallbacksReceived); + pw.println("NAT timeout update netlink errors during the " + + (isStarted ? "current" : "last") + + " offload session: " + + mNatUpdateNetlinkErrors); + } + + private void updateNatTimeout( + int proto, String srcAddr, int srcPort, String dstAddr, int dstPort) { + final String protoName = protoNameFor(proto); + if (protoName == null) { + mLog.e("Unknown NAT update callback protocol: " + proto); + return; + } + + final Inet4Address src = parseIPv4Address(srcAddr); + if (src == null) { + mLog.e("Failed to parse IPv4 address: " + srcAddr); + return; + } + + if (!IpUtils.isValidUdpOrTcpPort(srcPort)) { + mLog.e("Invalid src port: " + srcPort); + return; + } + + final Inet4Address dst = parseIPv4Address(dstAddr); + if (dst == null) { + mLog.e("Failed to parse IPv4 address: " + dstAddr); + return; + } + + if (!IpUtils.isValidUdpOrTcpPort(dstPort)) { + mLog.e("Invalid dst port: " + dstPort); + return; + } + + mNatUpdateCallbacksReceived++; + if (DBG) { + mLog.log(String.format("NAT timeout update: %s (%s, %s) -> (%s, %s)", + protoName, srcAddr, srcPort, dstAddr, dstPort)); + } + + final int timeoutSec = connectionTimeoutUpdateSecondsFor(proto); + final byte[] msg = ConntrackMessage.newIPv4TimeoutUpdateRequest( + proto, src, srcPort, dst, dstPort, timeoutSec); + + try { + NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_NETFILTER, msg); + } catch (ErrnoException e) { + mNatUpdateNetlinkErrors++; + mLog.e("Error updating NAT conntrack entry: " + e + + ", msg: " + NetlinkConstants.hexify(msg)); + mLog.log("NAT timeout update callbacks received: " + mNatUpdateCallbacksReceived); + mLog.log("NAT timeout update netlink errors: " + mNatUpdateNetlinkErrors); + } + } + + private static Inet4Address parseIPv4Address(String addrString) { + try { + final InetAddress ip = InetAddress.parseNumericAddress(addrString); + // TODO: Consider other sanitization steps here, including perhaps: + // not eql to 0.0.0.0 + // not within 169.254.0.0/16 + // not within ::ffff:0.0.0.0/96 + // not within ::/96 + // et cetera. + if (ip instanceof Inet4Address) { + return (Inet4Address) ip; + } + } catch (IllegalArgumentException iae) {} + return null; + } + + private static String protoNameFor(int proto) { + // OsConstants values are not constant expressions; no switch statement. + if (proto == OsConstants.IPPROTO_UDP) { + return "UDP"; + } else if (proto == OsConstants.IPPROTO_TCP) { + return "TCP"; + } + return null; + } + + private static int connectionTimeoutUpdateSecondsFor(int proto) { + // TODO: Replace this with more thoughtful work, perhaps reading from + // and maybe writing to any required + // + // /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_* + // /proc/sys/net/netfilter/nf_conntrack_udp_timeout{,_stream} + // + // entries. TBD. + if (proto == OsConstants.IPPROTO_TCP) { + // Cf. /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established + return 432000; + } else { + // Cf. /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream + return 180; + } } } diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java index 865a98902d0b..553fd8c453a0 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java @@ -21,10 +21,12 @@ import static com.android.internal.util.BitUtils.uint16; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; +import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; import android.os.Handler; import android.os.RemoteException; import android.net.util.SharedLog; +import android.system.OsConstants; import java.util.ArrayList; @@ -327,13 +329,24 @@ public class OffloadHardwareInterface { public void updateTimeout(NatTimeoutUpdate params) { handler.post(() -> { controlCb.onNatTimeoutUpdate( - params.proto, + networkProtocolToOsConstant(params.proto), params.src.addr, uint16(params.src.port), params.dst.addr, uint16(params.dst.port)); }); } } + private static int networkProtocolToOsConstant(int proto) { + switch (proto) { + case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP; + case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP; + default: + // The caller checks this value and will log an error. Just make + // sure it won't collide with valid OsContants.IPPROTO_* values. + return -Math.abs(proto); + } + } + private static class CbResults { boolean success; String errMsg; diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index d9ca00c1cb77..ea260a08c2e6 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -4184,7 +4184,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } public static String getString(int uid, long procStateSeq) { - return "UID=" + uid + " procStateSeq=" + procStateSeq; + return "UID=" + uid + " Seq=" + procStateSeq; } private int increaseNext(int next, int increment) { diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java index e833f6a03bce..714b35a03396 100644 --- a/services/net/java/android/net/ip/IpReachabilityMonitor.java +++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java @@ -205,44 +205,14 @@ public class IpReachabilityMonitor { final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage( 1, ip, StructNdMsg.NUD_PROBE, ifIndex, null); - int errno = -OsConstants.EPROTO; - try (NetlinkSocket nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE)) { - final long IO_TIMEOUT = 300L; - nlSocket.connectToKernel(); - nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT); - final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT); - // recvMessage() guaranteed to not return null if it did not throw. - final NetlinkMessage response = NetlinkMessage.parse(bytes); - if (response != null && response instanceof NetlinkErrorMessage && - (((NetlinkErrorMessage) response).getNlMsgError() != null)) { - errno = ((NetlinkErrorMessage) response).getNlMsgError().error; - if (errno != 0) { - // TODO: consider ignoring EINVAL (-22), which appears to be - // normal when probing a neighbor for which the kernel does - // not already have / no longer has a link layer address. - Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + response.toString()); - } - } else { - String errmsg; - if (response == null) { - bytes.position(0); - errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes); - } else { - errmsg = response.toString(); - } - Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + errmsg); - } + try { + NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_ROUTE, msg); } catch (ErrnoException e) { - Log.e(TAG, "Error " + msgSnippet, e); - errno = -e.errno; - } catch (InterruptedIOException e) { - Log.e(TAG, "Error " + msgSnippet, e); - errno = -OsConstants.ETIMEDOUT; - } catch (SocketException e) { - Log.e(TAG, "Error " + msgSnippet, e); - errno = -OsConstants.EIO; + Log.e(TAG, "Error " + msgSnippet + ": " + e); + return -e.errno; } - return errno; + + return 0; } public IpReachabilityMonitor(Context context, String ifName, SharedLog log, Callback callback) { diff --git a/services/net/java/android/net/netlink/ConntrackMessage.java b/services/net/java/android/net/netlink/ConntrackMessage.java new file mode 100644 index 000000000000..605c46b3b4e0 --- /dev/null +++ b/services/net/java/android/net/netlink/ConntrackMessage.java @@ -0,0 +1,117 @@ +/* + * 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.netlink; + +import static android.net.netlink.NetlinkConstants.alignedLengthOf; +import static android.net.netlink.StructNlAttr.makeNestedType; +import static android.net.netlink.StructNlAttr.NLA_HEADERLEN; +import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK; +import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; +import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE; +import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; +import static android.net.util.NetworkConstants.IPV4_ADDR_LEN; +import static java.nio.ByteOrder.BIG_ENDIAN; + +import android.system.OsConstants; +import android.util.Log; +import libcore.io.SizeOf; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + + +/** + * A NetlinkMessage subclass for netlink conntrack messages. + * + * see also: <linux_src>/include/uapi/linux/netfilter/nfnetlink_conntrack.h + * + * @hide + */ +public class ConntrackMessage extends NetlinkMessage { + public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE; + + public static final short NFNL_SUBSYS_CTNETLINK = 1; + public static final short IPCTNL_MSG_CT_NEW = 0; + + // enum ctattr_type + public static final short CTA_TUPLE_ORIG = 1; + public static final short CTA_TUPLE_REPLY = 2; + public static final short CTA_TIMEOUT = 7; + + // enum ctattr_tuple + public static final short CTA_TUPLE_IP = 1; + public static final short CTA_TUPLE_PROTO = 2; + + // enum ctattr_ip + public static final short CTA_IP_V4_SRC = 1; + public static final short CTA_IP_V4_DST = 2; + + // enum ctattr_l4proto + public static final short CTA_PROTO_NUM = 1; + public static final short CTA_PROTO_SRC_PORT = 2; + public static final short CTA_PROTO_DST_PORT = 3; + + public static byte[] newIPv4TimeoutUpdateRequest( + int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) { + // *** STYLE WARNING *** + // + // Code below this point uses extra block indentation to highlight the + // packing of nested tuple netlink attribute types. + final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG, + new StructNlAttr(CTA_TUPLE_IP, + new StructNlAttr(CTA_IP_V4_SRC, src), + new StructNlAttr(CTA_IP_V4_DST, dst)), + new StructNlAttr(CTA_TUPLE_PROTO, + new StructNlAttr(CTA_PROTO_NUM, (byte) proto), + new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN), + new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN))); + + final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN); + + final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength(); + final byte[] bytes = new byte[STRUCT_SIZE + payloadLength]; + final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.order(ByteOrder.nativeOrder()); + + final ConntrackMessage ctmsg = new ConntrackMessage(); + ctmsg.mHeader.nlmsg_len = bytes.length; + ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW; + ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE; + ctmsg.mHeader.nlmsg_seq = 1; + ctmsg.pack(byteBuffer); + + ctaTupleOrig.pack(byteBuffer); + ctaTimeout.pack(byteBuffer); + + return bytes; + } + + protected StructNfGenMsg mNfGenMsg; + + private ConntrackMessage() { + super(new StructNlMsgHdr()); + mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET); + } + + public void pack(ByteBuffer byteBuffer) { + mHeader.pack(byteBuffer); + mNfGenMsg.pack(byteBuffer); + } +} diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java index 657d48c15250..a9e0cd996fbd 100644 --- a/services/net/java/android/net/netlink/NetlinkSocket.java +++ b/services/net/java/android/net/netlink/NetlinkSocket.java @@ -51,6 +51,47 @@ public class NetlinkSocket implements Closeable { private long mLastRecvTimeoutMs; private long mLastSendTimeoutMs; + public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException { + final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage"; + + try (NetlinkSocket nlSocket = new NetlinkSocket(nlProto)) { + final long IO_TIMEOUT = 300L; + nlSocket.connectToKernel(); + nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT); + final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT); + // recvMessage() guaranteed to not return null if it did not throw. + final NetlinkMessage response = NetlinkMessage.parse(bytes); + if (response != null && response instanceof NetlinkErrorMessage && + (((NetlinkErrorMessage) response).getNlMsgError() != null)) { + final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error; + if (errno != 0) { + // TODO: consider ignoring EINVAL (-22), which appears to be + // normal when probing a neighbor for which the kernel does + // not already have / no longer has a link layer address. + Log.e(TAG, errPrefix + ", errmsg=" + response.toString()); + // Note: convert kernel errnos (negative) into userspace errnos (positive). + throw new ErrnoException(response.toString(), Math.abs(errno)); + } + } else { + final String errmsg; + if (response == null) { + bytes.position(0); + errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes); + } else { + errmsg = response.toString(); + } + Log.e(TAG, errPrefix + ", errmsg=" + errmsg); + throw new ErrnoException(errmsg, OsConstants.EPROTO); + } + } catch (InterruptedIOException e) { + Log.e(TAG, errPrefix, e); + throw new ErrnoException(errPrefix, OsConstants.ETIMEDOUT, e); + } catch (SocketException e) { + Log.e(TAG, errPrefix, e); + throw new ErrnoException(errPrefix, OsConstants.EIO, e); + } + } + public NetlinkSocket(int nlProto) throws ErrnoException { mDescriptor = Os.socket( OsConstants.AF_NETLINK, OsConstants.SOCK_DGRAM, nlProto); diff --git a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java index 02df1313c43f..e784fbb5e0dc 100644 --- a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java +++ b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java @@ -36,7 +36,7 @@ import java.nio.ByteOrder; /** - * A NetlinkMessage subclass for netlink error messages. + * A NetlinkMessage subclass for rtnetlink neighbor messages. * * see also: <linux_src>/include/uapi/linux/neighbour.h * diff --git a/services/net/java/android/net/netlink/StructNfGenMsg.java b/services/net/java/android/net/netlink/StructNfGenMsg.java new file mode 100644 index 000000000000..99695e23b248 --- /dev/null +++ b/services/net/java/android/net/netlink/StructNfGenMsg.java @@ -0,0 +1,51 @@ +/* + * 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.netlink; + +import libcore.io.SizeOf; + +import java.nio.ByteBuffer; + + +/** + * struct nfgenmsg + * + * see <linux_src>/include/uapi/linux/netfilter/nfnetlink.h + * + * @hide + */ +public class StructNfGenMsg { + public static final int STRUCT_SIZE = 2 + SizeOf.SHORT; + + public static final int NFNETLINK_V0 = 0; + + final public byte nfgen_family; + final public byte version; + final public short res_id; // N.B.: this is big endian in the kernel + + public StructNfGenMsg(byte family) { + nfgen_family = family; + version = (byte) NFNETLINK_V0; + res_id = (short) 0; + } + + public void pack(ByteBuffer byteBuffer) { + byteBuffer.put(nfgen_family); + byteBuffer.put(version); + byteBuffer.putShort(res_id); + } +} diff --git a/services/net/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java index 597a6aa1c9eb..811bdbbe821a 100644 --- a/services/net/java/android/net/netlink/StructNlAttr.java +++ b/services/net/java/android/net/netlink/StructNlAttr.java @@ -34,7 +34,12 @@ import java.nio.ByteBuffer; */ public class StructNlAttr { // Already aligned. - public static final int NLA_HEADERLEN = 4; + public static final int NLA_HEADERLEN = 4; + public static final int NLA_F_NESTED = (1 << 15); + + public static short makeNestedType(short type) { + return (short) (type | NLA_F_NESTED); + } // Return a (length, type) object only, without consuming any bytes in // |byteBuffer| and without copying or interpreting any value bytes. @@ -46,10 +51,17 @@ public class StructNlAttr { } final int baseOffset = byteBuffer.position(); - final StructNlAttr struct = new StructNlAttr(); - struct.nla_len = byteBuffer.getShort(); - struct.nla_type = byteBuffer.getShort(); - struct.mByteOrder = byteBuffer.order(); + // Assume the byte order of the buffer is the expected byte order of the value. + final StructNlAttr struct = new StructNlAttr(byteBuffer.order()); + // The byte order of nla_len and nla_type is always native. + final ByteOrder originalOrder = byteBuffer.order(); + byteBuffer.order(ByteOrder.nativeOrder()); + try { + struct.nla_len = byteBuffer.getShort(); + struct.nla_type = byteBuffer.getShort(); + } finally { + byteBuffer.order(originalOrder); + } byteBuffer.position(baseOffset); if (struct.nla_len < NLA_HEADERLEN) { @@ -78,13 +90,65 @@ public class StructNlAttr { return struct; } - public short nla_len; + public short nla_len = (short) NLA_HEADERLEN; public short nla_type; public byte[] nla_value; - public ByteOrder mByteOrder; - public StructNlAttr() { - mByteOrder = ByteOrder.nativeOrder(); + // The byte order used to read/write the value member. Netlink length and + // type members are always read/written in native order. + private ByteOrder mByteOrder = ByteOrder.nativeOrder(); + + public StructNlAttr() {} + + public StructNlAttr(ByteOrder byteOrder) { + mByteOrder = byteOrder; + } + + public StructNlAttr(short type, byte value) { + nla_type = type; + setValue(new byte[1]); + nla_value[0] = value; + } + + public StructNlAttr(short type, short value) { + this(type, value, ByteOrder.nativeOrder()); + } + + public StructNlAttr(short type, short value, ByteOrder order) { + this(order); + nla_type = type; + setValue(new byte[SizeOf.SHORT]); + getValueAsByteBuffer().putShort(value); + } + + public StructNlAttr(short type, int value) { + this(type, value, ByteOrder.nativeOrder()); + } + + public StructNlAttr(short type, int value, ByteOrder order) { + this(order); + nla_type = type; + setValue(new byte[SizeOf.INT]); + getValueAsByteBuffer().putInt(value); + } + + public StructNlAttr(short type, InetAddress ip) { + nla_type = type; + setValue(ip.getAddress()); + } + + public StructNlAttr(short type, StructNlAttr... nested) { + this(); + nla_type = makeNestedType(type); + + int payloadLength = 0; + for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength(); + setValue(new byte[payloadLength]); + + final ByteBuffer buf = getValueAsByteBuffer(); + for (StructNlAttr nla : nested) { + nla.pack(buf); + } } public int getAlignedLength() { @@ -117,13 +181,25 @@ public class StructNlAttr { } public void pack(ByteBuffer byteBuffer) { + final ByteOrder originalOrder = byteBuffer.order(); final int originalPosition = byteBuffer.position(); - byteBuffer.putShort(nla_len); - byteBuffer.putShort(nla_type); - byteBuffer.put(nla_value); + + byteBuffer.order(ByteOrder.nativeOrder()); + try { + byteBuffer.putShort(nla_len); + byteBuffer.putShort(nla_type); + if (nla_value != null) byteBuffer.put(nla_value); + } finally { + byteBuffer.order(originalOrder); + } byteBuffer.position(originalPosition + getAlignedLength()); } + private void setValue(byte[] value) { + nla_value = value; + nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0)); + } + @Override public String toString() { return "StructNlAttr{ " diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 2b528101d5d3..5b2892b7a868 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1697,7 +1697,6 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY, new String[]{ "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" + - "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED," + "com.android.internal.telephony.CARRIER_SIGNAL_RESET" }); sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null); diff --git a/test-runner/Android.mk b/test-runner/Android.mk index 0752661b3a68..a642fdfb58a0 100644 --- a/test-runner/Android.mk +++ b/test-runner/Android.mk @@ -70,11 +70,10 @@ LOCAL_MODULE := android.test.mock.sdk LOCAL_SOURCE_FILES_ALL_GENERATED := true -include $(BUILD_STATIC_JAVA_LIBRARY) - # Make sure to run droiddoc first to generate the stub source files. -$(full_classes_compiled_jar) : $(android_test_mock_gen_stamp) -$(full_classes_jack) : $(android_test_mock_gen_stamp) +LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_mock_gen_stamp) + +include $(BUILD_STATIC_JAVA_LIBRARY) # Archive a copy of the classes.jar in SDK build. $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.jar) diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java new file mode 100644 index 000000000000..3aab9426bc3f --- /dev/null +++ b/tests/net/java/android/net/netlink/ConntrackMessageTest.java @@ -0,0 +1,131 @@ +/* + * 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.netlink; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assume.assumeTrue; + +import android.system.OsConstants; +import libcore.util.HexEncoding; + +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import org.junit.runner.RunWith; +import org.junit.Test; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ConntrackMessageTest { + private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN); + + // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443) + public static final String CT_V4UPDATE_TCP_HEX = + // struct nlmsghdr + "50000000" + // length = 80 + "0001" + // type = (1 << 8) | 0 + "0501" + // flags + "01000000" + // seqno = 1 + "00000000" + // pid = 0 + // struct nfgenmsg + "02" + // nfgen_family = AF_INET + "00" + // version = NFNETLINK_V0 + "0000" + // res_id + // struct nlattr + "3400" + // nla_len = 52 + "0180" + // nla_type = nested CTA_TUPLE_ORIG + // struct nlattr + "1400" + // nla_len = 20 + "0180" + // nla_type = nested CTA_TUPLE_IP + "0800 0100 C0A82BD1" + // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209 + "0800 0200 17D30D1A" + // nla_type=CTA_IP_V4_DST, ip=23.211.13.26 + // struct nlattr + "1C00" + // nla_len = 28 + "0280" + // nla_type = nested CTA_TUPLE_PROTO + "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=6 + "0600 0200 AD2D 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian) + "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian) + // struct nlattr + "0800" + // nla_len = 8 + "0700" + // nla_type = CTA_TIMEOUT + "00069780"; // nla_value = 432000 (big endian) + public static final byte[] CT_V4UPDATE_TCP_BYTES = + HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false); + + // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443) + public static final String CT_V4UPDATE_UDP_HEX = + // struct nlmsghdr + "50000000" + // length = 80 + "0001" + // type = (1 << 8) | 0 + "0501" + // flags + "01000000" + // seqno = 1 + "00000000" + // pid = 0 + // struct nfgenmsg + "02" + // nfgen_family = AF_INET + "00" + // version = NFNETLINK_V0 + "0000" + // res_id + // struct nlattr + "3400" + // nla_len = 52 + "0180" + // nla_type = nested CTA_TUPLE_ORIG + // struct nlattr + "1400" + // nla_len = 20 + "0180" + // nla_type = nested CTA_TUPLE_IP + "0800 0100 6460A792" + // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146 + "0800 0200 D83AC50A" + // nla_type=CTA_IP_V4_DST, ip=216.58.197.10 + // struct nlattr + "1C00" + // nla_len = 28 + "0280" + // nla_type = nested CTA_TUPLE_PROTO + "0500 0100 11 000000" + // nla_type=CTA_PROTO_NUM, proto=17 + "0600 0200 90CD 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian) + "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian) + // struct nlattr + "0800" + // nla_len = 8 + "0700" + // nla_type = CTA_TIMEOUT + "000000B4"; // nla_value = 180 (big endian) + public static final byte[] CT_V4UPDATE_UDP_BYTES = + HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false); + + @Test + public void testConntrackIPv4TcpTimeoutUpdate() throws Exception { + assumeTrue(USING_LE); + + final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest( + OsConstants.IPPROTO_TCP, + (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333, + (Inet4Address) InetAddress.getByName("23.211.13.26"), 443, + 432000); + assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp); + } + + @Test + public void testConntrackIPv4UdpTimeoutUpdate() throws Exception { + assumeTrue(USING_LE); + + final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest( + OsConstants.IPPROTO_UDP, + (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069, + (Inet4Address) InetAddress.getByName("216.58.197.10"), 443, + 180); + assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp); + } +} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index f6481cf59140..8816d43ef8de 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -64,6 +64,7 @@ import android.net.NetworkInfo.DetailedState; import android.net.NetworkMisc; import android.net.NetworkRequest; import android.net.NetworkSpecifier; +import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.StringNetworkSpecifier; import android.net.metrics.IpConnectivityLog; @@ -88,6 +89,7 @@ import android.test.AndroidTestCase; import android.test.mock.MockContentResolver; import android.test.suitebuilder.annotation.SmallTest; import android.text.TextUtils; +import android.util.ArraySet; import android.util.Log; import android.util.LogPrinter; @@ -109,7 +111,10 @@ import org.mockito.Spy; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -304,6 +309,10 @@ public class ConnectivityServiceTest extends AndroidTestCase { private String mRedirectUrl; MockNetworkAgent(int transport) { + this(transport, new LinkProperties()); + } + + MockNetworkAgent(int transport, LinkProperties linkProperties) { final int type = transportToLegacyType(transport); final String typeName = ConnectivityManager.getNetworkTypeName(type); mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); @@ -329,7 +338,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { mHandlerThread.start(); mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext, "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities, - new LinkProperties(), mScore, new NetworkMisc()) { + linkProperties, mScore, new NetworkMisc()) { @Override public void unwanted() { mDisconnected.open(); } @@ -3338,6 +3347,68 @@ public class ConnectivityServiceTest extends AndroidTestCase { assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported); } + @SmallTest + public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() { + final NetworkRequest networkRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_WIFI).build(); + final TestNetworkCallback networkCallback = new TestNetworkCallback(); + mCm.registerNetworkCallback(networkRequest, networkCallback); + + LinkProperties lp = new LinkProperties(); + lp.setInterfaceName("wlan0"); + LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24"); + RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null, + NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName()); + lp.addLinkAddress(myIpv4Address); + lp.addRoute(myIpv4DefaultRoute); + + // Verify direct routes are added when network agent is first registered in + // ConnectivityService. + MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp); + networkAgent.connect(true); + networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent); + networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent); + CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, + networkAgent); + networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent); + networkCallback.assertNoCallback(); + checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address), + Arrays.asList(myIpv4DefaultRoute)); + checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()), + Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute)); + + // Verify direct routes are added during subsequent link properties updates. + LinkProperties newLp = new LinkProperties(lp); + LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64"); + LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64"); + newLp.addLinkAddress(myIpv6Address1); + newLp.addLinkAddress(myIpv6Address2); + networkAgent.sendLinkProperties(newLp); + cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent); + networkCallback.assertNoCallback(); + checkDirectlyConnectedRoutes(cbi.arg, + Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2), + Arrays.asList(myIpv4DefaultRoute)); + mCm.unregisterNetworkCallback(networkCallback); + } + + private void checkDirectlyConnectedRoutes(Object callbackObj, + Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) { + assertTrue(callbackObj instanceof LinkProperties); + LinkProperties lp = (LinkProperties) callbackObj; + + Set<RouteInfo> expectedRoutes = new ArraySet<>(); + expectedRoutes.addAll(otherRoutes); + for (LinkAddress address : linkAddresses) { + RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName()); + // Duplicates in linkAddresses are considered failures + assertTrue(expectedRoutes.add(localRoute)); + } + List<RouteInfo> observedRoutes = lp.getRoutes(); + assertEquals(expectedRoutes.size(), observedRoutes.size()); + assertTrue(observedRoutes.containsAll(expectedRoutes)); + } + private static <T> void assertEmpty(T[] ts) { int length = ts.length; assertEquals("expected empty array, but length was " + length, 0, length); diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java index d11565abb917..eff04ab5addd 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java @@ -201,9 +201,14 @@ public class IpConnectivityEventBuilderTest extends TestCase { " time_ms: 1", " transports: 0", " default_network_event <", + " default_network_duration_ms: 0", + " final_score: 0", + " initial_score: 0", + " ip_support: 0", " network_id <", " network_id: 102", " >", + " no_default_network_duration_ms: 0", " previous_network_id <", " network_id: 101", " >", @@ -442,6 +447,8 @@ public class IpConnectivityEventBuilderTest extends TestCase { " program_updates_all: 7", " program_updates_allowing_multicast: 3", " received_ras: 10", + " total_packet_dropped: 0", + " total_packet_processed: 0", " zero_lifetime_ras: 1", " >", ">", diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java index e01469b1825e..cc18b7f32208 100644 --- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java +++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java @@ -256,9 +256,14 @@ public class IpConnectivityMetricsTest { " time_ms: 300", " transports: 0", " default_network_event <", + " default_network_duration_ms: 0", + " final_score: 0", + " initial_score: 0", + " ip_support: 0", " network_id <", " network_id: 102", " >", + " no_default_network_duration_ms: 0", " previous_network_id <", " network_id: 101", " >", @@ -308,6 +313,8 @@ public class IpConnectivityMetricsTest { " program_updates_all: 7", " program_updates_allowing_multicast: 3", " received_ras: 10", + " total_packet_dropped: 0", + " total_packet_processed: 0", " zero_lifetime_ras: 1", " >", ">", @@ -367,6 +374,10 @@ public class IpConnectivityMetricsTest { " event_types: 1", " event_types: 1", " event_types: 2", + " getaddrinfo_error_count: 0", + " getaddrinfo_query_count: 0", + " gethostbyname_error_count: 0", + " gethostbyname_query_count: 0", " latencies_ms: 3456", " latencies_ms: 45", " latencies_ms: 638", @@ -384,6 +395,10 @@ public class IpConnectivityMetricsTest { " dns_lookup_batch <", " event_types: 1", " event_types: 2", + " getaddrinfo_error_count: 0", + " getaddrinfo_query_count: 0", + " gethostbyname_error_count: 0", + " gethostbyname_query_count: 0", " latencies_ms: 56", " latencies_ms: 34", " return_codes: 0", diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java index f98ab3d06921..46f395eae214 100644 --- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java +++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java @@ -111,6 +111,10 @@ public class NetdEventListenerServiceTest { " event_types: 1", " event_types: 2", " event_types: 2", + " getaddrinfo_error_count: 0", + " getaddrinfo_query_count: 0", + " gethostbyname_error_count: 0", + " gethostbyname_query_count: 0", " latencies_ms: 3456", " latencies_ms: 267", " latencies_ms: 1230", @@ -142,6 +146,10 @@ public class NetdEventListenerServiceTest { " event_types: 2", " event_types: 1", " event_types: 1", + " getaddrinfo_error_count: 0", + " getaddrinfo_query_count: 0", + " gethostbyname_error_count: 0", + " gethostbyname_query_count: 0", " latencies_ms: 56", " latencies_ms: 78", " latencies_ms: 14", |