Android9.0 藍牙開啓流程

第一次接觸藍牙,先從藍牙的開啓流程入手吧,藉此順便熟悉一下藍牙的代碼架構。

1、UI

/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java

public void onClick(View v) {
    // send users to scanning settings if they click on the link in the summary text
    new SubSettingLauncher(mContext)
            .setDestination(ScanningSettings.class.getName())
            .setSourceMetricsCategory(MetricsProto.MetricsEvent.BLUETOOTH_FRAGMENT)
            .launch();
}

/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothEnabler.java

public boolean onSwitchToggled(boolean isChecked) {
    if (maybeEnforceRestrictions()) {
        triggerParentPreferenceCallback(isChecked);
        return true;
    }

    // Show toast message if Bluetooth is not allowed in airplane mode
    if (isChecked &&
            !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
        Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
        // Reset switch to off
        mSwitchController.setChecked(false);
        triggerParentPreferenceCallback(false);
        return false;
    }

    mMetricsFeatureProvider.action(mContext, mMetricsEvent, isChecked);

    if (mLocalAdapter != null) {
        boolean status = mLocalAdapter.setBluetoothEnabled(isChecked);
        // If we cannot toggle it ON then reset the UI assets:
        // a) The switch should be OFF but it should still be togglable (enabled = True)
        // b) The switch bar should have OFF text.
        if (isChecked && !status) {
            mSwitchController.setChecked(false);
            mSwitchController.setEnabled(true);
            mSwitchController.updateTitle(false);
            triggerParentPreferenceCallback(false);
            return false;
        }
    }
    mSwitchController.setEnabled(false);
    triggerParentPreferenceCallback(isChecked);
    return true;
}

2、framework

/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java

public boolean setBluetoothEnabled(boolean enabled) {
    boolean success = enabled
            ? mAdapter.enable()
            : mAdapter.disable();

    if (success) {
        setBluetoothStateInt(enabled
            ? BluetoothAdapter.STATE_TURNING_ON
            : BluetoothAdapter.STATE_TURNING_OFF);
    } else {
        if (Utils.V) {
            Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +
                    "success for enabled: " + enabled);
        }

        syncBluetoothState();
    }
    return success;
}

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

@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
 public boolean enable() {
     if (isEnabled()) {
         if (DBG) {
             Log.d(TAG, "enable(): BT already enabled!");
         }
         return true;
     }
     try {
         return mManagerService.enable(ActivityThread.currentPackageName());
     } catch (RemoteException e) {
         Log.e(TAG, "", e);
     }
     return false;
 }

這個方法中的關鍵代碼是“return mManagerService.enable();” mManagerService 對象是由IBluetoothManager 接口代碼實現的,IBluetoothManager實際定義的是AIDL文件,對應的類就是 BluetoothManagerService 類,在路徑 frameworks/base/core/java/android/bluetooth/BluetoothManagerService 下面 。

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

public boolean enable(String packageName) throws RemoteException {
    final int callingUid = Binder.getCallingUid();
    final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID;

    if (isBluetoothDisallowed()) {
        if (DBG) {
            Slog.d(TAG, "enable(): not enabling - bluetooth disallowed");
        }
        return false;
    }

    if (!callerSystem) {
        if (!checkIfCallerIsForegroundUser()) {
            Slog.w(TAG, "enable(): not allowed for non-active and non system user");
            return false;
        }

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                "Need BLUETOOTH ADMIN permission");

        if (!isEnabled() && mPermissionReviewRequired && startConsentUiIfNeeded(packageName,
                callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
            return false;
        }
    }

    if (DBG) {
        Slog.d(TAG, "enable(" + packageName + "):  mBluetooth =" + mBluetooth + " mBinding = "
                + mBinding + " mState = " + BluetoothAdapter.nameForState(mState));
    }

    synchronized (mReceiver) {
        mQuietEnableExternal = false;
        mEnableExternal = true;
        // waive WRITE_SECURE_SETTINGS permission check
        sendEnableMsg(false,
                BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
    }
    if (DBG) {
        Slog.d(TAG, "enable returning");
    }
    return true;
}

方法中先判斷是否是系統app操作藍牙,檢查是否有操作藍牙的權限等,然後關鍵的代碼是“sendEnableMsg(false)”,handler最後調用handleEnable方法處理該消息。

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

    try {
        mBluetoothLock.writeLock().lock();
        if ((mBluetooth == null) && (!mBinding)) {
            //Start bind timeout and bind
            Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
            mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
            Intent i = new Intent(IBluetooth.class.getName());
            if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
                    UserHandle.CURRENT)) {
                mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
            } else {
                mBinding = true;
            }
        } else if (mBluetooth != null) {
            //Enable bluetooth
            try {
                if (!mQuietEnable) {
                    if (!mBluetooth.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();
    }
}

這裏通過AIDL的方式,調用Bluetooth App 中的AdapterService 。先綁定服務,然後註冊Ibluetooth回調函數,之後調用enable方法方法開啓藍牙。所以之後就從Framworks 跳到 Bluetooth APP 中繼續分析。

3、Bluetooth APP

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

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;
}
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;
    }
}

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

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

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

    mRemoteDevices.reset();
    mAdapterProperties.init(mRemoteDevices);

    debugLog("bleOnProcessStart() - Make Bond State Machine");
    mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);

    mJniCallbacks.init(mBondStateMachine, mRemoteDevices);

    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);
}

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

private BondStateMachine(AdapterService service, AdapterProperties prop,
        RemoteDevices remoteDevices) {
    super("BondStateMachine:");
    addState(mStableState);
    addState(mPendingCommandState);
    mRemoteDevices = remoteDevices;
    mAdapterService = service;
    mAdapterProperties = prop;
    mAdapter = BluetoothAdapter.getDefaultAdapter();
    setInitialState(mStableState);
}
private class StableState extends State {
    @Override
    public void enter() {
        infoLog("StableState(): Entering Off State");
    }

    @Override
    public boolean processMessage(Message msg) {

        BluetoothDevice dev = (BluetoothDevice) msg.obj;

        switch (msg.what) {

            case CREATE_BOND:
                OobData oobData = null;
                if (msg.getData() != null) {
                    oobData = msg.getData().getParcelable(OOBDATA);
                }

                createBond(dev, msg.arg1, oobData, true);
                break;
            case REMOVE_BOND:
                removeBond(dev, true);
                break;
            case BONDING_STATE_CHANGE:
                int newState = msg.arg1;
            /* if incoming pairing, transition to pending state */
                if (newState == BluetoothDevice.BOND_BONDING) {
                    sendIntent(dev, newState, 0);
                    transitionTo(mPendingCommandState);
                } else if (newState == BluetoothDevice.BOND_NONE) {
                /* if the link key was deleted by the stack */
                    sendIntent(dev, newState, 0);
                } else {
                    Log.e(TAG, "In stable state, received invalid newState: "
                            + state2str(newState));
                }
                break;

            case CANCEL_BOND:
            default:
                Log.e(TAG, "Received unhandled state: " + msg.what);
                return false;
        }
        return true;
    }
}

通過調用adapterService.enableNative()方法,開始調用JNI方法,進入C/C++層。adapterService.enableNative對應的cpp文件爲
/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

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;
}

通過調用“int ret = sBluetoothInterface->enable()”來驅動底層打開藍牙開關。接下來就是C裏面對打開藍牙的實現。

4、藍牙協議棧

/system/bt/btif/src/bluetooth.cc

static int enable(bool start_restricted) {
  LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted);

  restricted_mode = start_restricted;

  if (!interface_ready()) return BT_STATUS_NOT_READY;

  stack_manager_get_interface()->start_up_stack_async();
  return BT_STATUS_SUCCESS;
}

enable方法會調用start_up_stack_async方法,start_up_stack_async的實現在stack_manager.c 文件中:
/system/bt/btif/src/stack_manager.cc

static void start_up_stack_async(void) {
  thread_post(management_thread, event_start_up_stack, NULL);
}

通過thread_post異步event_start_up_stack,來啓動藍牙棧

static void event_start_up_stack(UNUSED_ATTR void* context) {
  if (stack_is_running) {
    LOG_INFO(LOG_TAG, "%s stack already brought up", __func__);
    return;
  }

  ensure_stack_is_initialized();

  LOG_INFO(LOG_TAG, "%s is bringing up the stack", __func__);
  future_t* local_hack_future = future_new();
  hack_future = local_hack_future;

  // Include this for now to put btif config into a shutdown-able state
  module_start_up(get_module(BTIF_CONFIG_MODULE));
  bte_main_enable();

  if (future_await(local_hack_future) != FUTURE_SUCCESS) {
    LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__);
    stack_is_running = true;  // So stack shutdown actually happens
    event_shut_down_stack(NULL);
    return;
  }

  stack_is_running = true;
  LOG_INFO(LOG_TAG, "%s finished", __func__);
  btif_thread_post(event_signal_stack_up, NULL);
}

bte_main_enable()方法中進行btsnoop_module和hci_module的啓動以及啓動BTU操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章