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

Commit 312688bb authored by Etienne Ruffieux's avatar Etienne Ruffieux
Browse files

Move all profile services bind to BluetoothManagerService

We are currently binding the profile services in framework/
BluetoothProfileConnector, except for BluetoothHeadset
and BluetoothLeCallControl that are bound in BMS.

The issue with binding the profiles in framework/ is that
calling apps don't always have the required permission
(BLUETOOTH_PRIVILEGED) to check if the service is enabled
or not (BluetoothAdapter#getSupportedProfiles), so we are
trying to bind the service even if the profile is disabled.

This change will unify the profiles service binding by
moving the bind process in BluetoothProfileConnector in
BluetoothManagerService and making BluetoothHeadset and
BluetoothLeCallControl use BluetoothProfileConnector.

Bug: 241827236
Bug: 236399693
Test: atest CtsBluetoothTestCases
Test: atest BluetoothInstrumentationTests
Tag: #feature
Ignore-AOSP-First: Cherry-pick
Change-Id: I925b4415c023ff9e43a8ff947ae7ca5456babe64
Merged-In: I925b4415c023ff9e43a8ff947ae7ca5456babe64
parent 16f28028
Loading
Loading
Loading
Loading
+42 −168
Original line number Diff line number Diff line
@@ -31,16 +31,10 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.CloseGuard;
import android.util.Log;

import com.android.modules.utils.SynchronousResultReceiver;
@@ -344,90 +338,25 @@ public final class BluetoothHeadset implements BluetoothProfile {
    public static final String EXTRA_HF_INDICATORS_IND_VALUE =
            "android.bluetooth.headset.extra.HF_INDICATORS_IND_VALUE";

    private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100;
    private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101;

    private final CloseGuard mCloseGuard = new CloseGuard();

    private Context mContext;
    private ServiceListener mServiceListener;
    private volatile IBluetoothHeadset mService;
    private final BluetoothAdapter mAdapter;
    private final AttributionSource mAttributionSource;

    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
            new IBluetoothStateChangeCallback.Stub() {
                public void onBluetoothStateChange(boolean up) {
                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
                    if (!up) {
                        doUnbind();
                    } else {
                        doBind();
                    }
    private final BluetoothProfileConnector<IBluetoothHeadset> mProfileConnector =
            new BluetoothProfileConnector(this, BluetoothProfile.HEADSET, "BluetoothHeadset",
                    IBluetoothHeadset.class.getName()) {
                @Override
                public IBluetoothHeadset getServiceInterface(IBinder service) {
                    return IBluetoothHeadset.Stub.asInterface(service);
                }
    };

    /**
     * Create a BluetoothHeadset proxy object.
     */
    /* package */ BluetoothHeadset(Context context, ServiceListener l, BluetoothAdapter adapter) {
        mContext = context;
        mServiceListener = l;
    /* package */ BluetoothHeadset(Context context, ServiceListener listener,
            BluetoothAdapter adapter) {
        mAdapter = adapter;
        mAttributionSource = adapter.getAttributionSource();

        // Preserve legacy compatibility where apps were depending on
        // registerStateChangeCallback() performing a permissions check which
        // has been relaxed in modern platform versions
        if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R
                && context.checkSelfPermission(android.Manifest.permission.BLUETOOTH)
                        != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Need BLUETOOTH permission");
        }

        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException e) {
                Log.e(TAG, "", e);
            }
        }

        doBind();
        mCloseGuard.open("close");
    }

    private boolean doBind() {
        synchronized (mConnection) {
            if (mService == null) {
                if (VDBG) Log.d(TAG, "Binding service...");
                try {
                    return mAdapter.getBluetoothManager().bindBluetoothProfileService(
                            BluetoothProfile.HEADSET, mConnection);
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to bind HeadsetService", e);
                }
            }
        }
        return false;
    }

    private void doUnbind() {
        synchronized (mConnection) {
            if (mService != null) {
                if (VDBG) Log.d(TAG, "Unbinding service...");
                try {
                    mAdapter.getBluetoothManager().unbindBluetoothProfileService(
                            BluetoothProfile.HEADSET, mConnection);
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to unbind HeadsetService", e);
                } finally {
                    mService = null;
                }
            }
        }
        mProfileConnector.connect(context, listener);
    }

    /**
@@ -438,31 +367,18 @@ public final class BluetoothHeadset implements BluetoothProfile {
     */
    @UnsupportedAppUsage
    /*package*/ void close() {
        if (VDBG) log("close()");

        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException re) {
                Log.e(TAG, "", re);
            }
        mProfileConnector.disconnect();
    }

        if (mServiceListener != null) {
            ServiceListener listener = mServiceListener;
            mServiceListener = null;
            listener.onServiceDisconnected(BluetoothProfile.HEADSET);
        }
        doUnbind();
        mCloseGuard.close();
    private IBluetoothHeadset getService() {
        return mProfileConnector.getService();
    }

    /** {@hide} */
    @Override
    protected void finalize() throws Throwable {
        mCloseGuard.warnIfOpen();
        close();
        // The empty finalize needs to be kept or the
        // cts signature tests would fail.
    }

    /**
@@ -492,7 +408,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public boolean connect(BluetoothDevice device) {
        if (DBG) log("connect(" + device + ")");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -537,7 +453,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean disconnect(BluetoothDevice device) {
        if (DBG) log("disconnect(" + device + ")");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -562,7 +478,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public List<BluetoothDevice> getConnectedDevices() {
        if (VDBG) log("getConnectedDevices()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -590,7 +506,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        if (VDBG) log("getDevicesMatchingStates()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -618,7 +534,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public int getConnectionState(BluetoothDevice device) {
        if (VDBG) log("getConnectionState(" + device + ")");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -657,7 +573,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
            @ConnectionPolicy int connectionPolicy) {
        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -715,7 +631,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
        if (VDBG) log("getConnectionPolicy(" + device + ")");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -743,7 +659,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean isNoiseReductionSupported(@NonNull BluetoothDevice device) {
        if (DBG) log("isNoiseReductionSupported()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -771,7 +687,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean isVoiceRecognitionSupported(@NonNull BluetoothDevice device) {
        if (DBG) log("isVoiceRecognitionSupported()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -815,7 +731,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public boolean startVoiceRecognition(BluetoothDevice device) {
        if (DBG) log("startVoiceRecognition()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -849,7 +765,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean stopVoiceRecognition(BluetoothDevice device) {
        if (DBG) log("stopVoiceRecognition()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -877,7 +793,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean isAudioConnected(BluetoothDevice device) {
        if (VDBG) log("isAudioConnected()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -923,7 +839,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    public @GetAudioStateReturnValues int getAudioState(@NonNull BluetoothDevice device) {
        if (VDBG) log("getAudioState");
        Objects.requireNonNull(device);
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -986,7 +902,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public @SetAudioRouteAllowedReturnValues int setAudioRouteAllowed(boolean allowed) {
        if (VDBG) log("setAudioRouteAllowed");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -1026,7 +942,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public @GetAudioRouteAllowedReturnValues int getAudioRouteAllowed() {
        if (VDBG) log("getAudioRouteAllowed");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -1061,7 +977,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void setForceScoAudio(boolean forced) {
        if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -1114,7 +1030,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public @ConnectAudioReturnValues int connectAudio() {
        if (VDBG) log("connectAudio()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1169,7 +1085,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public @DisconnectAudioReturnValues int disconnectAudio() {
        if (VDBG) log("disconnectAudio()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1224,7 +1140,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public boolean startScoUsingVirtualVoiceCall() {
        if (DBG) log("startScoUsingVirtualVoiceCall()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1263,7 +1179,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public boolean stopScoUsingVirtualVoiceCall() {
        if (DBG) log("stopScoUsingVirtualVoiceCall()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1296,7 +1212,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
            int type, String name) {
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -1322,7 +1238,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
            String number, int type) {
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -1365,7 +1281,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
        if (command == null) {
            throw new IllegalArgumentException("command is null");
        }
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1413,7 +1329,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
        if (DBG) {
            Log.d(TAG, "setActiveDevice: " + device);
        }
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1444,7 +1360,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public BluetoothDevice getActiveDevice() {
        if (VDBG) Log.d(TAG, "getActiveDevice");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final BluetoothDevice defaultValue = null;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1480,7 +1396,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
    })
    public boolean isInbandRingingEnabled() {
        if (DBG) log("isInbandRingingEnabled()");
        final IBluetoothHeadset service = mService;
        final IBluetoothHeadset service = getService();
        final boolean defaultValue = false;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -1497,26 +1413,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
        return defaultValue;
    }

    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private final IBluetoothProfileServiceConnection mConnection =
            new IBluetoothProfileServiceConnection.Stub() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (DBG) Log.d(TAG, "Proxy object connected");
            mService = IBluetoothHeadset.Stub.asInterface(service);
            mHandler.sendMessage(mHandler.obtainMessage(
                    MESSAGE_HEADSET_SERVICE_CONNECTED));
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            if (DBG) Log.d(TAG, "Proxy object disconnected");
            doUnbind();
            mHandler.sendMessage(mHandler.obtainMessage(
                    MESSAGE_HEADSET_SERVICE_DISCONNECTED));
        }
    };

    @UnsupportedAppUsage
    private boolean isEnabled() {
        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
@@ -1533,26 +1429,4 @@ public final class BluetoothHeadset implements BluetoothProfile {
    private static void log(String msg) {
        Log.d(TAG, msg);
    }

    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_HEADSET_SERVICE_CONNECTED: {
                    if (mServiceListener != null) {
                        mServiceListener.onServiceConnected(BluetoothProfile.HEADSET,
                                BluetoothHeadset.this);
                    }
                    break;
                }
                case MESSAGE_HEADSET_SERVICE_DISCONNECTED: {
                    if (mServiceListener != null) {
                        mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
                    }
                    break;
                }
            }
        }
    };
}
+12 −130
Original line number Diff line number Diff line
@@ -17,33 +17,23 @@

package android.bluetooth;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.content.ComponentName;
import android.annotation.SuppressLint;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;
import android.annotation.SuppressLint;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;

@@ -199,9 +189,6 @@ public final class BluetoothLeCallControl implements BluetoothProfile {
     */
    public static final int CAPABILITY_JOIN_CALLS = 0x00000002;

    private static final int MESSAGE_TBS_SERVICE_CONNECTED = 102;
    private static final int MESSAGE_TBS_SERVICE_DISCONNECTED = 103;

    private static final int REG_TIMEOUT = 10000;

    /**
@@ -387,83 +374,29 @@ public final class BluetoothLeCallControl implements BluetoothProfile {
        }
    };

    private Context mContext;
    private ServiceListener mServiceListener;
    private volatile IBluetoothLeCallControl mService;
    private BluetoothAdapter mAdapter;
    private final AttributionSource mAttributionSource;
    private int mCcid = 0;
    private String mToken;
    private Callback mCallback = null;

    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
        new IBluetoothStateChangeCallback.Stub() {
        public void onBluetoothStateChange(boolean up) {
            if (DBG)
                Log.d(TAG, "onBluetoothStateChange: up=" + up);
            if (!up) {
                doUnbind();
            } else {
                doBind();
            }
    private final BluetoothProfileConnector<IBluetoothLeCallControl> mProfileConnector =
            new BluetoothProfileConnector(this, BluetoothProfile.LE_CALL_CONTROL,
                    "BluetoothLeCallControl", IBluetoothLeCallControl.class.getName()) {
                @Override
                public IBluetoothLeCallControl getServiceInterface(IBinder service) {
                    return IBluetoothLeCallControl.Stub.asInterface(service);
                }
    };


    /**
     * Create a BluetoothLeCallControl proxy object for interacting with the local Bluetooth
     * telephone bearer service.
     */
    /* package */ BluetoothLeCallControl(Context context, ServiceListener listener) {
        mContext = context;
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mAttributionSource = mAdapter.getAttributionSource();
        mServiceListener = listener;

        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException e) {
                Log.e(TAG, "", e);
            }
        }

        doBind();
    }

    private boolean doBind() {
        synchronized (mConnection) {
            if (mService == null) {
                if (VDBG)
                    Log.d(TAG, "Binding service...");
                try {
                    return mAdapter.getBluetoothManager().
                            bindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
                            mConnection);
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to bind TelephoneBearerService", e);
                }
            }
        }
        return false;
    }

    private void doUnbind() {
        synchronized (mConnection) {
            if (mService != null) {
                if (VDBG)
                    Log.d(TAG, "Unbinding service...");
                try {
                    mAdapter.getBluetoothManager().
                        unbindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
                        mConnection);
                } catch (RemoteException e) {
                    Log.e(TAG, "Unable to unbind TelephoneBearerService", e);
                } finally {
                    mService = null;
                }
            }
        }
        mProfileConnector.connect(context, listener);
    }

    /* package */ void close() {
@@ -471,20 +404,11 @@ public final class BluetoothLeCallControl implements BluetoothProfile {
            log("close()");
        unregisterBearer();

        IBluetoothManager mgr = mAdapter.getBluetoothManager();
        if (mgr != null) {
            try {
                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
            } catch (RemoteException re) {
                Log.e(TAG, "", re);
            }
        }
        mServiceListener = null;
        doUnbind();
        mProfileConnector.disconnect();
    }

    private IBluetoothLeCallControl getService() {
        return mService;
        return mProfileConnector.getService();
    }

    /**
@@ -863,46 +787,4 @@ public final class BluetoothLeCallControl implements BluetoothProfile {
    private static void log(String msg) {
        Log.d(TAG, msg);
    }

    private final IBluetoothProfileServiceConnection mConnection =
                                    new IBluetoothProfileServiceConnection.Stub() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (DBG) {
                Log.d(TAG, "Proxy object connected");
            }
            mService = IBluetoothLeCallControl.Stub.asInterface(service);
            mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_CONNECTED));
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            if (DBG) {
                Log.d(TAG, "Proxy object disconnected");
            }
            doUnbind();
            mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_DISCONNECTED));
        }
    };

    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_TBS_SERVICE_CONNECTED: {
                if (mServiceListener != null) {
                    mServiceListener.onServiceConnected(BluetoothProfile.LE_CALL_CONTROL,
                        BluetoothLeCallControl.this);
                }
                break;
            }
            case MESSAGE_TBS_SERVICE_DISCONNECTED: {
                if (mServiceListener != null) {
                    mServiceListener.onServiceDisconnected(BluetoothProfile.LE_CALL_CONTROL);
                }
                break;
            }
            }
        }
    };
}
+43 −23

File changed.

Preview size limit exceeded, changes collapsed.

+7 −13

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ interface IBluetoothManager
    IBluetoothGatt getBluetoothGatt();

    @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission")
    boolean bindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
    boolean bindBluetoothProfileService(int profile, String serviceName, IBluetoothProfileServiceConnection proxy);
    @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission")
    void unbindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);