[转载]Bluetooth initialization - enable in Settings & System_server process

作者 by adtxl / 2022-08-18 / 暂无评论 / 180 个足迹

作者:MelanDawn
链接:https://www.jianshu.com/p/010c37d5743d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1. overview

image.png

蓝牙初始化框图如上:

  1. 蓝牙处于关闭状态时,进程 com.android.bluetooth 不存在。
  2. 以设置打开蓝牙为例,蓝牙初始化(即 enable)的流程是 com.android.settings(设置进程) ----> system_server(系统服务进程)----> com.android.bluetooth(蓝牙进程)
  3. 蓝牙进程启动之后,设置应用将直接与蓝牙进程通信,无需再经过系统服务进程。

2. Settings Process - 触发开启蓝牙

// frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java

    /**
     * Turn on the local Bluetooth adapter—do not use without explicit
     * user action to turn on Bluetooth.
     * <p>This powers on the underlying Bluetooth hardware, and starts all
     * Bluetooth system services.
     * <p class="caution"><strong>Bluetooth should never be enabled without
     * direct user consent</strong>. If you want to turn on Bluetooth in order
     * to create a wireless connection, you should use the {@link
     * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
     * user permission to turn on Bluetooth. The {@link #enable()} method is
     * provided only for applications that include a user interface for changing
     * system settings, such as a "power manager" app.</p>
     * <p>This is an asynchronous call: it will return immediately, and
     * clients should listen for {@link #ACTION_STATE_CHANGED}
     * to be notified of subsequent adapter state changes. If this call returns
     * true, then the adapter state will immediately transition from {@link
     * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
     * later transition to either {@link #STATE_OFF} or {@link
     * #STATE_ON}. If this call returns false then there was an
     * immediate problem that will prevent the adapter from being turned on -
     * such as Airplane mode, or the adapter is already turned on.
     *
     * @return true to indicate adapter startup has begun, or false on immediate error
     */
    @RequiresLegacyBluetoothAdminPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean enable() {
        if (isEnabled()) {
            if (DBG) {
                Log.d(TAG, "enable(): BT already enabled!");
            }
            return true;
        }
        try {
            return mManagerService.enable(mAttributionSource);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
        return false;
    }

3. System_server Process

3.1 启动蓝牙进程

frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    public boolean enableNoAutoConnect(AttributionSource attributionSource) {
        final String packageName = attributionSource.getPackageName();
        if (!checkBluetoothPermissions(attributionSource, "enableNoAutoConnect", false)) {
            if (DBG) {
                Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed");
            }
            return false;
        }

        if (DBG) {
            Slog.d(TAG, "enableNoAutoConnect():  mBluetooth =" + mBluetooth + " mBinding = "
                    + mBinding);
        }

        int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
        if (callingAppId != Process.NFC_UID) {
            throw new SecurityException("no permission to enable Bluetooth quietly");
        }

        synchronized (mReceiver) {
            mQuietEnableExternal = true;
            mEnableExternal = true;
            sendEnableMsg(true,
                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
        }
        return true;
    }

此处传递的 quietMode = false;

    private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
        sendEnableMsg(quietMode, reason, packageName, false);
    }

    private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) {
        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0,
                  isBle ? 1 : 0));
        addActiveLog(reason, packageName, true);
        mLastEnabledTime = SystemClock.elapsedRealtime();
    }

    private class BluetoothHandler extends Handler {
......
        @Override
        public void handleMessage(Message msg) {
                case MESSAGE_ENABLE:
......
                    mQuietEnable = (msg.arg1 == 1);  // mQuietEnable = false;
                    if (mBluetooth == null) {
                        handleEnable(mQuietEnable);
                    } 
......
                    break;

首次开启时,由于 com.android.bluetooth 还未启动,因此 mBluetooth == null,故会执行绑定服务的操作。

    private void handleEnable(boolean quietMode) {
        mQuietEnable = quietMode; // false

        try {
            if ((mBluetooth == null) && (!mBinding)) {
......
                Intent i = new Intent(IBluetooth.class.getName());
                if (!doBind(i, mConnection, 
                        Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                        UserHandle.CURRENT)) {
                } else {
                    mBinding = true;
                }
            } else if (mBluetooth != null) {
......
            }
        }
    }
    boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {
        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
        intent.setComponent(comp);
        if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {
            return false;
        }
        return true;
    }

绑定的是 IBluetooth 这个服务,由以下配置信息可知,绑定的是 AdapterService.java,该绑定过程会启动 com.android.bluetooth 进程。

packages/apps/Bluetooth/AndroidManifest.xml

        <service android:process="@string/process"
             android:name=".btservice.AdapterService"
             android:exported="true">
            <intent-filter>
                <action android:name="android.bluetooth.IBluetooth"/>
            </intent-filter>
        </service>

蓝牙进程的启动过程由 蓝牙进程初始化 来分析,此文继续分析服务被绑定成功后的回调。

3.2 绑定 AdapterService 成功后的回调

// frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    private class BluetoothServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            String name = componentName.getClassName();

            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
                msg.arg1 = SERVICE_IBLUETOOTH;
......
            }
            msg.obj = service;
            mHandler.sendMessage(msg);
        }
......
    }

    private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();

以上源码主要是创建了 MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息,下面开始处理该消息。

    private class BluetoothHandler extends Handler {
......
        @Override
        public void handleMessage(Message msg) {
                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {

                    IBinder service = (IBinder) msg.obj;
                    try {
                        mBluetoothLock.writeLock().lock();
                        if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
......
                            return;
                        } // else must be SERVICE_IBLUETOOTH
......
                        mBinding = false;
                        mBluetoothBinder = service;
                        // 0. 获取蓝牙进程蓝牙适配器服务的代理对象
                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
......
                        // 1. 向蓝牙进程注册回调函数,以达到双向通信的目的
                        try {
                            mBluetooth.registerCallback(mBluetoothCallback);
                        } catch (RemoteException re) {
                            Slog.e(TAG, "Unable to register BluetoothCallback", re);
                        }
                        // 2. Inform BluetoothAdapter instances that service is up
                        sendBluetoothServiceUpCallback();

                        // 3. Do enable request
                        try {
                            if (!mBluetooth.enable(mQuietEnable)) {
                                Slog.e(TAG, "IBluetooth.enable() returned false");
                            }
                        } catch (RemoteException e) {
                            Slog.e(TAG, "Unable to call enable()", e);
                        }

处理 MESSAGE_BLUETOOTH_SERVICE_CONNECTED 消息,从源码可知:
首先,获取并保存蓝牙进程入口的代理对象:mBluetooth;
其次,

  1. 向蓝牙进程注册回调,用于蓝牙进程向系统服务进程发送消息;
  2. 执行应用层注册到系统服务进程的回调,向已注册的应用进程提供 蓝牙进程入口的代理对象;
  3. 向蓝牙进程发起执行 enable 操作的请求。

3.2.1 registerCallback

3.2.1.1 Register Flow

AdapterService 存储该回调对象,在合适的时候触发回调。

// packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

public class AdapterService extends Service {

    private RemoteCallbackList<IBluetoothCallback> mCallbacks = 
            new RemoteCallbackList<IBluetoothCallback>();

    public static class AdapterServiceBinder extends IBluetooth.Stub {

        public void registerCallback(IBluetoothCallback callback) {
            AdapterService service = getService();
......
            service.mCallbacks.register(callback);
        }
    }

3.2.1.2 Callback Implementation

// frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() {
        @Override
        public void onBluetoothStateChange(int prevState, int newState) throws RemoteException {
            Message msg =
                    mHandler.obtainMessage(MESSAGE_BLUETOOTH_STATE_CHANGE, prevState, newState);
            mHandler.sendMessage(msg);
        }
    };

从以上源码可知,蓝牙进程调用该回调以通知系统服务进程蓝牙的状态变化信息。

    private class BluetoothHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_BLUETOOTH_STATE_CHANGE: {
                    int prevState = msg.arg1;
                    int newState = msg.arg2;
                    mState = newState;
                    bluetoothStateChangeHandler(prevState, newState);
  ......
                    break;
                }

bluetoothStateChangeHandler() 负责更新状态,并发送状态变化的广播。

3.2.1.3 Callback Invoke Example

回调方法执行的源码如下

packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java

    void updateAdapterState(int prevState, int newState) {
......
        if (mCallbacks != null) {
            int n = mCallbacks.beginBroadcast();
            for (int i = 0; i < n; i++) {
                try {
                    mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);
                } catch (RemoteException e) {
......
                }
            }
            mCallbacks.finishBroadcast();
        }

// frameworks/base/core/java/android/os/RemoteCallbackList.java

public class RemoteCallbackList<E extends IInterface> {

    public int beginBroadcast() {
        synchronized (mCallbacks) {
            final int N = mBroadcastCount = mCallbacks.size();
            if (N <= 0) {
                return 0;
            }
            Object[] active = mActiveBroadcast;
            if (active == null || active.length < N) {
                mActiveBroadcast = active = new Object[N];
            }
            for (int i=0; i<N; i++) {
                active[i] = mCallbacks.valueAt(i);
            }
            return N;
        }
    }

    public void finishBroadcast() {
        synchronized (mCallbacks) {
            Object[] active = mActiveBroadcast;
            if (active != null) {
                final int N = mBroadcastCount;
                for (int i=0; i<N; i++) {
                    active[i] = null;
                }
            }
            mBroadcastCount = -1;
        }
    }
}

3.2.2 sendBluetoothServiceUpCallback

frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java

    private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks = 
            new RemoteCallbackList<IBluetoothManagerCallback>();;

    private void sendBluetoothServiceUpCallback() {
        synchronized (mCallbacks) {
            try {
                int n = mCallbacks.beginBroadcast();
                for (int i = 0; i < n; i++) {
                    try {
                        mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
                    }
                }
            } finally {
                mCallbacks.finishBroadcast();
            }
        }
    }

BluetoothManagerService 回调应用层注册的回调对象的方法 onBluetoothServiceUp(),将蓝牙进程入口的代理对象发送到该应用。

frameworks/base/core/java/android/bluetooth/BluetoothDevice.java

public final class BluetoothDevice implements Parcelable {

    static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() {

        public void onBluetoothServiceUp(IBluetooth bluetoothService)
                throws RemoteException {
            synchronized (BluetoothDevice.class) {
                if (sService == null) {
                    sService = bluetoothService;
                }
            }
        }
        ......
    }
}

3.2.3 Bluetooth Process enable

蓝牙进程继续执行 enable 操作的内容较多,链接如下。
Bluetooth initialization - enable in Bluetooth process

用一张图总结下:

imagedc00453485c1f7bf.png

独特见解