From ce1452204226a20651ca4fa7a8bcdb5bdbaa8d71 Mon Sep 17 00:00:00 2001 From: Matthew Xie Date: Thu, 18 Jul 2013 17:31:50 -0700 Subject: Bluetooth MAP profile - sms and mms support initial check-in bug:10116530 Change-Id: I57d022005bcff5bc3e56438a81ac92566f957744 --- framework/java/android/bluetooth/BluetoothMap.java | 300 +++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 framework/java/android/bluetooth/BluetoothMap.java (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java new file mode 100644 index 0000000000..7de309fb83 --- /dev/null +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.RemoteException; +import android.os.IBinder; +import android.os.ServiceManager; +import android.util.Log; + +/** + * This class provides the APIs to control the Bluetooth MAP + * Profile. + *@hide + */ +public class BluetoothMap { + + private static final String TAG = "BluetoothMap"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + /** int extra for MAP_STATE_CHANGED_ACTION */ + public static final String MAP_STATE = + "android.bluetooth.map.intent.MAP_STATE"; + /** int extra for MAP_STATE_CHANGED_ACTION */ + public static final String MAP_PREVIOUS_STATE = + "android.bluetooth.map.intent.MAP_PREVIOUS_STATE"; + + /** Indicates the state of a Map connection state has changed. + * This intent will always contain MAP_STATE, MAP_PREVIOUS_STATE and + * BluetoothIntent.ADDRESS extras. + */ + public static final String MAP_STATE_CHANGED_ACTION = + "android.bluetooth.map.intent.action.MAP_STATE_CHANGED"; + + private IBluetoothMap mService; + private final Context mContext; + private ServiceListener mServiceListener; + private BluetoothAdapter mAdapter; + + /** There was an error trying to obtain the state */ + public static final int STATE_ERROR = -1; + /** No client currently connected */ + public static final int STATE_DISCONNECTED = 0; + /** Connection attempt in progress */ + public static final int STATE_CONNECTING = 1; + /** Client is currently connected */ + public static final int STATE_CONNECTED = 2; + + public static final int RESULT_FAILURE = 0; + public static final int RESULT_SUCCESS = 1; + /** Connection canceled before completion. */ + public static final int RESULT_CANCELED = 2; + + /** + * An interface for notifying Bluetooth PCE IPC clients when they have + * been connected to the BluetoothMap service. + */ + public interface ServiceListener { + /** + * Called to notify the client when this proxy object has been + * connected to the BluetoothMap service. Clients must wait for + * this callback before making IPC calls on the BluetoothMap + * service. + */ + public void onServiceConnected(BluetoothMap proxy); + + /** + * Called to notify the client that this proxy object has been + * disconnected from the BluetoothMap service. Clients must not + * make IPC calls on the BluetoothMap service after this callback. + * This callback will currently only occur if the application hosting + * the BluetoothMap service, but may be called more often in future. + */ + public void onServiceDisconnected(); + } + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) Log.d(TAG,"Binding service..."); + if (!mContext.bindService( + new Intent(IBluetoothMap.class.getName()), + mConnection, 0)) { + Log.e(TAG, "Could not bind to Bluetooth MAP Service"); + } + } + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + }; + + /** + * Create a BluetoothMap proxy object. + */ + public BluetoothMap(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + if (!context.bindService(new Intent(IBluetoothMap.class.getName()), mConnection, 0)) { + Log.e(TAG, "Could not bind to Bluetooth Map Service"); + } + } + + protected void finalize() throws Throwable { + try { + close(); + } finally { + super.finalize(); + } + } + + /** + * Close the connection to the backing service. + * Other public functions of BluetoothMap will return default error + * results once close() has been called. Multiple invocations of close() + * are ok. + */ + public synchronized void close() { + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + synchronized (mConnection) { + if (mService != null) { + try { + mService = null; + mContext.unbindService(mConnection); + mConnection = null; + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + mServiceListener = null; + } + + /** + * Get the current state of the BluetoothMap service. + * @return One of the STATE_ return codes, or STATE_ERROR if this proxy + * object is currently not connected to the Map service. + */ + public int getState() { + if (VDBG) log("getState()"); + if (mService != null) { + try { + return mService.getState(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } + return BluetoothMap.STATE_ERROR; + } + + /** + * Get the currently connected remote Bluetooth device (PCE). + * @return The remote Bluetooth device, or null if not in connected or + * connecting state, or if this proxy object is not connected to + * the Map service. + */ + public BluetoothDevice getClient() { + if (VDBG) log("getClient()"); + if (mService != null) { + try { + return mService.getClient(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } + return null; + } + + /** + * Returns true if the specified Bluetooth device is connected (does not + * include connecting). Returns false if not connected, or if this proxy + * object is not currently connected to the Map service. + */ + public boolean isConnected(BluetoothDevice device) { + if (VDBG) log("isConnected(" + device + ")"); + if (mService != null) { + try { + return mService.isConnected(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Disconnects the current Map Client. Currently this call blocks, + * it may soon be made asynchronous. Returns false if this proxy object is + * not currently connected to the Map service. + */ + public boolean disconnect() { + if (DBG) log("disconnect()"); + if (mService != null) { + try { + mService.disconnect(); + return true; + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Check class bits for possible Map support. + * This is a simple heuristic that tries to guess if a device with the + * given class bits might support Map. It is not accurate for all + * devices. It tries to err on the side of false positives. + * @return True if this device might support Map. + */ + public static boolean doesClassMatchSink(BluetoothClass btClass) { + // TODO optimize the rule + switch (btClass.getDeviceClass()) { + case BluetoothClass.Device.COMPUTER_DESKTOP: + case BluetoothClass.Device.COMPUTER_LAPTOP: + case BluetoothClass.Device.COMPUTER_SERVER: + case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: + return true; + default: + return false; + } + } + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) log("Proxy object connected"); + mService = IBluetoothMap.Stub.asInterface(service); + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothMap.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) log("Proxy object disconnected"); + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(); + } + } + }; + + private static void log(String msg) { + Log.d(TAG, msg); + } +} -- cgit v1.2.3 From 6816ee2b6d6820a727b59d78b6892473efd42f98 Mon Sep 17 00:00:00 2001 From: Kim Schulz Date: Thu, 22 Aug 2013 11:18:02 +0200 Subject: Fixed review comments - fixed review comments (internal+google) - corrected tabs/spaces - Add connection id header for obex client operations - added support for implementing ProfileService class Change-Id: Idab8b4fa54a0f31bec4ffa263a69a9850a07f858 Bug:10692365 --- framework/java/android/bluetooth/BluetoothMap.java | 244 +++++++++++++++------ 1 file changed, 176 insertions(+), 68 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 7de309fb83..fac8fd5184 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -16,6 +16,8 @@ package android.bluetooth; +import java.util.List; +import java.util.ArrayList; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -30,25 +32,14 @@ import android.util.Log; * Profile. *@hide */ -public class BluetoothMap { +public final class BluetoothMap implements BluetoothProfile { private static final String TAG = "BluetoothMap"; private static final boolean DBG = true; private static final boolean VDBG = false; - /** int extra for MAP_STATE_CHANGED_ACTION */ - public static final String MAP_STATE = - "android.bluetooth.map.intent.MAP_STATE"; - /** int extra for MAP_STATE_CHANGED_ACTION */ - public static final String MAP_PREVIOUS_STATE = - "android.bluetooth.map.intent.MAP_PREVIOUS_STATE"; - - /** Indicates the state of a Map connection state has changed. - * This intent will always contain MAP_STATE, MAP_PREVIOUS_STATE and - * BluetoothIntent.ADDRESS extras. - */ - public static final String MAP_STATE_CHANGED_ACTION = - "android.bluetooth.map.intent.action.MAP_STATE_CHANGED"; + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; private IBluetoothMap mService; private final Context mContext; @@ -57,41 +48,12 @@ public class BluetoothMap { /** There was an error trying to obtain the state */ public static final int STATE_ERROR = -1; - /** No client currently connected */ - public static final int STATE_DISCONNECTED = 0; - /** Connection attempt in progress */ - public static final int STATE_CONNECTING = 1; - /** Client is currently connected */ - public static final int STATE_CONNECTED = 2; public static final int RESULT_FAILURE = 0; public static final int RESULT_SUCCESS = 1; /** Connection canceled before completion. */ public static final int RESULT_CANCELED = 2; - /** - * An interface for notifying Bluetooth PCE IPC clients when they have - * been connected to the BluetoothMap service. - */ - public interface ServiceListener { - /** - * Called to notify the client when this proxy object has been - * connected to the BluetoothMap service. Clients must wait for - * this callback before making IPC calls on the BluetoothMap - * service. - */ - public void onServiceConnected(BluetoothMap proxy); - - /** - * Called to notify the client that this proxy object has been - * disconnected from the BluetoothMap service. Clients must not - * make IPC calls on the BluetoothMap service after this callback. - * This callback will currently only occur if the application hosting - * the BluetoothMap service, but may be called more often in future. - */ - public void onServiceDisconnected(); - } - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { @@ -111,11 +73,7 @@ public class BluetoothMap { try { if (mService == null) { if (VDBG) Log.d(TAG,"Binding service..."); - if (!mContext.bindService( - new Intent(IBluetoothMap.class.getName()), - mConnection, 0)) { - Log.e(TAG, "Could not bind to Bluetooth MAP Service"); - } + doBind(); } } catch (Exception re) { Log.e(TAG,"",re); @@ -128,7 +86,8 @@ public class BluetoothMap { /** * Create a BluetoothMap proxy object. */ - public BluetoothMap(Context context, ServiceListener l) { + /*package*/ BluetoothMap(Context context, ServiceListener l) { + if (DBG) Log.d(TAG, "Create BluetoothMap proxy object"); mContext = context; mServiceListener = l; mAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -140,9 +99,18 @@ public class BluetoothMap { Log.e(TAG,"",e); } } - if (!context.bindService(new Intent(IBluetoothMap.class.getName()), mConnection, 0)) { - Log.e(TAG, "Could not bind to Bluetooth Map Service"); + doBind(); + } + + boolean doBind() { + Intent intent = new Intent(IBluetoothMap.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); + return false; } + return true; } protected void finalize() throws Throwable { @@ -221,9 +189,9 @@ public class BluetoothMap { } /** - * Returns true if the specified Bluetooth device is connected (does not - * include connecting). Returns false if not connected, or if this proxy - * object is not currently connected to the Map service. + * Returns true if the specified Bluetooth device is connected. + * Returns false if not connected, or if this proxy object is not + * currently connected to the Map service. */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); @@ -239,21 +207,33 @@ public class BluetoothMap { } /** - * Disconnects the current Map Client. Currently this call blocks, - * it may soon be made asynchronous. Returns false if this proxy object is - * not currently connected to the Map service. + * Initiate connection. Initiation of outgoing connections is not + * supported for MAP server. */ - public boolean disconnect() { - if (DBG) log("disconnect()"); - if (mService != null) { + public boolean connect(BluetoothDevice device) { + if (DBG) log("connect(" + device + ")" + "not supported for MAPS"); + return false; + } + + /** + * Initiate disconnect. + * + * @param device Remote Bluetooth Device + * @return false on error, + * true otherwise + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { try { - mService.disconnect(); - return true; - } catch (RemoteException e) {Log.e(TAG, e.toString());} - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); + return mService.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"); return false; } @@ -277,19 +257,132 @@ public class BluetoothMap { } } + /** + * Get the list of connected devices. Currently at most one. + * + * @return list of connected devices + */ + public List getConnectedDevices() { + if (DBG) log("getConnectedDevices()"); + if (mService != null && isEnabled()) { + try { + return mService.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"); + return new ArrayList(); + } + + /** + * Get the list of devices matching specified states. Currently at most one. + * + * @return list of matching devices + */ + public List getDevicesMatchingConnectionStates(int[] states) { + if (DBG) log("getDevicesMatchingStates()"); + if (mService != null && isEnabled()) { + try { + return mService.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"); + return new ArrayList(); + } + + /** + * Get connection state of device + * + * @return device connection state + */ + public int getConnectionState(BluetoothDevice device) { + if (DBG) log("getConnectionState(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.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"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + /** + * Set priority of the profile + * + *

The device should already be paired. + * Priority can be one of {@link #PRIORITY_ON} or + * {@link #PRIORITY_OFF}, + * + * @param device Paired bluetooth device + * @param priority + * @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)) { + if (priority != BluetoothProfile.PRIORITY_OFF && + priority != BluetoothProfile.PRIORITY_ON) { + return false; + } + try { + return mService.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"); + return false; + } + + /** + * Get the priority of the profile. + * + *

The priority can be any of: + * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, + * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} + * + * @param device Bluetooth device + * @return priority of the device + */ + public int getPriority(BluetoothDevice device) { + if (VDBG) log("getPriority(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.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"); + return PRIORITY_OFF; + } + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) log("Proxy object connected"); mService = IBluetoothMap.Stub.asInterface(service); if (mServiceListener != null) { - mServiceListener.onServiceConnected(BluetoothMap.this); + mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this); } } public void onServiceDisconnected(ComponentName className) { if (DBG) log("Proxy object disconnected"); mService = null; if (mServiceListener != null) { - mServiceListener.onServiceDisconnected(); + mServiceListener.onServiceDisconnected(BluetoothProfile.MAP); } } }; @@ -297,4 +390,19 @@ public class BluetoothMap { private static void log(String msg) { Log.d(TAG, msg); } + + private boolean isEnabled() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; + 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; + } + + } -- cgit v1.2.3 From 86418bac9b6f772f8998b78e1dad07cede88097b Mon Sep 17 00:00:00 2001 From: Matthew Xie Date: Thu, 10 Oct 2013 11:21:40 -0700 Subject: Check callback null condition for register/unregsiter state change callback Fix BluetoothPan closing sequence for unregsiter state change callback bug 11160007 Change-Id: I405ec91a938289fe9541de2ebd9abc1fb938f44a --- framework/java/android/bluetooth/BluetoothMap.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index fac8fd5184..92a2f1e425 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -142,7 +142,6 @@ public final class BluetoothMap implements BluetoothProfile { try { mService = null; mContext.unbindService(mConnection); - mConnection = null; } catch (Exception re) { Log.e(TAG,"",re); } @@ -370,7 +369,7 @@ public final class BluetoothMap implements BluetoothProfile { 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 = IBluetoothMap.Stub.asInterface(service); -- cgit v1.2.3 From 9c530c2e37aa238af783db1f1715a60b4b74b02d Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Tue, 19 Nov 2013 16:54:46 -0500 Subject: Remove unused imports from frameworks/base. Change-Id: Ia1f99bd2c1105b0b0f70aa614f1f4a67b2840906 --- framework/java/android/bluetooth/BluetoothMap.java | 1 - 1 file changed, 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 92a2f1e425..5a1b7aa818 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -24,7 +24,6 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.RemoteException; import android.os.IBinder; -import android.os.ServiceManager; import android.util.Log; /** -- cgit v1.2.3 From 4ebffef0752d467f15199f1626d0a55648a17f9b Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 19 Mar 2014 18:06:58 -0700 Subject: Get rid of not specifying a user errors in bluetooth. W/ContextImpl( 1772): Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1559 android.content.ContextWrapper.bindService:513 android.bluetooth.BluetoothInputDevice.doBind:262 android.bluetooth.BluetoothInputDevice.:255 android.bluetooth.BluetoothAdapter.getProfileProxy:1365 W/ContextImpl( 1772): Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1559 android.content.ContextWrapper.bindService:513 android.bluetooth.BluetoothPan.doBind:148 android.bluetooth.BluetoothPan.:140 android.bluetooth.BluetoothAdapter.getProfileProxy:1368 W/ContextImpl( 1772): Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1559 android.content.ContextWrapper.bindService:513 android.bluetooth.BluetoothMap.doBind:108 android.bluetooth.BluetoothMap.:101 android.bluetooth.BluetoothAdapter.getProfileProxy:1374 W/ContextImpl( 1772): Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1559 android.content.ContextWrapper.bindService:513 android.bluetooth.BluetoothPbap.doBind:163 android.bluetooth.BluetoothPbap.:156 com.android.settings.bluetooth.PbapServerProfile.:68 Change-Id: I0a1e24ee71aef7d796fcee5692b9d19462a93637 --- framework/java/android/bluetooth/BluetoothMap.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 5a1b7aa818..7f57acf3dc 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -22,8 +22,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.RemoteException; -import android.os.IBinder; +import android.os.*; import android.util.Log; /** @@ -105,7 +104,8 @@ public final class BluetoothMap implements BluetoothProfile { Intent intent = new Intent(IBluetoothMap.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); - if (comp == null || !mContext.bindService(intent, mConnection, 0)) { + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); return false; } -- cgit v1.2.3 From 73458a81e89e0f1955f326d8d29e710a9b4eb746 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 4 Nov 2016 11:23:46 -0600 Subject: Detect non-oneway calls leaving system_server. To protect system stability, any Binder calls leaving the system_server must carefully be performed using FLAG_ONEWAY (or the 'oneway' verb in AIDL) which prevents the call from blocking indefinitely on the remote process. In this CL, the system_server uses the new Binder.setWarnOnBlocking() method to enable detection by default for all remote Binder interfaces. It can also use Binder.allowBlocking() to allow blocking calls on certain remote interfaces that have been determined to be safe. This CL adds the 'oneway' verb to several interfaces and methods where it should have been added, and marks a handful of system ContentProviders as being safe to call into. Also, we assume that any services obtained from ServiceManager are part of the core OS, and are okay to make blocking calls to. Test: builds, boots, runs with minimal logs triggered Bug: 32715088 Change-Id: Ide476e120cb40436a94b7faf7615c943d691f4c0 --- framework/java/android/bluetooth/BluetoothMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 7f57acf3dc..2e73051ee6 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -371,7 +371,7 @@ public final class BluetoothMap implements BluetoothProfile { private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) log("Proxy object connected"); - mService = IBluetoothMap.Stub.asInterface(service); + mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service)); if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this); } -- cgit v1.2.3 From 910201beb0bde1dcf6b33e4ec5d1eb60042419d8 Mon Sep 17 00:00:00 2001 From: Jack He Date: Tue, 22 Aug 2017 16:06:54 -0700 Subject: Fix checkstyle errors (1/2) * Automatic style corrections through IDE Bug: 63596319 Test: make checkbuild, no manual changes, no functional changes Change-Id: I2397d55abc34c9b7a9b748bec6137778df3421a7 --- framework/java/android/bluetooth/BluetoothMap.java | 101 ++++++++++++--------- 1 file changed, 57 insertions(+), 44 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 2e73051ee6..30c0d3c6d0 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -16,19 +16,23 @@ package android.bluetooth; -import java.util.List; -import java.util.ArrayList; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.*; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; import android.util.Log; +import java.util.ArrayList; +import java.util.List; + /** * This class provides the APIs to control the Bluetooth MAP * Profile. - *@hide + * + * @hide */ public final class BluetoothMap implements BluetoothProfile { @@ -37,7 +41,7 @@ public final class BluetoothMap implements BluetoothProfile { private static final boolean VDBG = false; public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; + "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; private IBluetoothMap mService; private final Context mContext; @@ -45,7 +49,7 @@ public final class BluetoothMap implements BluetoothProfile { private BluetoothAdapter mAdapter; /** There was an error trying to obtain the state */ - public static final int STATE_ERROR = -1; + public static final int STATE_ERROR = -1; public static final int RESULT_FAILURE = 0; public static final int RESULT_SUCCESS = 1; @@ -57,29 +61,29 @@ public final class BluetoothMap implements BluetoothProfile { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { - if (VDBG) Log.d(TAG,"Unbinding service..."); + if (VDBG) Log.d(TAG, "Unbinding service..."); synchronized (mConnection) { try { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } else { synchronized (mConnection) { try { if (mService == null) { - if (VDBG) Log.d(TAG,"Binding service..."); + if (VDBG) Log.d(TAG, "Binding service..."); doBind(); } } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } } - }; + }; /** * Create a BluetoothMap proxy object. @@ -94,7 +98,7 @@ public final class BluetoothMap implements BluetoothProfile { try { mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); } catch (RemoteException e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } doBind(); @@ -132,7 +136,7 @@ public final class BluetoothMap implements BluetoothProfile { try { mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); } catch (Exception e) { - Log.e(TAG,"",e); + Log.e(TAG, "", e); } } @@ -142,7 +146,7 @@ public final class BluetoothMap implements BluetoothProfile { mService = null; mContext.unbindService(mConnection); } catch (Exception re) { - Log.e(TAG,"",re); + Log.e(TAG, "", re); } } } @@ -151,15 +155,18 @@ public final class BluetoothMap implements BluetoothProfile { /** * Get the current state of the BluetoothMap service. - * @return One of the STATE_ return codes, or STATE_ERROR if this proxy - * object is currently not connected to the Map service. + * + * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not + * connected to the Map service. */ public int getState() { if (VDBG) log("getState()"); if (mService != null) { try { return mService.getState(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -169,16 +176,18 @@ public final class BluetoothMap implements BluetoothProfile { /** * Get the currently connected remote Bluetooth device (PCE). - * @return The remote Bluetooth device, or null if not in connected or - * connecting state, or if this proxy object is not connected to - * the Map service. + * + * @return The remote Bluetooth device, or null if not in connected or connecting state, or if + * this proxy object is not connected to the Map service. */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); if (mService != null) { try { return mService.getClient(); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -196,7 +205,9 @@ public final class BluetoothMap implements BluetoothProfile { if (mService != null) { try { return mService.isConnected(device); - } catch (RemoteException e) {Log.e(TAG, e.toString());} + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } } else { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); @@ -217,18 +228,17 @@ public final class BluetoothMap implements BluetoothProfile { * Initiate disconnect. * * @param device Remote Bluetooth Device - * @return false on error, - * true otherwise + * @return false on error, true otherwise */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); if (mService != null && isEnabled() && - isValidDevice(device)) { + isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; } } if (mService == null) Log.w(TAG, "Proxy not attached to service"); @@ -240,18 +250,19 @@ public final class BluetoothMap implements BluetoothProfile { * This is a simple heuristic that tries to guess if a device with the * given class bits might support Map. It is not accurate for all * devices. It tries to err on the side of false positives. + * * @return True if this device might support Map. */ public static boolean doesClassMatchSink(BluetoothClass btClass) { // TODO optimize the rule switch (btClass.getDeviceClass()) { - case BluetoothClass.Device.COMPUTER_DESKTOP: - case BluetoothClass.Device.COMPUTER_LAPTOP: - case BluetoothClass.Device.COMPUTER_SERVER: - case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: - return true; - default: - return false; + case BluetoothClass.Device.COMPUTER_DESKTOP: + case BluetoothClass.Device.COMPUTER_LAPTOP: + case BluetoothClass.Device.COMPUTER_SERVER: + case BluetoothClass.Device.COMPUTER_UNCATEGORIZED: + return true; + default: + return false; } } @@ -301,7 +312,7 @@ public final class BluetoothMap implements BluetoothProfile { public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); if (mService != null && isEnabled() && - isValidDevice(device)) { + isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -317,7 +328,7 @@ public final class BluetoothMap implements BluetoothProfile { * Set priority of the profile * *

The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} or + * Priority can be one of {@link #PRIORITY_ON} or * {@link #PRIORITY_OFF}, * * @param device Paired bluetooth device @@ -327,10 +338,10 @@ 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)) { + isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { - return false; + priority != BluetoothProfile.PRIORITY_ON) { + return false; } try { return mService.setPriority(device, priority); @@ -356,7 +367,7 @@ public final class BluetoothMap implements BluetoothProfile { public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); if (mService != null && isEnabled() && - isValidDevice(device)) { + isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { @@ -376,6 +387,7 @@ public final class BluetoothMap implements BluetoothProfile { mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this); } } + public void onServiceDisconnected(ComponentName className) { if (DBG) log("Proxy object disconnected"); mService = null; @@ -389,17 +401,18 @@ public final class BluetoothMap implements BluetoothProfile { Log.d(TAG, msg); } - private boolean isEnabled() { + private boolean isEnabled() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; log("Bluetooth is Not enabled"); return false; } + private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; + if (device == null) return false; - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; } -- cgit v1.2.3 From 9e045d26d0128826b40520f523307d8d16473779 Mon Sep 17 00:00:00 2001 From: Jack He Date: Tue, 22 Aug 2017 21:21:23 -0700 Subject: Fix checkstyle errors (2/2) * Manual style corrections with IDE assistance * Variable name refactors are done through IDE * Corrected general style errors such as: - "final private var" -> "private final var" - "&&", "+", "||" should not be at the end of line - Non-static private variable should be like "mVar" - Private static variable should be like "sVar" - Code file should always end with newline - Inherited methods should be annotated with @Override and no @hide tags - Public methods should always have a JavaDoc entry - "int[] array" is preferred over "int array[]" - private methods should be accessed without "this." when there is no name collisions. - "boolean ? true : false" -> boolean - "boolean ? false : true" -> !boolean - "boolean == true" OR "boolean != false" -> boolean - "boolean != true" OR "boolean == false" -> !boolean Bug: 63596319 Test: make checkbuild, no functional changes Change-Id: Iabdc2be912a32dd63a53213d175cf1bfef268ccd --- framework/java/android/bluetooth/BluetoothMap.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 30c0d3c6d0..26a9106f49 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -56,7 +56,7 @@ public final class BluetoothMap implements BluetoothProfile { /** Connection canceled before completion. */ public static final int RESULT_CANCELED = 2; - final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { public void onBluetoothStateChange(boolean up) { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); @@ -232,8 +232,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.disconnect(device); } catch (RemoteException e) { @@ -311,8 +310,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getConnectionState(device); } catch (RemoteException e) { @@ -337,10 +335,9 @@ 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)) { - if (priority != BluetoothProfile.PRIORITY_OFF && - priority != BluetoothProfile.PRIORITY_ON) { + if (mService != null && isEnabled() && isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF + && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { @@ -366,8 +363,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && - isValidDevice(device)) { + if (mService != null && isEnabled() && isValidDevice(device)) { try { return mService.getPriority(device); } catch (RemoteException e) { -- cgit v1.2.3 From 1f686f645294d624f8b61e4761fd14787a496c75 Mon Sep 17 00:00:00 2001 From: Jack He Date: Thu, 17 Aug 2017 12:11:18 -0700 Subject: Bluetooth: Thread-safe binder invocation * Binder object may become null between null check and actual invocation if using a instance private variable assignable by service connection callbacks * The solution to this problem without locking is to assign existing binder variable to a local final variable before the null check * Any further invocation to a disconnected binder object will result in RemoteException that is caught by the try-catch block * Read and write to volatile variable is always atomic and hence thread-safe * Removed unnecessary synchronization in BluetoothAdapter constructor * Private mConnection objects should be final * Simplfied several return statements where booleans can be returned directly * Removed unnecessary catches for NPE since there won't be any Bug: 64724692 Test: make, pair and use devices, no functional change Change-Id: Ifc9d6337c0d451a01484b61243230725d5314f8e --- framework/java/android/bluetooth/BluetoothMap.java | 68 ++++++++++++---------- 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 26a9106f49..5b55b23680 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/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 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(); } } - 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(); } @@ -291,15 +296,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public List 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(); } } - 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(); } @@ -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()); } - } -- cgit v1.2.3 From 6edd25f33e4e4bed4fdd9eb815012111e59ad2a7 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 2 Feb 2018 13:25:31 -0700 Subject: Pass in the user defined by Context. The majority of Manager-style classes already use Context.getUserId() when making calls into the OS, so clean up the remaining callers to unify behind this strategy. This gives @SystemApi developers a nice clean interface to interact across user boundaries, instead of manually adding "AsUser" or "ForUser" method variants, which would quickly become unsustainable. Test: builds, boots Bug: 72863821 Exempt-From-Owner-Approval: trivial changes Change-Id: Ib772ec4438e57a2ad4950821b9432f9842998451 --- framework/java/android/bluetooth/BluetoothMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 5b55b23680..0fa1d5d629 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -109,7 +109,7 @@ public final class BluetoothMap implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + mContext.getUser())) { Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); return false; } -- cgit v1.2.3 From 7d543894e0497651fc160728d659543483500f87 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Wed, 1 Aug 2018 15:07:20 +0100 Subject: Add @UnsupportedAppUsage annotations For packages: android.bluetooth.le android.bluetooth This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: Ifcf24c0617acd7facc0e03f30a95c3a6b09b205c Merged-In: I88a1311e27c5f9a5f9d1035db76034f86f650efc --- framework/java/android/bluetooth/BluetoothMap.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 5b55b23680..b82680c1ca 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -233,6 +234,7 @@ public final class BluetoothMap implements BluetoothProfile { * @param device Remote Bluetooth Device * @return false on error, true otherwise */ + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = mService; -- cgit v1.2.3 From 1652b94a121a19863c554551c57406cbef504ce8 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Tue, 26 Mar 2019 21:38:08 +0800 Subject: Fix binder leakage when turning off Bluetooth * In current design, Bluetooth AdapterState stops all BR/EDR profiles' service and triggers onServiceDisconnected callback to all binder clients before BluetoothManagerService invokes onBluetoothStateChange(false), which means unbind service would never be called in framework. * Do unbind service when onServiceDisconnected is invoked. * Move profile binder logic to BluetoothProfileConnector except: - BluetoothHeadset: its binder logic is in BluetoothManagerService - BluetoothPbap: it has an individual ServiceListener Bug: 129037442 Bug: 129437895 Test: Bluetooth ON/OFF stress test. adb shell dumpsys activity services | egrep "com.android.bluetooth" to check whether AppBindRecord for com.android.bluetooth grows Merged-In: Id0d85866d386962b94d2d966f0a864b1da165d13 Change-Id: Id0d85866d386962b94d2d966f0a864b1da165d13 --- framework/java/android/bluetooth/BluetoothMap.java | 128 ++++----------------- 1 file changed, 23 insertions(+), 105 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 98c23c600f..dd2f150ad4 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -17,10 +17,7 @@ package android.bluetooth; import android.annotation.UnsupportedAppUsage; -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; @@ -44,11 +41,6 @@ public final class BluetoothMap implements BluetoothProfile { public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; - private volatile IBluetoothMap mService; - private final Context mContext; - private ServiceListener mServiceListener; - private BluetoothAdapter mAdapter; - /** There was an error trying to obtain the state */ public static final int STATE_ERROR = -1; @@ -57,64 +49,23 @@ public final class BluetoothMap implements BluetoothProfile { /** Connection canceled before completion. */ public static final int RESULT_CANCELED = 2; - private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = - new IBluetoothStateChangeCallback.Stub() { - public void onBluetoothStateChange(boolean up) { - if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); - if (!up) { - if (VDBG) Log.d(TAG, "Unbinding service..."); - synchronized (mConnection) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG, "", re); - } - } - } else { - synchronized (mConnection) { - try { - if (mService == null) { - if (VDBG) Log.d(TAG, "Binding service..."); - doBind(); - } - } catch (Exception re) { - Log.e(TAG, "", re); - } - } - } + private BluetoothAdapter mAdapter; + private final BluetoothProfileConnector mProfileConnector = + new BluetoothProfileConnector(this, BluetoothProfile.MAP, + "BluetoothMap", IBluetoothMap.class.getName()) { + @Override + public IBluetoothMap getServiceInterface(IBinder service) { + return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service)); } - }; + }; /** * Create a BluetoothMap proxy object. */ - /*package*/ BluetoothMap(Context context, ServiceListener l) { + /*package*/ BluetoothMap(Context context, ServiceListener listener) { if (DBG) Log.d(TAG, "Create BluetoothMap proxy object"); - mContext = context; - mServiceListener = l; mAdapter = BluetoothAdapter.getDefaultAdapter(); - IBluetoothManager mgr = mAdapter.getBluetoothManager(); - if (mgr != null) { - try { - mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); - } catch (RemoteException e) { - Log.e(TAG, "", e); - } - } - doBind(); - } - - boolean doBind() { - Intent intent = new Intent(IBluetoothMap.class.getName()); - ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); - intent.setComponent(comp); - if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - mContext.getUser())) { - Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); - return false; - } - return true; + mProfileConnector.connect(context, listener); } protected void finalize() throws Throwable { @@ -132,26 +83,11 @@ public final class BluetoothMap implements BluetoothProfile { * are ok. */ public synchronized void close() { - IBluetoothManager mgr = mAdapter.getBluetoothManager(); - if (mgr != null) { - try { - mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); - } catch (Exception e) { - Log.e(TAG, "", e); - } - } + mProfileConnector.disconnect(); + } - synchronized (mConnection) { - if (mService != null) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG, "", re); - } - } - } - mServiceListener = null; + private IBluetoothMap getService() { + return mProfileConnector.getService(); } /** @@ -162,7 +98,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getState() { if (VDBG) log("getState()"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null) { try { return service.getState(); @@ -184,7 +120,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null) { try { return service.getClient(); @@ -205,7 +141,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null) { try { return service.isConnected(device); @@ -237,7 +173,7 @@ public final class BluetoothMap implements BluetoothProfile { @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { try { return service.disconnect(device); @@ -278,7 +214,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null && isEnabled()) { try { return service.getConnectedDevices(); @@ -298,7 +234,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null && isEnabled()) { try { return service.getDevicesMatchingConnectionStates(states); @@ -318,7 +254,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { try { return service.getConnectionState(device); @@ -344,7 +280,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { @@ -373,7 +309,7 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - final IBluetoothMap service = mService; + final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { try { return service.getPriority(device); @@ -386,24 +322,6 @@ public final class BluetoothMap implements BluetoothProfile { return PRIORITY_OFF; } - private final ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - if (DBG) log("Proxy object connected"); - mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service)); - if (mServiceListener != null) { - mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this); - } - } - - public void onServiceDisconnected(ComponentName className) { - if (DBG) log("Proxy object disconnected"); - mService = null; - if (mServiceListener != null) { - mServiceListener.onServiceDisconnected(BluetoothProfile.MAP); - } - } - }; - private static void log(String msg) { Log.d(TAG, msg); } -- cgit v1.2.3 From e8bac9b871a87aa38e99956c380069c3c377eb79 Mon Sep 17 00:00:00 2001 From: Rahul Sabnis Date: Wed, 27 Nov 2019 18:09:33 -0800 Subject: Rename priority to connection policy in bluetooth apis Bug: 145005327 Test: Manual Change-Id: I43ad57feb7dd70f39005ad7a01bc7dac6fb7b639 --- framework/java/android/bluetooth/BluetoothMap.java | 62 ++++++++++++++++++---- 1 file changed, 52 insertions(+), 10 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index dd2f150ad4..979dfd4e3b 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -16,6 +16,9 @@ package android.bluetooth; +import android.Manifest; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; @@ -271,23 +274,43 @@ public final class BluetoothMap implements BluetoothProfile { * Set priority of the profile * *

The device should already be paired. - * Priority can be one of {@link #PRIORITY_ON} or - * {@link #PRIORITY_OFF}, + * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}, * * @param device Paired bluetooth device * @param priority * @return true if priority is set, false on error + * @hide */ + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); + return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority)); + } + + /** + * Set connection policy of the profile + * + *

The device should already be paired. + * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED}, + * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN} + * + * @param device Paired bluetooth device + * @param connectionPolicy is the connection policy to set to for this profile + * @return true if connectionPolicy is set, false on error + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) { + if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { - if (priority != BluetoothProfile.PRIORITY_OFF - && priority != BluetoothProfile.PRIORITY_ON) { + if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { return false; } try { - return service.setPriority(device, priority); + return service.setConnectionPolicy(device, connectionPolicy); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; @@ -301,25 +324,44 @@ public final class BluetoothMap implements BluetoothProfile { * Get the priority of the profile. * *

The priority can be any of: - * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF}, - * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} + * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED} * * @param device Bluetooth device * @return priority of the device + * @hide */ + @RequiresPermission(Manifest.permission.BLUETOOTH) public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); + return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device)); + } + + /** + * Get the connection policy of the profile. + * + *

The connection policy can be any of: + * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN}, + * {@link #CONNECTION_POLICY_UNKNOWN} + * + * @param device Bluetooth device + * @return connection policy of the device + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH) + public int getConnectionPolicy(BluetoothDevice device) { + if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { try { - return service.getPriority(device); + return service.getConnectionPolicy(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); - return PRIORITY_OFF; + return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; } } if (service == null) Log.w(TAG, "Proxy not attached to service"); - return PRIORITY_OFF; + return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; } private static void log(String msg) { -- cgit v1.2.3 From 1429e81689c92c60f556aab1f387f8d2a10b8eb2 Mon Sep 17 00:00:00 2001 From: Rahul Sabnis Date: Wed, 8 Jan 2020 11:08:42 -0800 Subject: Make the BluetoothMap class @SystemApi Bug: 146462547 Test: Manual Change-Id: I2bd3fbb058019bbb32472eac4fcaa65677cbf950 --- framework/java/android/bluetooth/BluetoothMap.java | 49 +++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 979dfd4e3b..f2ceabcc7d 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -17,7 +17,10 @@ package android.bluetooth; import android.Manifest; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.content.Context; @@ -35,21 +38,35 @@ import java.util.List; * * @hide */ +@SystemApi public final class BluetoothMap implements BluetoothProfile { private static final String TAG = "BluetoothMap"; private static final boolean DBG = true; private static final boolean VDBG = false; + /** @hide */ + @SuppressLint("ActionValue") + @SystemApi public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; - /** There was an error trying to obtain the state */ + /** + * There was an error trying to obtain the state + * + * @hide + */ public static final int STATE_ERROR = -1; + /** @hide */ public static final int RESULT_FAILURE = 0; + /** @hide */ public static final int RESULT_SUCCESS = 1; - /** Connection canceled before completion. */ + /** + * Connection canceled before completion. + * + * @hide + */ public static final int RESULT_CANCELED = 2; private BluetoothAdapter mAdapter; @@ -71,6 +88,7 @@ public final class BluetoothMap implements BluetoothProfile { mProfileConnector.connect(context, listener); } + @SuppressLint("GenericException") protected void finalize() throws Throwable { try { close(); @@ -84,6 +102,8 @@ public final class BluetoothMap implements BluetoothProfile { * Other public functions of BluetoothMap will return default error * results once close() has been called. Multiple invocations of close() * are ok. + * + * @hide */ public synchronized void close() { mProfileConnector.disconnect(); @@ -98,6 +118,8 @@ public final class BluetoothMap implements BluetoothProfile { * * @return One of the STATE_ return codes, or STATE_ERROR if this proxy object is currently not * connected to the Map service. + * + * @hide */ public int getState() { if (VDBG) log("getState()"); @@ -120,6 +142,8 @@ public final class BluetoothMap implements BluetoothProfile { * * @return The remote Bluetooth device, or null if not in connected or connecting state, or if * this proxy object is not connected to the Map service. + * + * @hide */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); @@ -141,6 +165,8 @@ public final class BluetoothMap implements BluetoothProfile { * Returns true if the specified Bluetooth device is connected. * Returns false if not connected, or if this proxy object is not * currently connected to the Map service. + * + * @hide */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); @@ -161,6 +187,8 @@ public final class BluetoothMap implements BluetoothProfile { /** * Initiate connection. Initiation of outgoing connections is not * supported for MAP server. + * + * @hide */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")" + "not supported for MAPS"); @@ -172,6 +200,8 @@ public final class BluetoothMap implements BluetoothProfile { * * @param device Remote Bluetooth Device * @return false on error, true otherwise + * + * @hide */ @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { @@ -196,6 +226,8 @@ public final class BluetoothMap implements BluetoothProfile { * devices. It tries to err on the side of false positives. * * @return True if this device might support Map. + * + * @hide */ public static boolean doesClassMatchSink(BluetoothClass btClass) { // TODO optimize the rule @@ -214,8 +246,11 @@ public final class BluetoothMap implements BluetoothProfile { * Get the list of connected devices. Currently at most one. * * @return list of connected devices + * + * @hide */ - public List getConnectedDevices() { + @SystemApi + public @NonNull List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothMap service = getService(); if (service != null && isEnabled()) { @@ -234,6 +269,8 @@ public final class BluetoothMap implements BluetoothProfile { * Get the list of devices matching specified states. Currently at most one. * * @return list of matching devices + * + * @hide */ public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); @@ -254,6 +291,8 @@ public final class BluetoothMap implements BluetoothProfile { * Get connection state of device * * @return device connection state + * + * @hide */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); @@ -301,7 +340,7 @@ public final class BluetoothMap implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) - public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) { + public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { @@ -349,7 +388,7 @@ public final class BluetoothMap implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH) - public int getConnectionPolicy(BluetoothDevice device) { + public int getConnectionPolicy(@Nullable BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { -- cgit v1.2.3 From 3625be4eb7d52fe10c659b649d945a4cea0d0beb Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Tue, 10 Dec 2019 17:47:52 +0000 Subject: Use new UnsupportedAppUsage annotation. Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library. Bug: 145132366 Test: m && diff unsupportedappusage_index.csv Change-Id: I6ab53570aca580fbee1fcc927871caa09780f58f Merged-In: I6ab53570aca580fbee1fcc927871caa09780f58f --- framework/java/android/bluetooth/BluetoothMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 979dfd4e3b..917e7fa04e 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -19,7 +19,7 @@ package android.bluetooth; import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SystemApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; import android.os.IBinder; -- cgit v1.2.3 From 745310e2c9cdf886b71ffa7ad1b2404f9d0252f7 Mon Sep 17 00:00:00 2001 From: Rahul Sabnis Date: Wed, 22 Jan 2020 14:26:35 -0800 Subject: Use @ConnectionPolicy annotation more consistently in classes with methods setConnectionPolicy and getConnectionPolicy Bug: 147669289 Test: Manual Change-Id: I2b9b0391a02d01623c1cd253f2da12b2baaea599 --- framework/java/android/bluetooth/BluetoothMap.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 4674706742..1c62faa97e 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -340,7 +340,8 @@ public final class BluetoothMap implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) - public boolean setConnectionPolicy(@Nullable BluetoothDevice device, int connectionPolicy) { + public boolean setConnectionPolicy(@Nullable BluetoothDevice device, + @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { @@ -388,7 +389,7 @@ public final class BluetoothMap implements BluetoothProfile { */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH) - public int getConnectionPolicy(@Nullable BluetoothDevice device) { + public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { -- cgit v1.2.3 From d87b6b0457b2b31f682623c28f289404ed349281 Mon Sep 17 00:00:00 2001 From: Rahul Sabnis Date: Tue, 25 Feb 2020 11:33:43 -0800 Subject: Add missing RequiresPermission annotations in BluetoothHidHost and BluetoothMap APIs, disallow null device input for setConnectionPolicy, getConnectionPolicy, and getConnectionState in BluetoothHidHost, and BluetoothMap implements AutoCloseable, its close() method is public, and utilizes a CloseGuard. Bug: 149238030 Test: Manual Merged-In: I8add9e26afcaf1a988c15e3cc7f8c446491f0686 Change-Id: I8add9e26afcaf1a988c15e3cc7f8c446491f0686 --- framework/java/android/bluetooth/BluetoothMap.java | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 1c62faa97e..cc2b6155a7 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -27,6 +27,7 @@ import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.util.CloseGuard; import android.util.Log; import java.util.ArrayList; @@ -39,12 +40,14 @@ import java.util.List; * @hide */ @SystemApi -public final class BluetoothMap implements BluetoothProfile { +public final class BluetoothMap implements BluetoothProfile, AutoCloseable { private static final String TAG = "BluetoothMap"; private static final boolean DBG = true; private static final boolean VDBG = false; + private CloseGuard mCloseGuard; + /** @hide */ @SuppressLint("ActionValue") @SystemApi @@ -86,15 +89,16 @@ public final class BluetoothMap implements BluetoothProfile { if (DBG) Log.d(TAG, "Create BluetoothMap proxy object"); mAdapter = BluetoothAdapter.getDefaultAdapter(); mProfileConnector.connect(context, listener); + mCloseGuard = new CloseGuard(); + mCloseGuard.open("close"); } - @SuppressLint("GenericException") - protected void finalize() throws Throwable { - try { - close(); - } finally { - super.finalize(); + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + protected void finalize() { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); } + close(); } /** @@ -105,7 +109,10 @@ public final class BluetoothMap implements BluetoothProfile { * * @hide */ - public synchronized void close() { + @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + public void close() { + if (VDBG) log("close()"); mProfileConnector.disconnect(); } @@ -250,6 +257,7 @@ public final class BluetoothMap implements BluetoothProfile { * @hide */ @SystemApi + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public @NonNull List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothMap service = getService(); -- cgit v1.2.3 From ce594994e8aa1b4bf9a6917e18c4f2f3b68c1ddc Mon Sep 17 00:00:00 2001 From: Rahul Sabnis Date: Wed, 18 Mar 2020 17:46:33 -0700 Subject: Add BLUETOOTH_PRIVILEGED permission as a requirement for all new Bluetooth SystemApis and for hidden connect/disconnect APIs. Hide some APIs that were previously marked as @UnsupportedAppUsage and re-add annotation as changing the permissions for these SystemApis would break the unsupported app contract that was previously there. Therefore, we're choosing to hide them until we have a good story on how to deal with them next release. Bug: 148689314 Test: Manual Change-Id: I33ee2c7ccd3827db3d23d6447cf82d9ffc36836a --- framework/java/android/bluetooth/BluetoothMap.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index cc2b6155a7..14a71c4467 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -18,7 +18,6 @@ package android.bluetooth; import android.Manifest; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -328,7 +327,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @return true if priority is set, false on error * @hide */ - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority)); @@ -347,8 +346,8 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) - public boolean setConnectionPolicy(@Nullable BluetoothDevice device, + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothMap service = getService(); @@ -378,7 +377,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @return priority of the device * @hide */ - @RequiresPermission(Manifest.permission.BLUETOOTH) + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device)); @@ -396,8 +395,8 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH) - public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) { + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { -- cgit v1.2.3 From bc9a809f18a3b0ec23cbc39802fb4928c2074ea3 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 27 Oct 2020 11:47:29 +0000 Subject: Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. Bug: 170729553 Test: Treehugger Change-Id: I4c8fd0006f950de9955242e93968fb0996ceb372 --- framework/java/android/bluetooth/BluetoothMap.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 14a71c4467..3554995400 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.CloseGuard; @@ -209,7 +210,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = getService(); -- cgit v1.2.3 From bddbb77484a3694357df750c5e7df9527f409c8a Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Wed, 28 Oct 2020 19:38:11 +0000 Subject: Revert "Add maxTargetSdk restriction to unused APIs." This reverts commit bc9a809f18a3b0ec23cbc39802fb4928c2074ea3. Reason for revert: Droidcop-triggered revert due to breakage https://android-build.googleplex.com/builds/quarterdeck?testMethod=testAppZygotePreload&testClass=android.app.cts.ServiceTest&atpConfigName=suite%2Ftest-mapping-presubmit-retry_cloud-tf&testModule=CtsAppTestCases&fkbb=6936597&lkbb=6936969&lkgb=6936551&testResults=true&branch=git_master&target=cf_x86_phone-userdebug>, bug b/171886397 Bug: 171886397 Change-Id: Ibe0f0430a3451477c1ee8ef56a596e91ea1e7672 --- framework/java/android/bluetooth/BluetoothMap.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 3554995400..14a71c4467 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -24,7 +24,6 @@ import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; -import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.CloseGuard; @@ -210,7 +209,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = getService(); -- cgit v1.2.3 From cba870b777fc6d2a03a27758cf1db1c38556efe8 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 27 Oct 2020 11:47:29 +0000 Subject: Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. This is a resubmit of ag/12929664 with some APIs excluded that caused test failures; see bugs 171886397, 171888296, 171864568. APIs excluded: Landroid/bluetooth/le/ScanRecord;->parseFromBytes([B)Landroid/bluetooth/le/ScanRecord; Landroid/os/Process;->myPpid()I Landroid/os/SharedMemory;->getFd()I Landroid/hardware/input/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I Bug: 170729553 Test: Treehugger Change-Id: I8285daa8530260251ecad6f3f38f98e263629ca7 --- framework/java/android/bluetooth/BluetoothMap.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 14a71c4467..3554995400 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -24,6 +24,7 @@ import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.CloseGuard; @@ -209,7 +210,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = getService(); -- cgit v1.2.3 From 8f80e4a05b3f1b227f40de5ec0e9a6297154ffc0 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 2 Apr 2021 08:06:09 -0600 Subject: Update Bluetooth API annotations. Recent work has introduced a new "Nearby devices" runtime permission which protects all existing Bluetooth APIs; we've done this by defining a to convert the old BLUETOOTH and BLUETOOTH_ADMIN permissions into one of three new permissions: * BLUETOOTH_ADVERTISE: Required to be able to advertise to nearby Bluetooth devices. * BLUETOOTH_CONNECT: Allows applications to connect to paired bluetooth devices. * BLUETOOTH_SCAN: Required to be able to discover and pair nearby Bluetooth devices. At its core, this change begins updating the Bluetooth APIs to have correct @RequiresPermission indicating which permission is actually enforced internally. To ensure alignment across Binder, the newly added "RequiresPermissionChecker" Error Prone checker was used to discover any inconsistencies, ensuring correctness from server-side enforcement up through to the public APIs. In addition, since developers will continue building apps for both modern and legacy platforms, this change introduces new auto-doc annotations which will emit helpful consistent documentation describing the behavior of older devices that are still using the old permission model. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: I02aa127e8e07f239561f4f2a3bbdfc6fccb82f7f --- framework/java/android/bluetooth/BluetoothMap.java | 33 +++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 3554995400..3e7b75aa1f 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -93,7 +93,6 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { mCloseGuard.open("close"); } - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize() { if (mCloseGuard != null) { mCloseGuard.warnIfOpen(); @@ -110,7 +109,6 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public void close() { if (VDBG) log("close()"); mProfileConnector.disconnect(); @@ -128,6 +126,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getState() { if (VDBG) log("getState()"); final IBluetoothMap service = getService(); @@ -152,6 +151,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public BluetoothDevice getClient() { if (VDBG) log("getClient()"); final IBluetoothMap service = getService(); @@ -175,6 +175,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); final IBluetoothMap service = getService(); @@ -211,6 +212,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = getService(); @@ -257,7 +259,10 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) public @NonNull List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothMap service = getService(); @@ -280,6 +285,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); final IBluetoothMap service = getService(); @@ -302,6 +308,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); final IBluetoothMap service = getService(); @@ -328,7 +335,10 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @return true if priority is set, false on error * @hide */ - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority)); @@ -347,7 +357,10 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); @@ -378,7 +391,10 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @return priority of the device * @hide */ - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device)); @@ -396,7 +412,10 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothMap service = getService(); -- cgit v1.2.3 From 5ba8bfca7e9adf5c6d8ee8180aebad6f04037d6c Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 16 Apr 2021 09:53:23 -0600 Subject: More Bluetooth API annotation updates. This change adds a "BluetoothPermissionChecker" that ensures that all Bluetooth permission annotations are consistent. In addition, it verifies that all Bluetooth public APIs have been audited to be permission protected where relevant. We've currently standardized on saying that APIs that return device or Bluetooth state information (without sharing details about any particular remote Bluetooth device) do not need to be permission protected. This change is only annotations and has no behavior changes. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: Ie80b15b058359bf1e9a6ee881b89cb3e5b584ca1 --- framework/java/android/bluetooth/BluetoothMap.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 3e7b75aa1f..998fde0283 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -18,9 +18,11 @@ package android.bluetooth; import android.Manifest; import android.annotation.NonNull; +import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Binder; @@ -126,6 +128,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getState() { if (VDBG) log("getState()"); @@ -151,6 +154,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public BluetoothDevice getClient() { if (VDBG) log("getClient()"); @@ -175,6 +179,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); @@ -198,6 +203,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresNoPermission public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")" + "not supported for MAPS"); return false; @@ -212,6 +218,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); @@ -259,6 +266,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi + @RequiresBluetoothConnectPermission @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, @@ -285,6 +293,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); @@ -308,6 +317,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); @@ -335,6 +345,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @return true if priority is set, false on error * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, @@ -357,6 +368,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi + @RequiresBluetoothConnectPermission @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, @@ -391,6 +403,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @return priority of the device * @hide */ + @RequiresBluetoothConnectPermission @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, @@ -412,6 +425,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { * @hide */ @SystemApi + @RequiresBluetoothConnectPermission @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, -- cgit v1.2.3 From d7c55664839ca7e6237cd0ef0f36eb51a4ee7ae6 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 20 Apr 2021 12:30:37 -0600 Subject: Annotations for Bluetooth broadcast intents. Recent work has been using Error Prone rules and annotations to reflect the current state of permission enforcement across the Bluetooth stack, and we're now in a position were we can add new permission enforcement that had been missing. We've currently standardized on saying that APIs that return device or Bluetooth state information (without sharing details about any particular remote Bluetooth device) do not need to be permission protected. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: I53ac7a4fe1dea57316048c3cac4fa237b6ba3d38 --- framework/java/android/bluetooth/BluetoothMap.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 998fde0283..a025d9b4d0 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -20,8 +20,10 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; +import android.annotation.SdkConstant; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.annotation.SdkConstant.SdkConstantType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -53,6 +55,9 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { /** @hide */ @SuppressLint("ActionValue") @SystemApi + @RequiresBluetoothConnectPermission + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; -- cgit v1.2.3 From f9e176c3dcafb82f251a123751578539e3484deb Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 22 Apr 2021 16:01:29 -0600 Subject: More AttributionSource plumbing. To prepare for future work which will plumb AttributionSource values through all remaining AIDLs, we need profiles to interact directly with the specific BluetoothAdapter they were created from. This is how we'll ensure that the relevant AttributionSource can be chained down from the original Context they're obtained from. This change also marks getDefaultAdapter() as deprecated to clearly communicate that BluetoothManager.getAdapter() is the best-practice path to obtaining a correctly scoped BluetoothAdapter instance. Bug: 183626112 Test: atest BluetoothInstrumentationTests Change-Id: I1e15170d7679019bbb6e396279d6e633e3dad4d6 --- framework/java/android/bluetooth/BluetoothMap.java | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index a025d9b4d0..68bb60a854 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -26,6 +26,7 @@ import android.annotation.SystemApi; import android.annotation.SdkConstant.SdkConstantType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; +import android.content.AttributionSource; import android.content.Context; import android.os.Binder; import android.os.Build; @@ -79,7 +80,8 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { */ public static final int RESULT_CANCELED = 2; - private BluetoothAdapter mAdapter; + private final BluetoothAdapter mAdapter; + private final AttributionSource mAttributionSource; private final BluetoothProfileConnector mProfileConnector = new BluetoothProfileConnector(this, BluetoothProfile.MAP, "BluetoothMap", IBluetoothMap.class.getName()) { @@ -92,9 +94,11 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { /** * Create a BluetoothMap proxy object. */ - /*package*/ BluetoothMap(Context context, ServiceListener listener) { + /* package */ BluetoothMap(Context context, ServiceListener listener, + BluetoothAdapter adapter) { if (DBG) Log.d(TAG, "Create BluetoothMap proxy object"); - mAdapter = BluetoothAdapter.getDefaultAdapter(); + mAdapter = adapter; + mAttributionSource = adapter.getAttributionSource(); mProfileConnector.connect(context, listener); mCloseGuard = new CloseGuard(); mCloseGuard.open("close"); @@ -281,7 +285,8 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null && isEnabled()) { try { - return service.getConnectedDevices(); + return BluetoothDevice.setAttributionSource( + service.getConnectedDevices(), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList(); @@ -305,7 +310,8 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null && isEnabled()) { try { - return service.getDevicesMatchingConnectionStates(states); + return BluetoothDevice.setAttributionSource( + service.getDevicesMatchingConnectionStates(states), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList(); @@ -455,13 +461,10 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { } private boolean isEnabled() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; - log("Bluetooth is Not enabled"); - return false; + return mAdapter.isEnabled(); } + private static boolean isValidDevice(BluetoothDevice device) { return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } - } -- cgit v1.2.3 From 43ee69eed974cd7ebc4784416a6e1e251464cc36 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 23 Apr 2021 14:13:57 -0600 Subject: Long-tail of AttributionSource plumbing. Wires up AttributionSource across the remaining long-tail of Bluetooth AIDL interfaces, ensuring that developers can accurately make calls chained back to a specific Context. Moves "for data delivery" permission checks to happen in a single location on each interface to ensure they're performed consistently with the new AttributionSource arguments. Note that "for data delivery" isn't the best name; it's designed to represent that the requested action was performed and should result in the relevant appop being noted for the caller. This change has the positive side effect of ensuring that all interfaces are consistently enforcing the BLUETOOTH_CONNECT permission, even in the case where BLUETOOTH_PRIVILEGED is also required; this is what ensures that revoking the "Nearby devices" permission takes effect for all callers. Additionally, standardizing on enforcing permissions closer to the AIDL entry point reduces the need for @RequiresPermission annotations to be carried around inside the Bluetooth stack. Bug: 183626112 Test: atest BluetoothInstrumentationTests Change-Id: I8023dda654e325b8bfa2f0cdb994ad63a2b429d4 --- framework/java/android/bluetooth/BluetoothMap.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 68bb60a854..88505b51f8 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -144,7 +144,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null) { try { - return service.getState(); + return service.getState(mAttributionSource); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -170,7 +170,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null) { try { - return service.getClient(); + return service.getClient(mAttributionSource); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -195,7 +195,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null) { try { - return service.isConnected(device); + return service.isConnected(device, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -234,7 +234,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { try { - return service.disconnect(device); + return service.disconnect(device, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; @@ -286,7 +286,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { if (service != null && isEnabled()) { try { return BluetoothDevice.setAttributionSource( - service.getConnectedDevices(), mAttributionSource); + service.getConnectedDevices(mAttributionSource), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList(); @@ -311,7 +311,8 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { if (service != null && isEnabled()) { try { return BluetoothDevice.setAttributionSource( - service.getDevicesMatchingConnectionStates(states), mAttributionSource); + service.getDevicesMatchingConnectionStates(states, mAttributionSource), + mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList(); @@ -335,7 +336,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device); + return service.getConnectionState(device, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; @@ -394,7 +395,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { return false; } try { - return service.setConnectionPolicy(device, connectionPolicy); + return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; @@ -446,7 +447,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null && isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device); + return service.getConnectionPolicy(device, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; -- cgit v1.2.3 From 98f3044ce87c7ab9d2a0efbfb8ef6a16872262df Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 3 Jun 2021 09:26:53 -0600 Subject: More Binder call AttributionSource assignment. Since developers can use a BluetoothDevice object can make remote calls, it needs to have an accurate AttributionSource. Previous CLs had updated many places where these BluetoothDevice instances were passed across Binder interfaces, but this change updates several remaining locations which had been missed. Introduces new "Attributable" marker interface to offer consistent tooling when applying AttributionSource updates. Bug: 187097694 Test: atest BluetoothInstrumentationTests Change-Id: Icad3b9726591f0fbad58a493cefa5a0af7648280 --- framework/java/android/bluetooth/BluetoothMap.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 88505b51f8..86796519df 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -26,6 +26,7 @@ import android.annotation.SystemApi; import android.annotation.SdkConstant.SdkConstantType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; +import android.content.Attributable; import android.content.AttributionSource; import android.content.Context; import android.os.Binder; @@ -170,7 +171,8 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null) { try { - return service.getClient(mAttributionSource); + return Attributable.setAttributionSource( + service.getClient(mAttributionSource), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -285,7 +287,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null && isEnabled()) { try { - return BluetoothDevice.setAttributionSource( + return Attributable.setAttributionSource( service.getConnectedDevices(mAttributionSource), mAttributionSource); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); @@ -310,7 +312,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { final IBluetoothMap service = getService(); if (service != null && isEnabled()) { try { - return BluetoothDevice.setAttributionSource( + return Attributable.setAttributionSource( service.getDevicesMatchingConnectionStates(states, mAttributionSource), mAttributionSource); } catch (RemoteException e) { -- cgit v1.2.3 From d517127a57b499305f82ec6eea6da8e0bd485e87 Mon Sep 17 00:00:00 2001 From: William Escande Date: Tue, 14 Dec 2021 16:16:11 +0100 Subject: Copy attributable to Bluetooth Attributable is called by bluetooth and it's hidden. By copying into bluetooth we are now allowed to call it Bug: 210467788 Test: build Tag: #refactor Change-Id: I73ea07c9439988ab5477c82799f718c6d81513be --- framework/java/android/bluetooth/BluetoothMap.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 86796519df..474e41f4aa 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -21,12 +21,11 @@ import android.annotation.NonNull; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SuppressLint; import android.annotation.SystemApi; -import android.annotation.SdkConstant.SdkConstantType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; -import android.content.Attributable; import android.content.AttributionSource; import android.content.Context; import android.os.Binder; -- cgit v1.2.3 From b86023dde0fbbe539e2415942ffe1c97108654f8 Mon Sep 17 00:00:00 2001 From: William Escande Date: Thu, 16 Dec 2021 16:07:55 +0100 Subject: Remove allowBlocking from all BluetoothProfiles Since Bluetooth is becoming a mainline module, it can no longer call the allowBlocking hidden api. Instead, all interface are moved to be oneway and use a synchronous data to handle the return value. Bug: 200200870 Test: Build + start Bt and play something on speaker Tag: #refactor Merged-In: I776a6322faadca1504bce24f2b6b041e756b6448 Change-Id: I776a6322faadca1504bce24f2b6b041e756b6448 --- framework/java/android/bluetooth/BluetoothMap.java | 185 +++++++++++++-------- 1 file changed, 113 insertions(+), 72 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 474e41f4aa..56e4972624 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -16,6 +16,8 @@ package android.bluetooth; +import static android.bluetooth.BluetoothUtils.getSyncTimeout; + import android.Manifest; import android.annotation.NonNull; import android.annotation.RequiresNoPermission; @@ -28,15 +30,17 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.compat.annotation.UnsupportedAppUsage; import android.content.AttributionSource; import android.content.Context; -import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.CloseGuard; import android.util.Log; +import com.android.modules.utils.SynchronousResultReceiver; + import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeoutException; /** * This class provides the APIs to control the Bluetooth MAP @@ -87,7 +91,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { "BluetoothMap", IBluetoothMap.class.getName()) { @Override public IBluetoothMap getServiceInterface(IBinder service) { - return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service)); + return IBluetoothMap.Stub.asInterface(service); } }; @@ -142,17 +146,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public int getState() { if (VDBG) log("getState()"); final IBluetoothMap service = getService(); - if (service != null) { - try { - return service.getState(mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + final int defaultValue = BluetoothMap.STATE_ERROR; + if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getState(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return BluetoothMap.STATE_ERROR; + return defaultValue; } /** @@ -168,18 +175,23 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public BluetoothDevice getClient() { if (VDBG) log("getClient()"); final IBluetoothMap service = getService(); - if (service != null) { + final BluetoothDevice defaultValue = null; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { + final SynchronousResultReceiver recv = + new SynchronousResultReceiver(); + service.getClient(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getClient(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } - } else { - Log.w(TAG, "Proxy not attached to service"); - if (DBG) log(Log.getStackTraceString(new Throwable())); } - return null; + return defaultValue; } /** @@ -194,17 +206,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null) { - try { - return service.isConnected(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - } else { + final boolean defaultValue = false; + if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { + try { + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.isConnected(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } } - return false; + return defaultValue; } /** @@ -233,16 +248,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.disconnect(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.disconnect(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -284,17 +303,23 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public @NonNull List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); final IBluetoothMap service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getConnectedDevices(mAttributionSource, recv); return Attributable.setAttributionSource( - service.getConnectedDevices(mAttributionSource), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), + mAttributionSource); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -309,18 +334,23 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); final IBluetoothMap service = getService(); - if (service != null && isEnabled()) { + final List defaultValue = new ArrayList(); + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled()) { try { + final SynchronousResultReceiver> recv = + new SynchronousResultReceiver(); + service.getDevicesMatchingConnectionStates(states, mAttributionSource, recv); return Attributable.setAttributionSource( - service.getDevicesMatchingConnectionStates(states, mAttributionSource), + recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue), mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return new ArrayList(); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); + return defaultValue; } /** @@ -335,16 +365,21 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.STATE_DISCONNECTED; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionState(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; + final SynchronousResultReceiver recv = + new SynchronousResultReceiver(); + service.getConnectionState(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; + return defaultValue; } /** @@ -390,20 +425,22 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { @ConnectionPolicy int connectionPolicy) { if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } + final boolean defaultValue = false; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device) + && (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN + || connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED)) { try { - return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return false; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; + return defaultValue; } /** @@ -446,16 +483,20 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable { public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) { if (VDBG) log("getConnectionPolicy(" + device + ")"); final IBluetoothMap service = getService(); - if (service != null && isEnabled() && isValidDevice(device)) { + final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + if (service == null) { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (isEnabled() && isValidDevice(device)) { try { - return service.getConnectionPolicy(device, mAttributionSource); - } catch (RemoteException e) { - Log.e(TAG, Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + final SynchronousResultReceiver recv = new SynchronousResultReceiver(); + service.getConnectionPolicy(device, mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); + } catch (RemoteException | TimeoutException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; + return defaultValue; } private static void log(String msg) { -- cgit v1.2.3