Android -- Bluetooth startup process analysis of AdapterService

                  Android -- Bluetooth startup process analysis of AdapterService

 

The part that introduced the BluetoothManagerService startup process enable BT earlier mentioned that the final call to process the ENABLE msg is mainly to call to the AdapterService to register the IBluetoothCallback callback to monitor the Bluetooth enable status, and the AdapterService::enable() interface to enable Bluetooth, and this part will continue below look.

AdapterService is a subclass of Service, and Bind service will trigger its life cycle function onCreate() -> onBind() to be called in turn:

public class AdapterService extends Service {
......
    static {
        classInitNative();//native层的init部分
    }
......
    @Override
    public void onCreate() {
        super.onCreate();
        debugLog("onCreate()");
        mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());//重要类型,它实现了接受stack反馈的device信息变化的回调,比如UUID
        mRemoteDevices.init();
        mBinder = new AdapterServiceBinder(this);//AdapterService内部封装的IBluetooth接口实现者
        mAdapterProperties = new AdapterProperties(this);//管理当前Adapter的一些属性,比如配对的device,uuid信息等;有些接口供stack回调上报状态使用
        mAdapterStateMachine = AdapterState.make(this);//一个简单的StateMachine,处理开关BT中间的状态切换
        mJniCallbacks = new JniCallbacks(this, mAdapterProperties);//stack会通过此对象上报一些bt状态和信息
        initNative();//native层的init工作
......
// Phone policy is specific to phone implementations and hence if a device wants to exclude
        // it out then it can be disabled by using the flag below.
        if (getResources().getBoolean(com.android.bluetooth.R.bool.enable_phone_policy)) {
            Log.i(TAG, "Phone policy enabled");
            mPhonePolicy = new PhonePolicy(this, new ServiceFactory());//启动PhonePolicy,它会根据触发重连之前的设备;在available的设备之间处理连接切换等
            mPhonePolicy.start();
        } else {
            Log.i(TAG, "Phone policy disabled");
        }

        mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory());//处理Active Device的管理类;比如Android默认可以连接多个sink设备,但只有一个出声,这个就是active的device;
                                                                                   //要通过AudioManager的接口告知Audio当前系统哪个device是active的,这样Audio系统才能根据策略选择正确的设备播放音频
        mActiveDeviceManager.start();

        setAdapterService(this);//保存当前的AdapterServie实例,因为其他的类里可能要获取它
......
}
......
    @Override
    public IBinder onBind(Intent intent) {
        debugLog("onBind()");
        return mBinder;
    }
......
    /**
     * Handlers for incoming service calls
     */
    private AdapterServiceBinder mBinder;

    /**
     * The Binder implementation must be declared to be a static class, with
     * the AdapterService instance passed in the constructor. Furthermore,
     * when the AdapterService shuts down, the reference to the AdapterService
     * must be explicitly removed.
     *
     * Otherwise, a memory leak can occur from repeated starting/stopping the
     * service...Please refer to android.os.Binder for further details on
     * why an inner instance class should be avoided.
     *
     */
    private static class AdapterServiceBinder extends IBluetooth.Stub {
        private AdapterService mService;

        AdapterServiceBinder(AdapterService svc) {
            mService = svc;
        }

        public void cleanup() {
            mService = null;
        }

        public AdapterService getService() {
            if (mService != null && mService.isAvailable()) {
                return mService;
            }
            return null;
        }

......
        @Override
        public boolean enable() {
            if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) {
                Log.w(TAG, "enable() - Not allowed for non-active user and non system user");
                return false;
            }
            AdapterService service = getService();
            if (service == null) {
                return false;
            }
            return service.enable();
        }
......
}
}
}

It can be seen from the code that the BluetoothManagerService first obtains the IBinder object, and then calls the corresponding method of the AdapterService through it to complete the work. In order to better follow the flow, let's look at the initialization part first; for other details, please refer to the comments:

When the AdapterService class is loaded, the static code block calls that need to be completed:

    static {
        classInitNative();
    }
......
static void classInitNative(JNIEnv* env, jclass clazz) {
  jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
  android_bluetooth_UidTraffic.constructor =
      env->GetMethodID(jniUidTrafficClass, "<init>", "(IJJ)V");

  jclass jniCallbackClass =
      env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
  sJniCallbacksField = env->GetFieldID(
      clazz, "mJniCallbacks", "Lcom/android/bluetooth/btservice/JniCallbacks;");//获取AdapterService中的mJniCallbacks实例,通知上层stack的变化信息

  method_stateChangeCallback =
      env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");//

  method_adapterPropertyChangedCallback = env->GetMethodID(
      jniCallbackClass, "adapterPropertyChangedCallback", "([I[[B)V");
  method_discoveryStateChangeCallback = env->GetMethodID(
      jniCallbackClass, "discoveryStateChangeCallback", "(I)V");

  method_devicePropertyChangedCallback = env->GetMethodID(
      jniCallbackClass, "devicePropertyChangedCallback", "([B[I[[B)V");
  method_deviceFoundCallback =
      env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
  method_pinRequestCallback =
      env->GetMethodID(jniCallbackClass, "pinRequestCallback", "([B[BIZ)V");
  method_sspRequestCallback =
      env->GetMethodID(jniCallbackClass, "sspRequestCallback", "([B[BIII)V");

  method_bondStateChangeCallback =
      env->GetMethodID(jniCallbackClass, "bondStateChangeCallback", "(I[BI)V");

  method_aclStateChangeCallback =
      env->GetMethodID(jniCallbackClass, "aclStateChangeCallback", "(I[BI)V");

  method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
  method_acquireWakeLock =
      env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
  method_releaseWakeLock =
      env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
  method_energyInfo = env->GetMethodID(
      clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");

  if (hal_util_load_bt_library((bt_interface_t const**)&sBluetoothInterface)) {//加载bt stack的so,获取操作句柄sBluetoothInterface;用以调用stack的接口完成操作
    ALOGE("No Bluetooth Library found");
  }
}

This part of the initialization work is very clear from the code; it mainly does two things:

  1. Obtain the callback interface in AdapterService at the Jni layer. When the stack reports the status, it needs to be fed back to the framework layer through these interfaces.
  2. Parse bt so and obtain the interface it exposes to the upper layer, which is used to actually send the operation request of the framework to the protocol stack. It is mainly to operate so and get the operation handle in dlopen mode. The source code part is mainly in Pie_9.0.0_r3\system\bt\main

The bt_interface_t type defines the bt operations that the upper layer will involve. If connect/disconnect, createBond/removeBond, etc., this type will eventually send the request to the protocol stack:

/** Represents the standard Bluetooth DM interface. */
typedef struct {
  /** set to sizeof(bt_interface_t) */
  size_t size;
  /**
   * Opens the interface and provides the callback routines
   * to the implemenation of this interface.
   */
  int (*init)(bt_callbacks_t* callbacks);

  /** Enable Bluetooth. */
  int (*enable)(bool guest_mode);

  /** Disable Bluetooth. */
  int (*disable)(void);

  /** Closes the interface. */
  void (*cleanup)(void);

  /** Remove Bond */
  int (*remove_bond)(const RawAddress* bd_addr);

  /** Cancel Bond */
  int (*cancel_bond)(const RawAddress* bd_addr);

  /**
   * Get the connection status for a given remote device.
   * return value of 0 means the device is not connected,
   * non-zero return status indicates an active connection.
   */
  int (*get_connection_state)(const RawAddress* bd_addr);


  /** Read Energy info details - return value indicates BT_STATUS_SUCCESS or
   * BT_STATUS_NOT_READY Success indicates that the VSC command was sent to
   * controller
   */
  int (*read_energy_info)();

  /**
   * Get the AvrcpTarget Service interface to interact with the Avrcp Service
   */
  bluetooth::avrcp::ServiceInterface* (*get_avrcp_service)(void);
} bt_interface_t;

After the static initialization block is completed, it is the call of Service::onCreate(). In addition to the initialization of some important Java objects mentioned above, it will also initialize some Native layers:

static bool initNative(JNIEnv* env, jobject obj) {
  ALOGV("%s", __func__);

  android_bluetooth_UidTraffic.clazz =
      (jclass)env->NewGlobalRef(env->FindClass("android/bluetooth/UidTraffic"));

  sJniAdapterServiceObj = env->NewGlobalRef(obj);
  sJniCallbacksObj =
      env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));

  if (!sBluetoothInterface) {
    return JNI_FALSE;
  }

  int ret = sBluetoothInterface->init(&sBluetoothCallbacks);//将需要的一些callback函数注册到stack中,这样stack就可以通过这些函数上报此类事件
  if (ret != BT_STATUS_SUCCESS) {
    ALOGE("Error while setting the callbacks: %d\n", ret);
    sBluetoothInterface = NULL;
    return JNI_FALSE;
  }
  ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);//将需要的一些callback函数注册到stack中,这样stack就可以通过这些函数上报此类事件
  if (ret != BT_STATUS_SUCCESS) {
    ALOGE("Error while setting Bluetooth callouts: %d\n", ret);
    sBluetoothInterface->cleanup();
    sBluetoothInterface = NULL;
    return JNI_FALSE;
  }
......
static bt_callbacks_t sBluetoothCallbacks = {
    sizeof(sBluetoothCallbacks), adapter_state_change_callback,
    adapter_properties_callback, remote_device_properties_callback,
    device_found_callback,       discovery_state_changed_callback,
    pin_request_callback,        ssp_request_callback,
    bond_state_changed_callback, acl_state_changed_callback,
    callback_thread_event,       dut_mode_recv_callback,
    le_test_mode_recv_callback,  energy_info_recv_callback};
......
static bt_os_callouts_t sBluetoothOsCallouts = {
    sizeof(sBluetoothOsCallouts), set_wake_alarm_callout,
    acquire_wake_lock_callout, release_wake_lock_callout,
};

Register some callback functions that the stack needs to use to it, so that when needed, the stack can feed back information to the upper layer by calling these functions.

After this path is connected, look back at AdapterService::enable():

    public synchronized boolean enable(boolean quietMode) {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");

        // Enforce the user restriction for disallowing Bluetooth if it was set.
        if (mUserManager.hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM)) {
            debugLog("enable() called when Bluetooth was disallowed");
            return false;
        }

        debugLog("enable() - Enable called with quiet mode status =  " + quietMode);
        mQuietmode = quietMode;
        mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);
        return true;
    }

It can be seen that it simply sends a BLE_TURN_ON msg to AdapterState, and randomly enters the state machine for processing;

/**
 * This state machine handles Bluetooth Adapter State.
 * Stable States:
 *      {@link OffState}: Initial State
 *      {@link BleOnState} : Bluetooth Low Energy, Including GATT, is on
 *      {@link OnState} : Bluetooth is on (All supported profiles)
 *
 * Transition States:
 *      {@link TurningBleOnState} : OffState to BleOnState
 *      {@link TurningBleOffState} : BleOnState to OffState
 *      {@link TurningOnState} : BleOnState to OnState
 *      {@link TurningOffState} : OnState to BleOnState
 *
 *        +------   Off  <-----+
 *        |                    |
 *        v                    |
 * TurningBleOn   TO--->   TurningBleOff
 *        |                  ^ ^
 *        |                  | |
 *        +----->        ----+ |
 *                 BleOn       |
 *        +------        <---+ O
 *        v                  | T
 *    TurningOn  TO---->  TurningOff
 *        |                    ^
 *        |                    |
 *        +----->   On   ------+
 *
 */

From the comments and code of AdapterState above, we know the following points:

  1. The parent class of all States in AdapterState is BaseAdapterState, so when entering a state machine, the enter() interface of this parent class will be called first; at the same time, when exiting a state machine, the exit of this parent class will also be called ()interface
  2. The default initialization state is Off state, that is, BT has not been started at this time
  3. Because AdapterState is the main part of logic that manages BT startup, it is more reasonable to notify the outside of the current BT enabling process. It should be triggered here

Because in a state node, we should all notify the state to the outside, so this part is encapsulated into the parent class State:

AdapterState:
    private abstract class BaseAdapterState extends State {

        abstract int getStateValue();

        @Override
        public void enter() {
            int currState = getStateValue();
            infoLog("entered ");
            mAdapterService.updateAdapterState(mPrevState, currState);//通过AdapterService向外通知BT使能的状态信息
            mPrevState = currState;
        }
......
    }

AdapterService:
    void updateAdapterState(int prevState, int newState) {//如果某个服务对蓝牙启动状态过程感兴趣,它就应该注册IBluetootCallback对象;跟BluetoothManagerService一样
        mAdapterProperties.setState(newState);
        if (mCallbacks != null) {
            int n = mCallbacks.beginBroadcast();
            debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState(
                    newState) + " to " + n + " receivers.");
            for (int i = 0; i < n; i++) {
                try {
                    mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);//调用onBluetoothStateChange()回调状态变化
                } catch (RemoteException e) {
                    debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")");
                }
            }
            mCallbacks.finishBroadcast();
        }
......
    }

BluetoothManagerService:
    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);//发送MESSAGE_BLUETOOTH_STATE_CHANGE
            mHandler.sendMessage(msg);
        }
    };

Here we send BLE_TURN_ON msg, see its processing:

    private class OffState extends BaseAdapterState {

        @Override
        int getStateValue() {
            return BluetoothAdapter.STATE_OFF;
        }

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case BLE_TURN_ON:
                    transitionTo(mTurningBleOnState);
                    break;

                default:
                    infoLog("Unhandled message - " + messageString(msg.what));
                    return false;
            }
            return true;
        }
    }
......
 private class TurningBleOnState extends BaseAdapterState {

        @Override
        int getStateValue() {
            return BluetoothAdapter.STATE_BLE_TURNING_ON;
        }

        @Override
        public void enter() {
            super.enter();
            sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
            mAdapterService.bringUpBle();
        }

        @Override
        public void exit() {
            removeMessages(BLE_START_TIMEOUT);
            super.exit();
        }

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case BLE_STARTED:
                    transitionTo(mBleOnState);
                    break;

                case BLE_START_TIMEOUT:
                    errorLog(messageString(msg.what));
                    transitionTo(mTurningBleOffState);
                    break;

                default:
                    infoLog("Unhandled message - " + messageString(msg.what));
                    return false;
            }
            return true;
        }
    }
......
    }

The message processing of BLE_TURN_ON is transferTo TurningBleOnState, and its enter() will call mAdapterService.bringUpBle():

    void bringUpBle() {
        debugLog("bleOnProcessStart()");

        if (getResources().getBoolean(
                R.bool.config_bluetooth_reload_supported_profiles_when_enabled)) {
            Config.init(getApplicationContext());
        }

        // Reset |mRemoteDevices| whenever BLE is turned off then on
        // This is to replace the fact that |mRemoteDevices| was
        // reinitialized in previous code.
        //
        // TODO(apanicke): The reason is unclear but
        // I believe it is to clear the variable every time BLE was
        // turned off then on. The same effect can be achieved by
        // calling cleanup but this may not be necessary at all
        // We should figure out why this is needed later
        mRemoteDevices.reset();//RemoteDeivces管理对端设备的一些信息
        mAdapterProperties.init(mRemoteDevices);//AdapterProperties管理当前Adapter的一些信息

        debugLog("bleOnProcessStart() - Make Bond State Machine");
        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);//创建BondStateMachine对象,它负责管理一个device的配对过程

        mJniCallbacks.init(mBondStateMachine, mRemoteDevices);//JniCallbacks主要负责监听来自stack的callback信息,如设备配对状态或设备更新UUID变化时,framework就可以收到回调

        try {
            mBatteryStats.noteResetBleScan();
        } catch (RemoteException e) {
            Log.w(TAG, "RemoteException trying to send a reset to BatteryStats");
        }
        StatsLog.write_non_chained(StatsLog.BLE_SCAN_STATE_CHANGED, -1, null,
                StatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, false, false, false);

        //Start Gatt service
        setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);//启动GattService服务,BLE设备需要GATT协议交换信息
    }

In addition to creating some important objects, here is mainly to play GattService, Ble devices need to exchange information through the GATT protocol; others can refer to the above notes.

The Profile services declared by the Bluetooth framework are basically subclasses of ProfileService, so referring to the startup process of Android Service, when a Profile starts, the method of ProfileService will be called:

/**
 * Base class for a background service that runs a Bluetooth profile
 */
public abstract class ProfileService extends Service {


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
            ......
            if (state == BluetoothAdapter.STATE_OFF) {
                doStop();//通知AdapterService的此Profile停止成功
            } else if (state == BluetoothAdapter.STATE_ON) {
                doStart();//通知AdapterService的此Profile启动成功
            }
        }
        return PROFILE_SERVICE_MODE;
    }

 private void doStart() {
        ......
        mAdapterService.addProfile(this);//告知AdapterService此Profile启动成功,更新Profile集合

        ......
        mAdapterService.onProfileServiceStateChanged(this, BluetoothAdapter.STATE_ON);//通知AdapterService此Profile已启动
    }

    private void doStop() {
        ......
        if (mAdapterService != null) {
            mAdapterService.onProfileServiceStateChanged(this, BluetoothAdapter.STATE_OFF);//通知AdapterService此Profile已停止
        }
        if (!stop()) {
            Log.e(mName, "Unable to stop profile");
        }
        if (mAdapterService != null) {
            mAdapterService.removeProfile(this);//告知AdapterService此Profile停止成功,更新Profile集合
        }
        ......
        stopSelf();
    }
}

Then look at the processing of AdapterService:

/**
     * Register a {@link ProfileService} with AdapterService.
     *
     * @param profile the service being added.
     */
    public void addProfile(ProfileService profile) {
        mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_REGISTERED, profile).sendToTarget();
    }

    /**
     * Unregister a ProfileService with AdapterService.
     *
     * @param profile the service being removed.
     */
    public void removeProfile(ProfileService profile) {
        mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED, profile).sendToTarget();
    }

    /**
     * Notify AdapterService that a ProfileService has started or stopped.
     *
     * @param profile the service being removed.
     * @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF}
     */
    public void onProfileServiceStateChanged(ProfileService profile, int state) {
        if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
            throw new IllegalArgumentException(BluetoothAdapter.nameForState(state));
        }
        Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
        m.obj = profile;
        m.arg1 = state;
        mHandler.sendMessage(m);
    }

    private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED = 1;
    private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2;
    private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3;

    class AdapterServiceHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            debugLog("handleMessage() - Message: " + msg.what);

            switch (msg.what) {
                case MESSAGE_PROFILE_SERVICE_STATE_CHANGED:
                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");
                    processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1);
                    break;
                case MESSAGE_PROFILE_SERVICE_REGISTERED:
                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_REGISTERED");
                    registerProfileService((ProfileService) msg.obj);
                    break;
                case MESSAGE_PROFILE_SERVICE_UNREGISTERED:
                    debugLog("handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED");
                    unregisterProfileService((ProfileService) msg.obj);
                    break;
            }
        }

        private void registerProfileService(ProfileService profile) {
            if (mRegisteredProfiles.contains(profile)) {
                Log.e(TAG, profile.getName() + " already registered.");
                return;
            }
            mRegisteredProfiles.add(profile);
        }

        private void unregisterProfileService(ProfileService profile) {
            if (!mRegisteredProfiles.contains(profile)) {
                Log.e(TAG, profile.getName() + " not registered (UNREGISTERED).");
                return;
            }
            mRegisteredProfiles.remove(profile);
        }

        private void processProfileServiceStateChanged(ProfileService profile, int state) {
            switch (state) {
                case BluetoothAdapter.STATE_ON://此时是启动GattService,所以是STATE_ON
                    if (!mRegisteredProfiles.contains(profile)) {
                        Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
                        return;
                    }
                    if (mRunningProfiles.contains(profile)) {//防止重复启动某个Profile
                        Log.e(TAG, profile.getName() + " already running.");
                        return;
                    }
                    mRunningProfiles.add(profile);
                    if (GattService.class.getSimpleName().equals(profile.getName())) {
                        enableNativeWithGuestFlag();//如果是启动Gatt profile,则向stack下发enable bt的指令
                    } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
                            && mRegisteredProfiles.size() == mRunningProfiles.size()) {//这里是启动Gatt以外的,在config.xml中声明支持的其他Profile;相当于启动BREDR mode
                        mAdapterProperties.onBluetoothReady();
                        updateUuids();
                        setBluetoothClassFromConfig();
                        mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
                    }
                    break;
                case BluetoothAdapter.STATE_OFF:
                    if (!mRegisteredProfiles.contains(profile)) {
                        Log.e(TAG, profile.getName() + " not registered (STATE_OFF).");
                        return;
                    }
                    if (!mRunningProfiles.contains(profile)) {
                        Log.e(TAG, profile.getName() + " not running.");
                        return;
                    }
                    mRunningProfiles.remove(profile);
                    // If only GATT is left, send BREDR_STOPPED.
                    if ((mRunningProfiles.size() == 1 && (GattService.class.getSimpleName()
                            .equals(mRunningProfiles.get(0).getName())))) {
                        mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED);
                    } else if (mRunningProfiles.size() == 0) {
                        disableNative();
                        mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
                    }
                    break;
                default:
                    Log.e(TAG, "Unhandled profile state: " + state);
            }
        }
    }

Handle enable bluetooth:

    private void enableNativeWithGuestFlag() {
        boolean isGuest = UserManager.get(this).isGuestUser();
        if (!enableNative(isGuest)) {
            Log.e(TAG, "enableNative() returned false");
        }
    }

static jboolean enableNative(JNIEnv* env, jobject obj, jboolean isGuest) {
  ALOGV("%s", __func__);

  if (!sBluetoothInterface) return JNI_FALSE;
  int ret = sBluetoothInterface->enable(isGuest == JNI_TRUE ? 1 : 0);
  return (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE
                                                             : JNI_FALSE;
}

As mentioned above, the state callback of the stack will be called back through the JNICallbacks object, and the enable state is also the same:

final class JniCallbacks {

    void stateChangeCallback(int status) {
        mAdapterService.stateChangeCallback(status);
    }
}


AdapterService:
    void stateChangeCallback(int status) {
        if (status == AbstractionLayer.BT_STATE_OFF) {
            debugLog("stateChangeCallback: disableNative() completed");
        } else if (status == AbstractionLayer.BT_STATE_ON) {//BT State on
            mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED);
        } else {
            Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback");
        }
    }

After BT is started, it notifies AdapterState of the state, and after TurningBleOnState receives the message, it will enter BleOnState; and external notification of state changes, as introduced earlier, is processed through the AdapterService::updateAdapterState() function:

    void updateAdapterState(int prevState, int newState) {//如果某个服务对蓝牙启动状态过程感兴趣,它就应该注册IBluetootCallback对象;跟BluetoothManagerService一样
        mAdapterProperties.setState(newState);
        if (mCallbacks != null) {
            int n = mCallbacks.beginBroadcast();
            debugLog("updateAdapterState() - Broadcasting state " + BluetoothAdapter.nameForState(
                    newState) + " to " + n + " receivers.");
            for (int i = 0; i < n; i++) {
                try {
                    mCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState);//调用onBluetoothStateChange()回调状态变化
                } catch (RemoteException e) {
                    debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")");
                }
            }
            mCallbacks.finishBroadcast();
        }
        // Turn the Adapter all the way off if we are disabling and the snoop log setting changed.
        if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON) {
            mSnoopLogSettingAtEnable =
                    SystemProperties.getBoolean(BLUETOOTH_BTSNOOP_ENABLE_PROPERTY, false);
        } else if (newState == BluetoothAdapter.STATE_BLE_ON
                   && prevState != BluetoothAdapter.STATE_OFF) {
            boolean snoopLogSetting =
                    SystemProperties.getBoolean(BLUETOOTH_BTSNOOP_ENABLE_PROPERTY, false);
            if (mSnoopLogSettingAtEnable != snoopLogSetting) {
                mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
            }
        }
    }

When introducing BluetoothManagerService, we mentioned that BMS will register a callback with AdapterService to monitor the status of BT:

    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);//发送MESSAGE_BLUETOOTH_STATE_CHANGE
            mHandler.sendMessage(msg);
        }
    };

Handle Msg:

                case MESSAGE_BLUETOOTH_STATE_CHANGE: {
                    int prevState = msg.arg1;
                    int newState = msg.arg2;
                    if (DBG) {
                        Slog.d(TAG,
                                "MESSAGE_BLUETOOTH_STATE_CHANGE: " + BluetoothAdapter.nameForState(
                                        prevState) + " > " + BluetoothAdapter.nameForState(
                                        newState));
                    }
                    mState = newState;
                    bluetoothStateChangeHandler(prevState, newState);//处理state变化
                    ......
                }

Look at the main processing of bluetoothStateChangeHandler():

        // Notify all proxy objects first of adapter state change
        if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
            boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
                    && newState == BluetoothAdapter.STATE_BLE_ON);

            if (newState == BluetoothAdapter.STATE_OFF) {
                // If Bluetooth is off, send service down event to proxy objects, and unbind
                if (DBG) {
                    Slog.d(TAG, "Bluetooth is complete send Service Down");
                }
                sendBluetoothServiceDownCallback();
                unbindAndFinish();
                sendBleStateChanged(prevState, newState);
                // Don't broadcast as it has already been broadcast before
                isStandardBroadcast = false;

            } else if (!intermediate_off) {//现在state是BLE_ON
                // connect to GattService
                if (DBG) {
                    Slog.d(TAG, "Bluetooth is in LE only mode");
                }
                if (mBluetoothGatt != null || !mContext.getPackageManager()
                            .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {//此时GattService只是启动了,BMS还未拿到它的Binder操作句柄
                    continueFromBleOnState();
                } else {
                    if (DBG) {
                        Slog.d(TAG, "Binding Bluetooth GATT service");
                    }
                    Intent i = new Intent(IBluetoothGatt.class.getName());
                    doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                            UserHandle.CURRENT);//这里去Bind GattService,然后在BluetoothServiceConnection中触发MESSAGE_BLUETOOTH_SERVICE_CONNECTED msg,并区分是SERVICE_IBLUETOOTHGATT
                }
                sendBleStateChanged(prevState, newState);
                //Don't broadcase this as std intent
                isStandardBroadcast = false;

            } else if (intermediate_off) {
                if (DBG) {
                    Slog.d(TAG, "Intermediate off, back to LE only mode");
                }
                // For LE only mode, broadcast as is
                sendBleStateChanged(prevState, newState);
                sendBluetoothStateCallback(false); // BT is OFF for general users
                // Broadcast as STATE_OFF
                newState = BluetoothAdapter.STATE_OFF;
                sendBrEdrDownCallback();
            }
        } 

The content of Bind Profile in BluetoothManagerService is the same as that introduced before, let's directly look at the processing:

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));//获取GattService的句柄
                            continueFromBleOnState();//启动BREDR的profile
                            break;
                        } // else must be SERVICE_IBLUETOOTH
}

Get the Binder handle of the Gatt profile, and call continueFromBleOnState() to start other profiles:

    /**
     * Call IBluetooth.onLeServiceUp() to continue if Bluetooth should be on.
     */
    private void continueFromBleOnState() {
        if (DBG) {
            Slog.d(TAG, "continueFromBleOnState()");
        }
        try {
            mBluetoothLock.readLock().lock();
            if (mBluetooth == null) {
                Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!");
                return;
            }
            if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) {
                // This triggers transition to STATE_ON
                mBluetooth.onLeServiceUp();//调用onLeServiceUp()
                persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Unable to call onServiceUp", e);
        } finally {
            mBluetoothLock.readLock().unlock();
        }
    }


AdapterService:
    void onLeServiceUp() {
        mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);//发送USER_TURN_ON
    }

//现在处于BleOnState,处理此消息进入TurningOnState
AdapterState:

    private class TurningOnState extends BaseAdapterState {

        @Override
        int getStateValue() {
            return BluetoothAdapter.STATE_TURNING_ON;
        }

        @Override
        public void enter() {
            super.enter();
            sendMessageDelayed(BREDR_START_TIMEOUT, BREDR_START_TIMEOUT_DELAY);
            mAdapterService.startProfileServices();
        }
        ......
}

//启动配置文件中定义的Profile:
AdapterService:
    void startProfileServices() {
        debugLog("startCoreServices()");
        Class[] supportedProfileServices = Config.getSupportedProfiles();
        if (supportedProfileServices.length == 1 && GattService.class.getSimpleName()
                .equals(supportedProfileServices[0].getSimpleName())) {
            mAdapterProperties.onBluetoothReady();
            updateUuids();
            setBluetoothClassFromConfig();
            mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
        } else {
            setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
        }
    }

The final process is to start all the Profiles defined in the config.xml of Bluetooth.apk, and the Profile set obtained by calling Config.getSupportedProfiles() is the Service that declares true:

    <bool name="profile_supported_a2dp">true</bool>
    <bool name="profile_supported_a2dp_sink">false</bool>
    <bool name="profile_supported_hdp">true</bool>
    <bool name="profile_supported_hs_hfp">true</bool>
    <bool name="profile_supported_hfpclient">false</bool>
    <bool name="profile_supported_hid_host">true</bool>
    <bool name="profile_supported_opp">true</bool>
    <bool name="profile_supported_pan">true</bool>
    <bool name="profile_supported_pbap">true</bool>
    <bool name="profile_supported_gatt">true</bool>
    <bool name="pbap_include_photos_in_vcard">true</bool>
    <bool name="pbap_use_profile_for_owner_vcard">true</bool>
    <bool name="profile_supported_map">true</bool>
    <bool name="profile_supported_avrcp_target">true</bool>
    <bool name="profile_supported_avrcp_controller">false</bool>
    <bool name="profile_supported_sap">false</bool>
    <bool name="profile_supported_pbapclient">false</bool>
    <bool name="profile_supported_mapmce">false</bool>
    <bool name="profile_supported_hid_device">true</bool>
    <bool name="profile_supported_hearing_aid">false</bool>

setAllProfileServiceStates() is to start all these supported Profiles in the state of STATE_ON, and they are also subclasses of ProfileService:

    private void setAllProfileServiceStates(Class[] services, int state) {
        for (Class service : services) {
            if (GattService.class.getSimpleName().equals(service.getSimpleName())) {
                continue;
            }
            setProfileServiceState(service, state);
        }
    }

So similar to the flow started by GattService, AdapterService will handle the status changes of these Profiles, here is STATE_ON:

        private void processProfileServiceStateChanged(ProfileService profile, int state) {
            switch (state) {
                case BluetoothAdapter.STATE_ON://此时是启动GattService,所以是STATE_ON
                    if (!mRegisteredProfiles.contains(profile)) {
                        Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
                        return;
                    }
                    if (mRunningProfiles.contains(profile)) {//防止重复启动某个Profile
                        Log.e(TAG, profile.getName() + " already running.");
                        return;
                    }
                    mRunningProfiles.add(profile);
                    if (GattService.class.getSimpleName().equals(profile.getName())) {
                        enableNativeWithGuestFlag();//如果是启动Gatt profile,则向stack下发enable bt的指令
                    } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
                            && mRegisteredProfiles.size() == mRunningProfiles.size()) {//这里是启动Gatt以外的,在config.xml中声明支持的其他Profile;相当于启动BREDR mode
                        mAdapterProperties.onBluetoothReady();//Profile全部启动完成,初始化变化,并设置当前Bt工作的mode
                        updateUuids();//更新UUID
                        setBluetoothClassFromConfig();
                        mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);//通知AdapterState,随即进入OnState;BT启动成功
                    }
                    break;
......
}

mRegisteredProfiles and mRunningProfiles will eventually be consistent with the Profile declared by config, and then continue to do some setting work, among which we may be more concerned about setting the current Bluetooth working mode:

    void onBluetoothReady() {
        debugLog("onBluetoothReady, state=" + BluetoothAdapter.nameForState(getState())
                + ", ScanMode=" + mScanMode);

        synchronized (mObject) {
            // Reset adapter and profile connection states
            setConnectionState(BluetoothAdapter.STATE_DISCONNECTED);
            mProfileConnectionState.clear();
            mProfilesConnected = 0;
            mProfilesConnecting = 0;
            mProfilesDisconnecting = 0;
            // adapterPropertyChangedCallback has already been received.  Set the scan mode.
            setScanMode(AbstractionLayer.BT_SCAN_MODE_CONNECTABLE);//当前设备可以扫描和连接其他设备,其他设备无法扫描到当前设备
            // This keeps NV up-to date on first-boot after flash.
            setDiscoverableTimeout(mDiscoverableTimeout);//设置扫描的超时时长
        }
    }

We can set the desired Bluetooth working mode and scan timeout here, so that the Bluetooth startup work is basically over.

Guess you like

Origin blog.csdn.net/csdn_of_coder/article/details/104169113