Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25fc56ed authored by William Escande's avatar William Escande
Browse files

Add caching for {Map,Sap}.getConnectionState

BluetoothMap and BluetoothSap are heavily using their getConnectionState
method. By caching the value I intend to reduce drastically the number
of binder calls generated.
While performing a discovery, the caching is working on 80% of binder
calls. This value should be bigger when we kepp asking the value for the
same device. (currently everytime you ask the connection state of a new
device, you refresh the cache, there is no caching for multiples
devices).

I don't have any Map/Sap setup to test it, asking to test team if they
hit some issues

Fixing cache on BluetoothDevice by passing the device as parameter

Doing a refactoring of all cached method in bluetooth to keep code
consistency: AKA we try to do the most of check outside of the cache
query

Bug: 217366135
Test: Put some log to see the value being cached sometimes - need more testing
Ignore-AOSP-First: No caching api on AOSP
Change-Id: Iababf9f9068a181e277b400e786a4a67d4447dc8
parent 89f4da04
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -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();
    }
    }
@@ -274,6 +278,7 @@ class AdapterProperties {
        invalidateIsOffloadedFilteringSupportedCache();
        invalidateIsOffloadedFilteringSupportedCache();
        invalidateGetConnectionStateCache();
        invalidateGetConnectionStateCache();
        invalidateGetBondStateCache();
        invalidateGetBondStateCache();
        invalidateBluetoothGetConnectionStateCache();
    }
    }


    @Override
    @Override
+4 −0
Original line number Original line Diff line number Diff line
@@ -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;
@@ -974,6 +976,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) {
+12 −4
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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() {
@@ -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;
@@ -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);
            }
            }
@@ -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);
@@ -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;
@@ -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)) {
@@ -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) {
@@ -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) {
+7 −3
Original line number Original line Diff line number Diff line
@@ -109,6 +109,7 @@ public class SapService extends ProfileService {


    public SapService() {
    public SapService() {
        mState = BluetoothSap.STATE_DISCONNECTED;
        mState = BluetoothSap.STATE_DISCONNECTED;
        BluetoothSap.invalidateBluetoothGetConnectionStateCache();
    }
    }


    /***
    /***
@@ -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");
@@ -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);
@@ -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;
@@ -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) {
+121 −97
Original line number Original line Diff line number Diff line
@@ -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
@@ -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;
    }
    }


    /**
    /**
@@ -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
@@ -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;
    }
    }


    /**
    /**
@@ -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
@@ -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
@@ -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