Loading android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -263,6 +263,10 @@ class AdapterProperties { private static void invalidateIsOffloadedFilteringSupportedCache() { private static void invalidateIsOffloadedFilteringSupportedCache() { BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); } } private static void invalidateBluetoothGetConnectionStateCache() { BluetoothMap.invalidateBluetoothGetConnectionStateCache(); BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } private static void invalidateGetConnectionStateCache() { private static void invalidateGetConnectionStateCache() { BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); } } Loading @@ -274,6 +278,7 @@ class AdapterProperties { invalidateIsOffloadedFilteringSupportedCache(); invalidateIsOffloadedFilteringSupportedCache(); invalidateGetConnectionStateCache(); invalidateGetConnectionStateCache(); invalidateGetBondStateCache(); invalidateGetBondStateCache(); invalidateBluetoothGetConnectionStateCache(); } } @Override @Override Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -46,8 +46,10 @@ import android.bluetooth.BluetoothAdapter.ActiveDeviceUse; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothFrameworkInitializer; import android.bluetooth.BluetoothFrameworkInitializer; import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothSap; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes; Loading Loading @@ -985,6 +987,8 @@ public class AdapterService extends Service { BluetoothDevice.invalidateBluetoothGetBondStateCache(); BluetoothDevice.invalidateBluetoothGetBondStateCache(); BluetoothAdapter.invalidateBluetoothGetStateCache(); BluetoothAdapter.invalidateBluetoothGetStateCache(); BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); BluetoothMap.invalidateBluetoothGetConnectionStateCache(); BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } } private void setProfileServiceState(Class service, int state) { private void setProfileServiceState(Class service, int state) { Loading android/app/src/com/android/bluetooth/map/BluetoothMapService.java +12 −4 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.bluetooth.IBluetoothMap; import android.bluetooth.SdpMnsRecord; import android.bluetooth.SdpMnsRecord; import android.content.AttributionSource; import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; Loading Loading @@ -166,6 +165,7 @@ public class BluetoothMapService extends ProfileService { public BluetoothMapService() { public BluetoothMapService() { mState = BluetoothMap.STATE_DISCONNECTED; mState = BluetoothMap.STATE_DISCONNECTED; BluetoothMap.invalidateBluetoothGetConnectionStateCache(); } } private synchronized void closeService() { private synchronized void closeService() { Loading Loading @@ -195,6 +195,7 @@ public class BluetoothMapService extends ProfileService { } } sRemoteDevice = null; sRemoteDevice = null; // no need to invalidate cache here because setState did it above if (mSessionStatusHandler == null) { if (mSessionStatusHandler == null) { return; return; Loading Loading @@ -332,6 +333,7 @@ public class BluetoothMapService extends ProfileService { setState(BluetoothMap.STATE_DISCONNECTED); setState(BluetoothMap.STATE_DISCONNECTED); mPermission = BluetoothDevice.ACCESS_UNKNOWN; mPermission = BluetoothDevice.ACCESS_UNKNOWN; sRemoteDevice = null; sRemoteDevice = null; // no need to invalidate cache here because setState did it above if (mAccountChanged) { if (mAccountChanged) { updateMasInstances(UPDATE_MAS_INSTANCES_ACCOUNT_DISCONNECT); updateMasInstances(UPDATE_MAS_INSTANCES_ACCOUNT_DISCONNECT); } } Loading Loading @@ -519,6 +521,7 @@ public class BluetoothMapService extends ProfileService { } } int prevState = mState; int prevState = mState; mState = state; mState = state; BluetoothMap.invalidateBluetoothGetConnectionStateCache(); Intent intent = new Intent(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); Intent intent = new Intent(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); Loading Loading @@ -595,7 +598,8 @@ public class BluetoothMapService extends ProfileService { */ */ public int getConnectionState(BluetoothDevice device) { public int getConnectionState(BluetoothDevice device) { synchronized (this) { synchronized (this) { if (getState() == BluetoothMap.STATE_CONNECTED && getRemoteDevice().equals(device)) { if (getState() == BluetoothMap.STATE_CONNECTED && getRemoteDevice() != null && getRemoteDevice().equals(device)) { return BluetoothProfile.STATE_CONNECTED; return BluetoothProfile.STATE_CONNECTED; } else { } else { return BluetoothProfile.STATE_DISCONNECTED; return BluetoothProfile.STATE_DISCONNECTED; Loading Loading @@ -911,6 +915,9 @@ public class BluetoothMapService extends ProfileService { synchronized (this) { synchronized (this) { if (sRemoteDevice == null) { if (sRemoteDevice == null) { sRemoteDevice = remoteDevice; sRemoteDevice = remoteDevice; if (getState() == BluetoothMap.STATE_CONNECTED) { BluetoothMap.invalidateBluetoothGetConnectionStateCache(); } sRemoteDeviceName = Utils.getName(sRemoteDevice); sRemoteDeviceName = Utils.getName(sRemoteDevice); // In case getRemoteName failed and return null // In case getRemoteName failed and return null if (TextUtils.isEmpty(sRemoteDeviceName)) { if (TextUtils.isEmpty(sRemoteDeviceName)) { Loading @@ -933,6 +940,7 @@ public class BluetoothMapService extends ProfileService { (remoteDevice == null) ? "unknown" : Utils.getName(remoteDevice))); (remoteDevice == null) ? "unknown" : Utils.getName(remoteDevice))); return false; return false; } // Else second connection to same device, just continue } // Else second connection to same device, just continue } } if (sendIntent) { if (sendIntent) { Loading Loading @@ -1274,8 +1282,8 @@ public class BluetoothMapService extends ProfileService { BluetoothMapService service = getService(source); BluetoothMapService service = getService(source); boolean result = false; boolean result = false; if (service != null) { if (service != null) { result = service.getState() == BluetoothMap.STATE_CONNECTED result = service.getConnectionState(device) && BluetoothMapService.getRemoteDevice().equals(device); == BluetoothProfile.STATE_CONNECTED; } } receiver.send(result); receiver.send(result); } catch (RuntimeException e) { } catch (RuntimeException e) { Loading android/app/src/com/android/bluetooth/sap/SapService.java +7 −3 Original line number Original line Diff line number Diff line Loading @@ -109,6 +109,7 @@ public class SapService extends ProfileService { public SapService() { public SapService() { mState = BluetoothSap.STATE_DISCONNECTED; mState = BluetoothSap.STATE_DISCONNECTED; BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } } /*** /*** Loading Loading @@ -362,6 +363,7 @@ public class SapService extends ProfileService { break; break; } } mRemoteDevice = mConnSocket.getRemoteDevice(); mRemoteDevice = mConnSocket.getRemoteDevice(); BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } } if (mRemoteDevice == null) { if (mRemoteDevice == null) { Log.i(TAG, "getRemoteDevice() = null"); Log.i(TAG, "getRemoteDevice() = null"); Loading Loading @@ -525,6 +527,7 @@ public class SapService extends ProfileService { } } int prevState = mState; int prevState = mState; mState = state; mState = state; BluetoothSap.invalidateBluetoothGetConnectionStateCache(); Intent intent = new Intent(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); Intent intent = new Intent(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); Loading Loading @@ -596,7 +599,8 @@ public class SapService extends ProfileService { public int getConnectionState(BluetoothDevice device) { public int getConnectionState(BluetoothDevice device) { synchronized (this) { synchronized (this) { if (getState() == BluetoothSap.STATE_CONNECTED && getRemoteDevice().equals(device)) { if (getState() == BluetoothSap.STATE_CONNECTED && getRemoteDevice() != null && getRemoteDevice().equals(device)) { return BluetoothProfile.STATE_CONNECTED; return BluetoothProfile.STATE_CONNECTED; } else { } else { return BluetoothProfile.STATE_DISCONNECTED; return BluetoothProfile.STATE_DISCONNECTED; Loading Loading @@ -982,8 +986,8 @@ public class SapService extends ProfileService { boolean defaultValue = false; boolean defaultValue = false; SapService service = getService(source); SapService service = getService(source); if (service != null) { if (service != null) { defaultValue = service.getState() == BluetoothSap.STATE_CONNECTED defaultValue = service.getConnectionState(device) && service.getRemoteDevice().equals(device); == BluetoothProfile.STATE_CONNECTED; } } receiver.send(defaultValue); receiver.send(defaultValue); } catch (RuntimeException e) { } catch (RuntimeException e) { Loading framework/java/android/bluetooth/BluetoothAdapter.java +121 −97 Original line number Original line Diff line number Diff line Loading @@ -1269,36 +1269,27 @@ public final class BluetoothAdapter { IpcDataCache.invalidateCache(IpcDataCache.MODULE_BLUETOOTH, api); IpcDataCache.invalidateCache(IpcDataCache.MODULE_BLUETOOTH, api); } } /** private final IpcDataCache.QueryHandler<IBluetooth, Integer> mBluetoothGetStateQuery = * The binder cache for getState(). */ private static final String GET_STATE_API = "getState"; private final IpcDataCache.QueryHandler<Void, Integer> mBluetoothGetStateQuery = new IpcDataCache.QueryHandler<>() { new IpcDataCache.QueryHandler<>() { @RequiresLegacyBluetoothPermission @RequiresLegacyBluetoothPermission @RequiresNoPermission @RequiresNoPermission @Override @Override public @InternalAdapterState Integer apply(Void query) { public @InternalAdapterState Integer apply(IBluetooth serviceQuery) { int state = BluetoothAdapter.STATE_OFF; mServiceLock.readLock().lock(); try { try { if (mService != null) { final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = serviceQuery.getState(recv); new SynchronousResultReceiver(); return recv.awaitResultNoInterrupt(getSyncTimeout()) mService.getState(recv); .getValue(BluetoothAdapter.STATE_OFF); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(state); } } catch (RemoteException | TimeoutException e) { } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw new RuntimeException(e); } finally { mServiceLock.readLock().unlock(); } } return state; } }}; }; private final IpcDataCache<Void, Integer> mBluetoothGetStateCache = private static final String GET_STATE_API = "BluetoothAdapter_getState"; new BluetoothCache<Void, Integer>(GET_STATE_API, mBluetoothGetStateQuery); private final IpcDataCache<IBluetooth, Integer> mBluetoothGetStateCache = new BluetoothCache<>(GET_STATE_API, mBluetoothGetStateQuery); /** @hide */ /** @hide */ @RequiresNoPermission @RequiresNoPermission Loading @@ -1316,7 +1307,21 @@ public final class BluetoothAdapter { * OFF. * OFF. */ */ private @InternalAdapterState int getStateInternal() { private @InternalAdapterState int getStateInternal() { return mBluetoothGetStateCache.query(null); mServiceLock.readLock().lock(); try { if (mService != null) { return mBluetoothGetStateCache.query(mService); } } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } return STATE_OFF; } } /** /** Loading Loading @@ -2417,31 +2422,25 @@ public final class BluetoothAdapter { } } } } private final IpcDataCache.QueryHandler<Void, Boolean> mBluetoothFilteringQuery = private final IpcDataCache.QueryHandler<IBluetooth, Boolean> mBluetoothFilteringQuery = new IpcDataCache.QueryHandler<>() { new IpcDataCache.QueryHandler<>() { @RequiresLegacyBluetoothPermission @RequiresLegacyBluetoothPermission @RequiresNoPermission @RequiresNoPermission @Override @Override public Boolean apply(Void query) { public Boolean apply(IBluetooth serviceQuery) { mServiceLock.readLock().lock(); try { try { if (mService != null) { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); mService.isOffloadedFilteringSupported(recv); serviceQuery.isOffloadedFilteringSupported(recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false); } } catch (RemoteException | TimeoutException e) { } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw new RuntimeException(e); } finally { mServiceLock.readLock().unlock(); } } return false; }}; }}; private static final String FILTERING_API = "isOffloadedFilteringSupported"; private static final String FILTERING_API = "BluetoothAdapter_isOffloadedFilteringSupported"; private final IpcDataCache<Void, Boolean> mBluetoothFilteringCache = private final IpcDataCache<IBluetooth, Boolean> mBluetoothFilteringCache = new BluetoothCache<Void, Boolean>(FILTERING_API, mBluetoothFilteringQuery); new BluetoothCache<>(FILTERING_API, mBluetoothFilteringQuery); /** @hide */ /** @hide */ @RequiresNoPermission @RequiresNoPermission Loading @@ -2465,7 +2464,19 @@ public final class BluetoothAdapter { if (!getLeAccess()) { if (!getLeAccess()) { return false; return false; } } return mBluetoothFilteringCache.query(null); mServiceLock.readLock().lock(); try { if (mService != null) return mBluetoothFilteringCache.query(mService); } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } return false; } } /** /** Loading Loading @@ -2967,35 +2978,28 @@ public final class BluetoothAdapter { return supportedProfiles; return supportedProfiles; } } private final IpcDataCache.QueryHandler<Void, Integer> mBluetoothGetAdapterQuery = private final IpcDataCache.QueryHandler<IBluetooth, Integer> new IpcDataCache.QueryHandler<>() { mBluetoothGetAdapterConnectionStateQuery = new IpcDataCache.QueryHandler<>() { @RequiresLegacyBluetoothPermission @RequiresLegacyBluetoothPermission @RequiresNoPermission @RequiresNoPermission @Override @Override public Integer apply(Void query) { public Integer apply(IBluetooth serviceQuery) { mServiceLock.readLock().lock(); try { try { if (mService != null) { final SynchronousResultReceiver<Integer> recv = final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); new SynchronousResultReceiver(); mService.getAdapterConnectionState(recv); serviceQuery.getAdapterConnectionState(recv); return recv.awaitResultNoInterrupt(getSyncTimeout()) return recv.awaitResultNoInterrupt(getSyncTimeout()) .getValue(STATE_DISCONNECTED); .getValue(STATE_DISCONNECTED); } catch (RemoteException | TimeoutException e) { throw new RuntimeException(e); } } } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } catch (RemoteException e) { Log.e(TAG, "failed to getConnectionState, error: ", e); } finally { mServiceLock.readLock().unlock(); } } return BluetoothAdapter.STATE_DISCONNECTED; }; }}; private static final String GET_CONNECTION_API = "BluetoothAdapter_getConnectionState"; private static final String GET_CONNECTION_API = "getAdapterConnectionState"; private final IpcDataCache<IBluetooth, Integer> mBluetoothGetAdapterConnectionStateCache = private final IpcDataCache<Void, Integer> new BluetoothCache<>(GET_CONNECTION_API, mBluetoothGetAdapterConnectionStateQuery); mBluetoothGetAdapterConnectionStateCache = new BluetoothCache<Void, Integer>(GET_CONNECTION_API, mBluetoothGetAdapterQuery); /** @hide */ /** @hide */ @RequiresNoPermission @RequiresNoPermission Loading Loading @@ -3025,36 +3029,42 @@ public final class BluetoothAdapter { if (getState() != STATE_ON) { if (getState() != STATE_ON) { return BluetoothAdapter.STATE_DISCONNECTED; return BluetoothAdapter.STATE_DISCONNECTED; } } return mBluetoothGetAdapterConnectionStateCache.query(null); mServiceLock.readLock().lock(); try { if (mService != null) return mBluetoothGetAdapterConnectionStateCache.query(mService); } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } return STATE_DISCONNECTED; } } private final IpcDataCache.QueryHandler<Integer, Integer> mBluetoothProfileQuery = private final IpcDataCache.QueryHandler<Pair<IBluetooth, Integer>, Integer> new IpcDataCache.QueryHandler<>() { mBluetoothProfileQuery = new IpcDataCache.QueryHandler<>() { @RequiresNoPermission @RequiresNoPermission @Override @Override public Integer apply(Integer query) { public Integer apply(Pair<IBluetooth, Integer> pairQuery) { final int defaultValue = STATE_DISCONNECTED; try { try { mServiceLock.readLock().lock(); final SynchronousResultReceiver<Integer> recv = if (mService != null) { new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); pairQuery.first.getProfileConnectionState(pairQuery.second, recv); mService.getProfileConnectionState(query, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); return recv.awaitResultNoInterrupt(getSyncTimeout()) } catch (RemoteException | TimeoutException e) { .getValue(BluetoothProfile.STATE_DISCONNECTED); throw new RuntimeException(e); } } } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } catch (RemoteException e) { Log.e(TAG, "failed to getProfileConnectionState, error: ", e); } finally { mServiceLock.readLock().unlock(); } } return BluetoothProfile.STATE_DISCONNECTED; }; }}; private static final String PROFILE_API = "BluetoothAdapter_getProfileConnectionState"; private static final String PROFILE_API = "getProfileConnectionState"; private final IpcDataCache<Pair<IBluetooth, Integer>, Integer> mGetProfileConnectionStateCache = private final IpcDataCache<Integer, Integer> new BluetoothCache<>(PROFILE_API, mBluetoothProfileQuery); mGetProfileConnectionStateCache = new BluetoothCache<Integer, Integer>(PROFILE_API, mBluetoothProfileQuery); /** /** * @hide * @hide Loading Loading @@ -3085,9 +3095,23 @@ public final class BluetoothAdapter { @SuppressLint("AndroidFrameworkRequiresPermission") @SuppressLint("AndroidFrameworkRequiresPermission") public @ConnectionState int getProfileConnectionState(int profile) { public @ConnectionState int getProfileConnectionState(int profile) { if (getState() != STATE_ON) { if (getState() != STATE_ON) { return BluetoothProfile.STATE_DISCONNECTED; return STATE_DISCONNECTED; } mServiceLock.readLock().lock(); try { if (mService != null) { return mGetProfileConnectionStateCache.query(new Pair<>(mService, profile)); } } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } } return mGetProfileConnectionStateCache.query(profile); return STATE_DISCONNECTED; } } /** /** Loading Loading
android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -263,6 +263,10 @@ class AdapterProperties { private static void invalidateIsOffloadedFilteringSupportedCache() { private static void invalidateIsOffloadedFilteringSupportedCache() { BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); } } private static void invalidateBluetoothGetConnectionStateCache() { BluetoothMap.invalidateBluetoothGetConnectionStateCache(); BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } private static void invalidateGetConnectionStateCache() { private static void invalidateGetConnectionStateCache() { BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); } } Loading @@ -274,6 +278,7 @@ class AdapterProperties { invalidateIsOffloadedFilteringSupportedCache(); invalidateIsOffloadedFilteringSupportedCache(); invalidateGetConnectionStateCache(); invalidateGetConnectionStateCache(); invalidateGetBondStateCache(); invalidateGetBondStateCache(); invalidateBluetoothGetConnectionStateCache(); } } @Override @Override Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -46,8 +46,10 @@ import android.bluetooth.BluetoothAdapter.ActiveDeviceUse; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothFrameworkInitializer; import android.bluetooth.BluetoothFrameworkInitializer; import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothSap; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothStatusCodes; Loading Loading @@ -985,6 +987,8 @@ public class AdapterService extends Service { BluetoothDevice.invalidateBluetoothGetBondStateCache(); BluetoothDevice.invalidateBluetoothGetBondStateCache(); BluetoothAdapter.invalidateBluetoothGetStateCache(); BluetoothAdapter.invalidateBluetoothGetStateCache(); BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); BluetoothMap.invalidateBluetoothGetConnectionStateCache(); BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } } private void setProfileServiceState(Class service, int state) { private void setProfileServiceState(Class service, int state) { Loading
android/app/src/com/android/bluetooth/map/BluetoothMapService.java +12 −4 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.bluetooth.IBluetoothMap; import android.bluetooth.SdpMnsRecord; import android.bluetooth.SdpMnsRecord; import android.content.AttributionSource; import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; Loading Loading @@ -166,6 +165,7 @@ public class BluetoothMapService extends ProfileService { public BluetoothMapService() { public BluetoothMapService() { mState = BluetoothMap.STATE_DISCONNECTED; mState = BluetoothMap.STATE_DISCONNECTED; BluetoothMap.invalidateBluetoothGetConnectionStateCache(); } } private synchronized void closeService() { private synchronized void closeService() { Loading Loading @@ -195,6 +195,7 @@ public class BluetoothMapService extends ProfileService { } } sRemoteDevice = null; sRemoteDevice = null; // no need to invalidate cache here because setState did it above if (mSessionStatusHandler == null) { if (mSessionStatusHandler == null) { return; return; Loading Loading @@ -332,6 +333,7 @@ public class BluetoothMapService extends ProfileService { setState(BluetoothMap.STATE_DISCONNECTED); setState(BluetoothMap.STATE_DISCONNECTED); mPermission = BluetoothDevice.ACCESS_UNKNOWN; mPermission = BluetoothDevice.ACCESS_UNKNOWN; sRemoteDevice = null; sRemoteDevice = null; // no need to invalidate cache here because setState did it above if (mAccountChanged) { if (mAccountChanged) { updateMasInstances(UPDATE_MAS_INSTANCES_ACCOUNT_DISCONNECT); updateMasInstances(UPDATE_MAS_INSTANCES_ACCOUNT_DISCONNECT); } } Loading Loading @@ -519,6 +521,7 @@ public class BluetoothMapService extends ProfileService { } } int prevState = mState; int prevState = mState; mState = state; mState = state; BluetoothMap.invalidateBluetoothGetConnectionStateCache(); Intent intent = new Intent(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); Intent intent = new Intent(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); Loading Loading @@ -595,7 +598,8 @@ public class BluetoothMapService extends ProfileService { */ */ public int getConnectionState(BluetoothDevice device) { public int getConnectionState(BluetoothDevice device) { synchronized (this) { synchronized (this) { if (getState() == BluetoothMap.STATE_CONNECTED && getRemoteDevice().equals(device)) { if (getState() == BluetoothMap.STATE_CONNECTED && getRemoteDevice() != null && getRemoteDevice().equals(device)) { return BluetoothProfile.STATE_CONNECTED; return BluetoothProfile.STATE_CONNECTED; } else { } else { return BluetoothProfile.STATE_DISCONNECTED; return BluetoothProfile.STATE_DISCONNECTED; Loading Loading @@ -911,6 +915,9 @@ public class BluetoothMapService extends ProfileService { synchronized (this) { synchronized (this) { if (sRemoteDevice == null) { if (sRemoteDevice == null) { sRemoteDevice = remoteDevice; sRemoteDevice = remoteDevice; if (getState() == BluetoothMap.STATE_CONNECTED) { BluetoothMap.invalidateBluetoothGetConnectionStateCache(); } sRemoteDeviceName = Utils.getName(sRemoteDevice); sRemoteDeviceName = Utils.getName(sRemoteDevice); // In case getRemoteName failed and return null // In case getRemoteName failed and return null if (TextUtils.isEmpty(sRemoteDeviceName)) { if (TextUtils.isEmpty(sRemoteDeviceName)) { Loading @@ -933,6 +940,7 @@ public class BluetoothMapService extends ProfileService { (remoteDevice == null) ? "unknown" : Utils.getName(remoteDevice))); (remoteDevice == null) ? "unknown" : Utils.getName(remoteDevice))); return false; return false; } // Else second connection to same device, just continue } // Else second connection to same device, just continue } } if (sendIntent) { if (sendIntent) { Loading Loading @@ -1274,8 +1282,8 @@ public class BluetoothMapService extends ProfileService { BluetoothMapService service = getService(source); BluetoothMapService service = getService(source); boolean result = false; boolean result = false; if (service != null) { if (service != null) { result = service.getState() == BluetoothMap.STATE_CONNECTED result = service.getConnectionState(device) && BluetoothMapService.getRemoteDevice().equals(device); == BluetoothProfile.STATE_CONNECTED; } } receiver.send(result); receiver.send(result); } catch (RuntimeException e) { } catch (RuntimeException e) { Loading
android/app/src/com/android/bluetooth/sap/SapService.java +7 −3 Original line number Original line Diff line number Diff line Loading @@ -109,6 +109,7 @@ public class SapService extends ProfileService { public SapService() { public SapService() { mState = BluetoothSap.STATE_DISCONNECTED; mState = BluetoothSap.STATE_DISCONNECTED; BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } } /*** /*** Loading Loading @@ -362,6 +363,7 @@ public class SapService extends ProfileService { break; break; } } mRemoteDevice = mConnSocket.getRemoteDevice(); mRemoteDevice = mConnSocket.getRemoteDevice(); BluetoothSap.invalidateBluetoothGetConnectionStateCache(); } } if (mRemoteDevice == null) { if (mRemoteDevice == null) { Log.i(TAG, "getRemoteDevice() = null"); Log.i(TAG, "getRemoteDevice() = null"); Loading Loading @@ -525,6 +527,7 @@ public class SapService extends ProfileService { } } int prevState = mState; int prevState = mState; mState = state; mState = state; BluetoothSap.invalidateBluetoothGetConnectionStateCache(); Intent intent = new Intent(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); Intent intent = new Intent(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); intent.putExtra(BluetoothProfile.EXTRA_STATE, mState); Loading Loading @@ -596,7 +599,8 @@ public class SapService extends ProfileService { public int getConnectionState(BluetoothDevice device) { public int getConnectionState(BluetoothDevice device) { synchronized (this) { synchronized (this) { if (getState() == BluetoothSap.STATE_CONNECTED && getRemoteDevice().equals(device)) { if (getState() == BluetoothSap.STATE_CONNECTED && getRemoteDevice() != null && getRemoteDevice().equals(device)) { return BluetoothProfile.STATE_CONNECTED; return BluetoothProfile.STATE_CONNECTED; } else { } else { return BluetoothProfile.STATE_DISCONNECTED; return BluetoothProfile.STATE_DISCONNECTED; Loading Loading @@ -982,8 +986,8 @@ public class SapService extends ProfileService { boolean defaultValue = false; boolean defaultValue = false; SapService service = getService(source); SapService service = getService(source); if (service != null) { if (service != null) { defaultValue = service.getState() == BluetoothSap.STATE_CONNECTED defaultValue = service.getConnectionState(device) && service.getRemoteDevice().equals(device); == BluetoothProfile.STATE_CONNECTED; } } receiver.send(defaultValue); receiver.send(defaultValue); } catch (RuntimeException e) { } catch (RuntimeException e) { Loading
framework/java/android/bluetooth/BluetoothAdapter.java +121 −97 Original line number Original line Diff line number Diff line Loading @@ -1269,36 +1269,27 @@ public final class BluetoothAdapter { IpcDataCache.invalidateCache(IpcDataCache.MODULE_BLUETOOTH, api); IpcDataCache.invalidateCache(IpcDataCache.MODULE_BLUETOOTH, api); } } /** private final IpcDataCache.QueryHandler<IBluetooth, Integer> mBluetoothGetStateQuery = * The binder cache for getState(). */ private static final String GET_STATE_API = "getState"; private final IpcDataCache.QueryHandler<Void, Integer> mBluetoothGetStateQuery = new IpcDataCache.QueryHandler<>() { new IpcDataCache.QueryHandler<>() { @RequiresLegacyBluetoothPermission @RequiresLegacyBluetoothPermission @RequiresNoPermission @RequiresNoPermission @Override @Override public @InternalAdapterState Integer apply(Void query) { public @InternalAdapterState Integer apply(IBluetooth serviceQuery) { int state = BluetoothAdapter.STATE_OFF; mServiceLock.readLock().lock(); try { try { if (mService != null) { final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = serviceQuery.getState(recv); new SynchronousResultReceiver(); return recv.awaitResultNoInterrupt(getSyncTimeout()) mService.getState(recv); .getValue(BluetoothAdapter.STATE_OFF); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(state); } } catch (RemoteException | TimeoutException e) { } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw new RuntimeException(e); } finally { mServiceLock.readLock().unlock(); } } return state; } }}; }; private final IpcDataCache<Void, Integer> mBluetoothGetStateCache = private static final String GET_STATE_API = "BluetoothAdapter_getState"; new BluetoothCache<Void, Integer>(GET_STATE_API, mBluetoothGetStateQuery); private final IpcDataCache<IBluetooth, Integer> mBluetoothGetStateCache = new BluetoothCache<>(GET_STATE_API, mBluetoothGetStateQuery); /** @hide */ /** @hide */ @RequiresNoPermission @RequiresNoPermission Loading @@ -1316,7 +1307,21 @@ public final class BluetoothAdapter { * OFF. * OFF. */ */ private @InternalAdapterState int getStateInternal() { private @InternalAdapterState int getStateInternal() { return mBluetoothGetStateCache.query(null); mServiceLock.readLock().lock(); try { if (mService != null) { return mBluetoothGetStateCache.query(mService); } } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } return STATE_OFF; } } /** /** Loading Loading @@ -2417,31 +2422,25 @@ public final class BluetoothAdapter { } } } } private final IpcDataCache.QueryHandler<Void, Boolean> mBluetoothFilteringQuery = private final IpcDataCache.QueryHandler<IBluetooth, Boolean> mBluetoothFilteringQuery = new IpcDataCache.QueryHandler<>() { new IpcDataCache.QueryHandler<>() { @RequiresLegacyBluetoothPermission @RequiresLegacyBluetoothPermission @RequiresNoPermission @RequiresNoPermission @Override @Override public Boolean apply(Void query) { public Boolean apply(IBluetooth serviceQuery) { mServiceLock.readLock().lock(); try { try { if (mService != null) { final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver(); mService.isOffloadedFilteringSupported(recv); serviceQuery.isOffloadedFilteringSupported(recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false); } } catch (RemoteException | TimeoutException e) { } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); throw new RuntimeException(e); } finally { mServiceLock.readLock().unlock(); } } return false; }}; }}; private static final String FILTERING_API = "isOffloadedFilteringSupported"; private static final String FILTERING_API = "BluetoothAdapter_isOffloadedFilteringSupported"; private final IpcDataCache<Void, Boolean> mBluetoothFilteringCache = private final IpcDataCache<IBluetooth, Boolean> mBluetoothFilteringCache = new BluetoothCache<Void, Boolean>(FILTERING_API, mBluetoothFilteringQuery); new BluetoothCache<>(FILTERING_API, mBluetoothFilteringQuery); /** @hide */ /** @hide */ @RequiresNoPermission @RequiresNoPermission Loading @@ -2465,7 +2464,19 @@ public final class BluetoothAdapter { if (!getLeAccess()) { if (!getLeAccess()) { return false; return false; } } return mBluetoothFilteringCache.query(null); mServiceLock.readLock().lock(); try { if (mService != null) return mBluetoothFilteringCache.query(mService); } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } return false; } } /** /** Loading Loading @@ -2967,35 +2978,28 @@ public final class BluetoothAdapter { return supportedProfiles; return supportedProfiles; } } private final IpcDataCache.QueryHandler<Void, Integer> mBluetoothGetAdapterQuery = private final IpcDataCache.QueryHandler<IBluetooth, Integer> new IpcDataCache.QueryHandler<>() { mBluetoothGetAdapterConnectionStateQuery = new IpcDataCache.QueryHandler<>() { @RequiresLegacyBluetoothPermission @RequiresLegacyBluetoothPermission @RequiresNoPermission @RequiresNoPermission @Override @Override public Integer apply(Void query) { public Integer apply(IBluetooth serviceQuery) { mServiceLock.readLock().lock(); try { try { if (mService != null) { final SynchronousResultReceiver<Integer> recv = final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); new SynchronousResultReceiver(); mService.getAdapterConnectionState(recv); serviceQuery.getAdapterConnectionState(recv); return recv.awaitResultNoInterrupt(getSyncTimeout()) return recv.awaitResultNoInterrupt(getSyncTimeout()) .getValue(STATE_DISCONNECTED); .getValue(STATE_DISCONNECTED); } catch (RemoteException | TimeoutException e) { throw new RuntimeException(e); } } } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } catch (RemoteException e) { Log.e(TAG, "failed to getConnectionState, error: ", e); } finally { mServiceLock.readLock().unlock(); } } return BluetoothAdapter.STATE_DISCONNECTED; }; }}; private static final String GET_CONNECTION_API = "BluetoothAdapter_getConnectionState"; private static final String GET_CONNECTION_API = "getAdapterConnectionState"; private final IpcDataCache<IBluetooth, Integer> mBluetoothGetAdapterConnectionStateCache = private final IpcDataCache<Void, Integer> new BluetoothCache<>(GET_CONNECTION_API, mBluetoothGetAdapterConnectionStateQuery); mBluetoothGetAdapterConnectionStateCache = new BluetoothCache<Void, Integer>(GET_CONNECTION_API, mBluetoothGetAdapterQuery); /** @hide */ /** @hide */ @RequiresNoPermission @RequiresNoPermission Loading Loading @@ -3025,36 +3029,42 @@ public final class BluetoothAdapter { if (getState() != STATE_ON) { if (getState() != STATE_ON) { return BluetoothAdapter.STATE_DISCONNECTED; return BluetoothAdapter.STATE_DISCONNECTED; } } return mBluetoothGetAdapterConnectionStateCache.query(null); mServiceLock.readLock().lock(); try { if (mService != null) return mBluetoothGetAdapterConnectionStateCache.query(mService); } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } return STATE_DISCONNECTED; } } private final IpcDataCache.QueryHandler<Integer, Integer> mBluetoothProfileQuery = private final IpcDataCache.QueryHandler<Pair<IBluetooth, Integer>, Integer> new IpcDataCache.QueryHandler<>() { mBluetoothProfileQuery = new IpcDataCache.QueryHandler<>() { @RequiresNoPermission @RequiresNoPermission @Override @Override public Integer apply(Integer query) { public Integer apply(Pair<IBluetooth, Integer> pairQuery) { final int defaultValue = STATE_DISCONNECTED; try { try { mServiceLock.readLock().lock(); final SynchronousResultReceiver<Integer> recv = if (mService != null) { new SynchronousResultReceiver(); final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver(); pairQuery.first.getProfileConnectionState(pairQuery.second, recv); mService.getProfileConnectionState(query, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); return recv.awaitResultNoInterrupt(getSyncTimeout()) } catch (RemoteException | TimeoutException e) { .getValue(BluetoothProfile.STATE_DISCONNECTED); throw new RuntimeException(e); } } } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } catch (RemoteException e) { Log.e(TAG, "failed to getProfileConnectionState, error: ", e); } finally { mServiceLock.readLock().unlock(); } } return BluetoothProfile.STATE_DISCONNECTED; }; }}; private static final String PROFILE_API = "BluetoothAdapter_getProfileConnectionState"; private static final String PROFILE_API = "getProfileConnectionState"; private final IpcDataCache<Pair<IBluetooth, Integer>, Integer> mGetProfileConnectionStateCache = private final IpcDataCache<Integer, Integer> new BluetoothCache<>(PROFILE_API, mBluetoothProfileQuery); mGetProfileConnectionStateCache = new BluetoothCache<Integer, Integer>(PROFILE_API, mBluetoothProfileQuery); /** /** * @hide * @hide Loading Loading @@ -3085,9 +3095,23 @@ public final class BluetoothAdapter { @SuppressLint("AndroidFrameworkRequiresPermission") @SuppressLint("AndroidFrameworkRequiresPermission") public @ConnectionState int getProfileConnectionState(int profile) { public @ConnectionState int getProfileConnectionState(int profile) { if (getState() != STATE_ON) { if (getState() != STATE_ON) { return BluetoothProfile.STATE_DISCONNECTED; return STATE_DISCONNECTED; } mServiceLock.readLock().lock(); try { if (mService != null) { return mGetProfileConnectionStateCache.query(new Pair<>(mService, profile)); } } catch (RuntimeException e) { if (!(e.getCause() instanceof TimeoutException) && !(e.getCause() instanceof RemoteException)) { throw e; } Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } } return mGetProfileConnectionStateCache.query(profile); return STATE_DISCONNECTED; } } /** /** Loading