Android -- Bluetooth framework启动过程简析

                    Android -- Bluetooth framework启动过程简析

        蓝牙是Android设备中非常常见的一个feature,设备厂家可以用BT来做RC、连接音箱、设备本身做Sink等常见功能。如果一些设备不需要BT功能,Android也可以通过配置来disable此模块,方便厂家为自己的设备做客制化。APP操作设备的蓝牙功能,一般是通过标准API-BluetoothAdapter实现,这里我们先不关心具体API的实现flow,先来了解Bluetooth framework的启动过程,这样可以为后面介绍一些BT 常见flow,做铺垫。

我们都知道Android的主要系统服务都是在system_server中启动的,BT也不例外:

            // Skip Bluetooth if we have an emulator kernel
            // TODO: Use a more reliable check to see if this product should
            // support Bluetooth - see bug 988521
            if (isEmulator) {
                Slog.i(TAG, "No Bluetooth Service (emulator)");
            } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                Slog.i(TAG, "No Bluetooth Service (factory test)");
            } else if (!context.getPackageManager().hasSystemFeature
                       (PackageManager.FEATURE_BLUETOOTH)) {
                Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
            } else {
                traceBeginAndSlog("StartBluetoothService");
                mSystemServiceManager.startService(BluetoothService.class);
                traceEnd();
            }

在SystemServer中,BT framework启动的起点以服务启动的形式表现,这在Android中非常常见;我们可以通过配置feature xml文件来表明系统当前是否支持蓝牙,在一些没有蓝牙模组的设备上,就可以去掉hardware feature bluetooth的声明,这样设备启动时就不会启动BT framework相关的模块了:

class BluetoothService extends SystemService {
    private BluetoothManagerService mBluetoothManagerService;

    public BluetoothService(Context context) {
        super(context);
        //创建BluetoothManagerService的实例
        mBluetoothManagerService = new BluetoothManagerService(context);
    }
    ........
    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            //将BluetoothManagerService实例发布到系统中,这样就可以Context根据BT的service名去获取它的Binder代理操作API了
            publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
                    mBluetoothManagerService);
        } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
            //此时系统应该启动到一个比较晚的阶段了,可以使用AMS去Bind需要的Service了
            mBluetoothManagerService.handleOnBootPhase();
        }
    }
    ........
}

BluetoothManagerService构造过程中,跟开机flow中自动enable bt相关的主要是mEnableExternal这个flag:

    BluetoothManagerService(Context context) {
        mHandler = new BluetoothHandler(IoThread.get().getLooper());//创建内部处理msg的handler

        mContext = context;

        mPermissionReviewRequired = context.getResources()
                .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired);

        mCrashes = 0;
        mBluetooth = null;
        mBluetoothBinder = null;
        mBluetoothGatt = null;
        mBinding = false;
        mUnbinding = false;
        mEnable = false;
        mState = BluetoothAdapter.STATE_OFF;
        mQuietEnableExternal = false;//false表示此次enable需要触发auto connect device和保存状态,BluetoothAdapter::enableNoAutoConnect()可以改变此状态
        mEnableExternal = false;
        mAddress = null;
        mName = null;
        mErrorRecoveryRetryCounter = 0;
        mContentResolver = context.getContentResolver();
        // Observe BLE scan only mode settings change.
        registerForBleScanModeChange();
        mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
        mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();

        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);//监听App通过接口修改BT local name的广播(对端设备搜索你显示的字符串)
        filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);//监听bt地址改变的广播
        filter.addAction(Intent.ACTION_SETTING_RESTORED);//监听当前设置需要restore回上一次设置的广播,此时需要重新保存name和addr为上一次的信息
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(mReceiver, filter);

        loadStoredNameAndAddress();//从数据库中加载本机Bt的local name和address
        if (isBluetoothPersistedStateOn()) {//查看上一次关机时,BT是否为enable状态;如果是,这次开机也需要enable BT
            if (DBG) {
                Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
            }
            mEnableExternal = true;//表明开机过程中需要enable BT
        }

        String airplaneModeRadios =
                Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
        if (airplaneModeRadios == null || airplaneModeRadios.contains(
                Settings.Global.RADIO_BLUETOOTH)) {
            mContentResolver.registerContentObserver(
                    Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
                    mAirplaneModeObserver);//监听Airplane mode改变,相应改变BT状态;这在TV plateform上基本没用
        }

        int systemUiUid = -1;
        try {
            // Check if device is configured with no home screen, which implies no SystemUI.
            boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
            if (!noHome) {
                systemUiUid = mContext.getPackageManager()
                        .getPackageUidAsUser("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY,
                                UserHandle.USER_SYSTEM);
            }
            Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
        } catch (PackageManager.NameNotFoundException e) {
            // Some platforms, such as wearables do not have a system ui.
            Slog.w(TAG, "Unable to resolve SystemUI's UID.", e);
        }
        mSystemUiUid = systemUiUid;
    }

它为true,表明上一次关机前BT就是enable的,这次开机也需要enable;其他的主要是一些广播、数据库字段的初始化动作。

回到前面BluetoothService启动的过程,当系统启动到合适的阶段,就回调SystemService相应的函数,当phase为PHASE_ACTIVITY_MANAGER_READY时,调用到BMS::handleOnBootPhase(),进行BT framework的启动:

    /**
     * Send enable message and set adapter name and address. Called when the boot phase becomes
     * PHASE_SYSTEM_SERVICES_READY.
     */
    public void handleOnBootPhase() {
        if (DBG) {
            Slog.d(TAG, "Bluetooth boot completed");
        }
        UserManagerInternal userManagerInternal =
                LocalServices.getService(UserManagerInternal.class);
        userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
        final boolean isBluetoothDisallowed = isBluetoothDisallowed();
        if (isBluetoothDisallowed) {
            return;
        }
        if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
            if (DBG) {
                Slog.d(TAG, "Auto-enabling Bluetooth.");
            }
            sendEnableMsg(mQuietEnableExternal/*默认false,表示此次enable需要自动连接device/保存enable状态*/,
                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
                    mContext.getPackageName());
        } else if (!isNameAndAddressSet()) {
            if (DBG) {
                Slog.d(TAG, "Getting adapter name and address");
            }
            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
            mHandler.sendMessage(getMsg);
        }
    }

handleOnBootPhase()的内容比较单一,根据一些flag判断是否需要enable BT;而enable蓝牙这里是通过触发send msg实现:

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


     case MESSAGE_ENABLE:
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_ENABLE(" + msg.arg1 + "): mBluetooth = " + mBluetooth);
                    }
                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                    mEnable = true;

                    // Use service interface to get the exact state
                    try {
                        mBluetoothLock.readLock().lock();
                        if (mBluetooth != null) { //开机第一次enable,值为null
                            int state = mBluetooth.getState();
                            if (state == BluetoothAdapter.STATE_BLE_ON) {//大部分设备一般都不是ble only mode
                                Slog.w(TAG, "BT Enable in BLE_ON State, going to ON");
                                mBluetooth.onLeServiceUp();
                                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
                                break;
                            }
                        }
                    } catch (RemoteException e) {
                        Slog.e(TAG, "", e);
                    } finally {
                        mBluetoothLock.readLock().unlock();
                    }

                    mQuietEnable = (msg.arg1 == 1);//此时为false
                    if (mBluetooth == null) {//mBluetooth是后面绑定Bt apk中AdapterService时拿到的Binder代理对象;用以把操作bypass到BT核心框架中
                        handleEnable(mQuietEnable);
                    } else {//如果mBluetooth不是null,说明之前已经启动过了;此时是Restart flow,以MESSAGE_RESTART_BLUETOOTH_SERVICE触发
                        //
                        // We need to wait until transitioned to STATE_OFF and
                        // the previous Bluetooth process has exited. The
                        // waiting period has three components:
                        // (a) Wait until the local state is STATE_OFF. This
                        //     is accomplished by "waitForOnOff(false, true)".
                        // (b) Wait until the STATE_OFF state is updated to
                        //     all components.
                        // (c) Wait until the Bluetooth process exits, and
                        //     ActivityManager detects it.
                        // The waiting for (b) and (c) is accomplished by
                        // delaying the MESSAGE_RESTART_BLUETOOTH_SERVICE
                        // message. On slower devices, that delay needs to be
                        // on the order of (2 * SERVICE_RESTART_TIME_MS).
                        //
                        waitForOnOff(false, true);
                        Message restartMsg =
                                mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                        mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
                    }
                    break;

handleEnable()去Bind AdapterService拿到它的Binder句柄:

 private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
......

    private class BluetoothServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            String name = componentName.getClassName();
            if (DBG) {
                Slog.d(TAG, "BluetoothServiceConnection: " + name);
            }
            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
                msg.arg1 = SERVICE_IBLUETOOTH;
            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
                msg.arg1 = SERVICE_IBLUETOOTHGATT;
            } else {
                Slog.e(TAG, "Unknown service connected: " + name);
                return;
            }
            msg.obj = service;
            mHandler.sendMessage(msg);
        }

        public void onServiceDisconnected(ComponentName componentName) {
            // Called if we unexpectedly disconnect.
            String name = componentName.getClassName();
            if (DBG) {
                Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
            }
            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
            if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
                msg.arg1 = SERVICE_IBLUETOOTH;
            } else if (name.equals("com.android.bluetooth.gatt.GattService")) {
                msg.arg1 = SERVICE_IBLUETOOTHGATT;
            } else {
                Slog.e(TAG, "Unknown service disconnected: " + name);
                return;
            }
            mHandler.sendMessage(msg);
        }
    }
......
    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)) {
            Slog.e(TAG, "Fail to bind to: " + intent);
            return false;
        }
        return true;
    }

IBluetooth.class对于的Service声明在Bluetooth apk的manifest xml中:

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

去Bind AdapterService服务,并拿到它的Binder句柄,用以后面操作它的接口。AdapterService的初始化下篇再讲,现在先回到BMS binder成功之后发送MESSAGE_BLUETOOTH_SERVICE_CONNECTED(arg1:SERVICE_IBLUETOOTH)的处理:

case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
                    if (DBG) {
                        Slog.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
                    }

                    IBinder service = (IBinder) msg.obj; //保存Service的onBinder()句柄
                    try {
                        mBluetoothLock.writeLock().lock();
                        if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
                            mBluetoothGatt =
                                    IBluetoothGatt.Stub.asInterface(Binder.allowBlocking(service));
                            continueFromBleOnState();
                            break;
                        } // else must be SERVICE_IBLUETOOTH

                        //Remove timeout
                        mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);

                        mBinding = false;
                        mBluetoothBinder = service;
                        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));//再转成IBluetooth对象

                        if (!isNameAndAddressSet()) {
                            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
                            mHandler.sendMessage(getMsg);
                            if (mGetNameAddressOnly) {
                                return;
                            }
                        }

                        //Register callback object
                        try {
                            mBluetooth.registerCallback(mBluetoothCallback);//mBluetoothCallback用来监听BT的enable状态,如state_on/state_off的状态变化
                        } catch (RemoteException re) {
                            Slog.e(TAG, "Unable to register BluetoothCallback", re);
                        }
                        //Inform BluetoothAdapter instances that service is up
                        sendBluetoothServiceUpCallback();

                        //Do enable request
                        try {
                            if (!mQuietEnable) {
                                if (!mBluetooth.enable()) {//Service bind成功之后,call AdpaterService的enable()接口;做一些初始化动作,并向stack发送enable命令启动蓝牙
                                    Slog.e(TAG, "IBluetooth.enable() returned false");
                                }
                            } else {
                                if (!mBluetooth.enableNoAutoConnect()) {
                                    Slog.e(TAG, "IBluetooth.enableNoAutoConnect() returned false");
                                }
                            }
                        } catch (RemoteException e) {
                            Slog.e(TAG, "Unable to call enable()", e);
                        }
                    } finally {
                        mBluetoothLock.writeLock().unlock();
                    }

                    if (!mEnable) {
                        waitForOnOff(true, false);
                        handleDisable();
                        waitForOnOff(false, false);
                    }
                    break;
                }

主要操作:

  1. 拿到bind服务的onBinder()句柄,并转成IBluetooth类型
  2. 通过IBluetooth类型的obj,调用enable()接口,将flow转到AdapterService中,做一些初始化、并向stack下enable bt的cmd

也要注意到,如果BMS中和AdapterService的连接断掉了,最终会通过MESSAGE_RESTART_BLUETOOTH_SERVICE msg去重新bind它;这在场景可能是由于模组异常导致Bluetooth apk crash(会产生tombstone),与AdapterService的bind连接断掉;这里触发Restart,会导致重走一遍介绍的enable BT流程。

到此,enable BT的flow就从BluetoothManagerService转到AdapterService中了;实际上,通过BluetoothAdapter下来的大部分API调用最终都是call到AdapterService,再通过它下cmd给stack。

AdapterService是蓝牙框架中一个非常重要的服务,它的启动和初始化部分,我们下篇再单独介绍。

PS:

可以看到BT启动过程中有两个常见到的flag:

  1. mEnable:它主要是用来标记系统运行时,蓝牙状态的变化,它有些时候时跟mEnableExternal值一致的。但如果蓝牙的状态是因为某些原因,如stack崩溃,导致蓝牙需要reset、重新启动时,需要靠这个flag来标记这种case的enable/disable状态
  2. mEnableExternal:它主要是记录通过用户手动操作导致的BT使能状态,如通过蓝牙功能按钮来enable/disable BT

猜你喜欢

转载自blog.csdn.net/csdn_of_coder/article/details/103965577