国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android藍(lán)牙使能流程圖(Android Bluetooth enable) -- java & jni層

這篇具有很好參考價值的文章主要介紹了Android藍(lán)牙使能流程圖(Android Bluetooth enable) -- java & jni層。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

在介紹Android enable流程之前,我們首先來看下Android的流程圖

Android藍(lán)牙使能流程圖(Android Bluetooth enable) -- java & jni層

以上圖示是android8以上的,主要跟Android8之前的架構(gòu)在于Bluetooth stack跟vendor層之間增加一層HIDL,主要是抽象硬件層的作用

OK,回歸主題,我們來看下Android的enable流程,首先上一張架構(gòu)圖

Android藍(lán)牙使能流程圖(Android Bluetooth enable) -- java & jni層

另外聲明下:我們做了一些列的藍(lán)牙教程(包括視頻)。我們會以連載的方式持續(xù)更新,內(nèi)容如下:

本專欄文章我們會以連載的方式持續(xù)更新,本專欄計劃更新內(nèi)容如下:

Android藍(lán)牙使能流程圖(Android Bluetooth enable) -- java & jni層

第一篇:藍(lán)牙綜合介紹 ,主要介紹藍(lán)牙的一些概念,產(chǎn)生背景,發(fā)展軌跡,市面藍(lán)牙介紹,以及藍(lán)牙開發(fā)板介紹。

第二篇:Transport層介紹,主要介紹藍(lán)牙協(xié)議棧跟藍(lán)牙芯片之前的硬件傳輸協(xié)議,比如基于UART的H4,H5,BCSP,基于USB的H2等

第三篇:傳統(tǒng)藍(lán)牙controller介紹,主要介紹傳統(tǒng)藍(lán)牙芯片的介紹,包括射頻層(RF),基帶層(baseband),鏈路管理層(LMP)等

第四篇:傳統(tǒng)藍(lán)牙host介紹,主要介紹傳統(tǒng)藍(lán)牙的協(xié)議棧,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的協(xié)議吧。

第五篇:低功耗藍(lán)牙controller介紹,主要介紹低功耗藍(lán)牙芯片,包括物理層(PHY),鏈路層(LL)

第六篇:低功耗藍(lán)牙host介紹,低功耗藍(lán)牙協(xié)議棧的介紹,包括HCI,L2CAP,ATT,GATT,SM等

第七篇:藍(lán)牙芯片介紹,主要介紹一些藍(lán)牙芯片的初始化流程,基于HCI vendor command的擴(kuò)展

第八篇:附錄,主要介紹以上常用名詞的介紹以及一些特殊流程的介紹等。

另外,開發(fā)板如下所示,對于想學(xué)習(xí)藍(lán)牙協(xié)議棧的最好人手一套。以便更好的學(xué)習(xí)藍(lán)牙協(xié)議棧,相信我,學(xué)完這一套視頻你將擁有修改任何協(xié)議棧的能力(比如Linux下的bluez,Android下的bluedroid)。

-------------------------------------------------------------------------------------------------------------------------

藍(lán)牙視頻教程(跟韋東山老師合作):https://item.taobao.com/item.htm?spm=a1z10.5-c-s.w4002-22329603914.10.77201fc98qgCWh&id=679276693032

藍(lán)牙交流扣扣群:970324688

Github代碼:GitHub - sj15712795029/bluetooth_stack: 這是一個開源的雙模藍(lán)牙協(xié)議棧(bluetooth.stack)(btstack),可以運行在STM32,Linux.,包含HCI,L2CAP,SDP,RFCOMM,HFP,SPP,A2DP,AVRCP,AVDTP,AVCTP,OBEX,PBAP等協(xié)議,后續(xù)會繼續(xù)維護(hù),以達(dá)到商用的目的

入手開發(fā)板:https://shop220811498.taobao.com/category-1542116976.htm?spm=a1z10.5-c-s.w4010-22329603913.7.39ca7dbe2EA0K3&search=y&catName=%C0%B6%D1%C0%BF%AA%B7%A2%B0%E5#bd

藍(lán)牙學(xué)習(xí)目錄:一篇文章足夠你學(xué)習(xí)藍(lán)牙技術(shù),提供史上最全的藍(lán)牙技術(shù)(傳統(tǒng)藍(lán)牙/低功耗藍(lán)牙)文章總結(jié),文檔下載總結(jié)(2020/12/11更新)_Wireless_Link的博客-CSDN博客_藍(lán)牙eir

--------------------------------------------------------------------------------------------------------------------------

步驟1:開機(jī)會啟動SystemServer類的main函數(shù)

在Android系統(tǒng)啟動過程中,SystemServer是第一個被啟動的進(jìn)程。當(dāng)Android設(shè)備被開機(jī)后,內(nèi)核會創(chuàng)建一個名為init的進(jìn)程,init進(jìn)程會啟動Zygote進(jìn)程,Zygote進(jìn)程會啟動SystemServer進(jìn)程。因此,SystemServer是整個Android系統(tǒng)啟動的核心進(jìn)程,它負(fù)責(zé)初始化并啟動大部分系統(tǒng)服務(wù)和應(yīng)用程序,是整個Android系統(tǒng)的主要啟動入口。

具體來說,SystemServer主要完成以下幾個任務(wù):

  • 啟動和初始化系統(tǒng)服務(wù):SystemServer會啟動和初始化大部分系統(tǒng)服務(wù),例如ActivityManagerService、WindowManagerService、PackageManagerService、PowerManagerService等等。這些服務(wù)會在啟動過程中被創(chuàng)建并注冊到系統(tǒng)服務(wù)中心,供其他應(yīng)用程序和服務(wù)調(diào)用。

  • 啟動和初始化核心應(yīng)用程序:SystemServer會啟動和初始化Android系統(tǒng)中的核心應(yīng)用程序,例如SystemUI、Settings等等。這些應(yīng)用程序會在啟動過程中被創(chuàng)建并運行,提供各種用戶界面和功能。

  • 加載和初始化系統(tǒng)屬性:SystemServer會加載和初始化/system/build.prop文件中定義的系統(tǒng)屬性,例如設(shè)備型號、廠商信息等等。這些屬性可以在系統(tǒng)運行時被訪問和修改。

  • 啟動Adb守護(hù)進(jìn)程:SystemServer會啟動Adb守護(hù)進(jìn)程,使得開發(fā)者可以通過adb工具來訪問設(shè)備。

總之,SystemServer是整個Android系統(tǒng)啟動過程中的核心進(jìn)程,負(fù)責(zé)啟動和初始化大部分系統(tǒng)服務(wù)和應(yīng)用程序,為整個系統(tǒng)的運行提供基礎(chǔ)支持。SystemServer的啟動時間通常在內(nèi)核啟動之后的幾秒鐘內(nèi),具體時間取決于設(shè)備的硬件性能和系統(tǒng)配置。

/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
    new SystemServer().run();
}

SystemServer().run();執(zhí)行startOtherServices(t);

然后startOtherServices(t);執(zhí)行如下代碼,開啟Bluetooth service類

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
    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 {
        t.traceBegin("StartBluetoothService");
        mSystemServiceManager.startService(BluetoothService.class);
        t.traceEnd();
    }
    ...
}

步驟2:BluetoothService構(gòu)造函數(shù)中執(zhí)行創(chuàng)建BluetoothManagerService

mBluetoothManagerService = new BluetoothManagerService(context);

BluetoothManagerService(Context context) {

        Slog.e(TAG, "new BluetoothManagerService");

        // BluetoothManagerService的私有類,主要用于處理一些message
        mHandler = new BluetoothHandler(IoThread.get().getLooper()); 

        mContext = context;

        mWirelessConsentRequired = context.getResources()
                .getBoolean(com.android.internal.R.bool.config_wirelessConsentRequired);

        mCrashes = 0;
        mBluetooth = null;
        mBluetoothBinder = null;
        mBluetoothGatt = null;
        mBinding = false;
        mUnbinding = false;
        mEnable = false;
        mState = BluetoothAdapter.STATE_OFF;
        mQuietEnableExternal = false;
        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>();

        mIsHearingAidProfileSupported = context.getResources()
                .getBoolean(com.android.internal.R.bool.config_hearing_aid_profile_supported);

        // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils
        String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS);
        if (!TextUtils.isEmpty(value)) {
            boolean isHearingAidEnabled = Boolean.parseBoolean(value);
            Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled);
            FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled);
            if (isHearingAidEnabled && !mIsHearingAidProfileSupported) {
                // Overwrite to enable support by FeatureFlag
                mIsHearingAidProfileSupported = true;
            }
        }

        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
        filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
        filter.addAction(Intent.ACTION_SETTING_RESTORED);
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(mReceiver, filter);

        loadStoredNameAndAddress();
        if (isBluetoothPersistedStateOn()) {
            if (DBG) {
                Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
            }
            mEnableExternal = true;
        }

        String airplaneModeRadios =
                Settings.Global.getString(mContentResolver, Settings.Global.AIRPLANE_MODE_RADIOS);
        if (airplaneModeRadios == null || airplaneModeRadios.contains(
                Settings.Global.RADIO_BLUETOOTH)) {
            mBluetoothAirplaneModeListener = new BluetoothAirplaneModeListener(
                    this, IoThread.get().getLooper(), context);
        }

        int systemUiUid = -1;
        // Check if device is configured with no home screen, which implies no SystemUI.
        boolean noHome = mContext.getResources().getBoolean(R.bool.config_noHomeScreen);
        if (!noHome) {
            PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
            systemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
                    MATCH_SYSTEM_ONLY, USER_SYSTEM);
        }
        if (systemUiUid >= 0) {
            Slog.d(TAG, "Detected SystemUiUid: " + Integer.toString(systemUiUid));
        } else {
            // Some platforms, such as wearables do not have a system ui.
            Slog.w(TAG, "Unable to resolve SystemUI's UID.");
        }
        mSystemUiUid = systemUiUid;
    }

步驟3:啟動默認(rèn)用戶調(diào)用的方法處理

public void onSwitchUser(int userHandle) {
    if (!mInitialized) {
        initialize();
    } else {
        mBluetoothManagerService.handleOnSwitchUser(userHandle);
    }
}

onSwitchUser 是 Android 框架中的一個回調(diào)方法,用于在用戶切換時接收通知。當(dāng)有多個用戶在同一個設(shè)備上使用時,可以使用此方法來執(zhí)行一些特定于用戶的操作,例如切換到其它用戶時保存當(dāng)前用戶的狀態(tài)并加載新用戶的數(shù)據(jù)。

在 Android 系統(tǒng)中,只有在設(shè)備啟用多用戶功能并啟用多個用戶帳戶時才會調(diào)用此方法。在單用戶設(shè)備上,該方法不會被調(diào)用。

當(dāng)一個用戶從其它用戶切換到當(dāng)前用戶時,系統(tǒng)會調(diào)用 onSwitchUser 方法。

當(dāng)設(shè)備啟動時,如果已經(jīng)啟用了多用戶功能,則系統(tǒng)會自動創(chuàng)建一個默認(rèn)的用戶,并在該用戶的環(huán)境下啟動應(yīng)用程序。此時,onSwitchUser 方法也會被調(diào)用,此時傳遞給方法的 userId 參數(shù)為默認(rèn)用戶的 ID。

備注:該方法已經(jīng)在 Android 12 中被標(biāo)記為過時。因此,在新的應(yīng)用程序中,應(yīng)該避免使用該方法,而應(yīng)該考慮使用更現(xiàn)代的 Android 架構(gòu)組件或 API 來實現(xiàn)多用戶管理和數(shù)據(jù)保護(hù)。

private void initialize() {
    if (!mInitialized) {
        mBluetoothManagerService.handleOnBootPhase();
        mInitialized = true;
    }
}
public void handleOnBootPhase() {
    ...
    final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
    if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
        if (DBG) {
            Slog.d(TAG, "Auto-enabling Bluetooth.");
        }
        //調(diào)用
        sendEnableMsg(mQuietEnableExternal,
                BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
                mContext.getPackageName());
    } 
    ....
}

步驟4:BluetoothManagerService.java處理enable

private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
    addActiveLog(reason, packageName, true);
    mLastEnabledTime = SystemClock.elapsedRealtime();
}
public void handleMessage(Message msg)
{
    switch (msg.what)
    {
        case MESSAGE_ENABLE:
            handleEnable(mQuietEnable);
            break;
    }
}
private void handleEnable(boolean quietMode)
{
    ...
    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;
    }
    ...
}

bond后會調(diào)用這個函數(shù)onServiceConnected

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);
    }
}
public void handleMessage(Message msg)
{
    switch (msg.what)
    {
        case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
            ...
            mBluetooth.registerCallback(mBluetoothCallback);
            ...
            sendBluetoothServiceUpCallback();
            ...
            mBluetooth.enable(mQuietEnable);
            break;
    }
}

步驟5:AdapterService.java處理enable

注意在里面還有一個AdapterServiceBinder的類,不是這個類下面的enable

public synchronized boolean enable(boolean quietMode) {
    // 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;
    }

    Log.e(TAG, "AdapterService enable");

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

這個會觸發(fā)status machine,會調(diào)用到OffState中processMessage

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

然后進(jìn)入到TurningBleOnState類中的enter

public void enter() {
    super.enter();
    sendMessageDelayed(BLE_START_TIMEOUT, BLE_START_TIMEOUT_DELAY);
    mAdapterService.bringUpBle();
}
void bringUpBle() {
    ...
    //Start Gatt service
    setProfileServiceState(GattService.class, BluetoothAdapter.STATE_ON);
}

開啟gattservice服務(wù)

另外,ProfileService的狀態(tài)改變會觸發(fā)AdapterService的onProfileServiceStateChanged

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 void processProfileServiceStateChanged(ProfileService profile, int state) {
    switch (state) {
        case BluetoothAdapter.STATE_ON:
            if (!mRegisteredProfiles.contains(profile)) {
                Log.e(TAG, profile.getName() + " not registered (STATE_ON).");
                return;
            }
            if (mRunningProfiles.contains(profile)) {
                Log.e(TAG, profile.getName() + " already running.");
                return;
            }
            mRunningProfiles.add(profile);
            if (GattService.class.getSimpleName().equals(profile.getName())) {

                Log.e(TAG, "processProfileServiceStateChanged enableNative");

                // 這個地方就是調(diào)用libjni.so的方法,通過jni native調(diào)用
                enableNative();
            } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
                    && mRegisteredProfiles.size() == mRunningProfiles.size()) {
                mAdapterProperties.onBluetoothReady();
                updateUuids();
                setBluetoothClassFromConfig();
                initProfileServices();
                getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS);
                getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_LOCAL_IO_CAPS_BLE);
                mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
            }
            break;
        default:
            Log.e(TAG, "Unhandled profile state: " + state);
    }
}

NOTED:能夠直接調(diào)用到libbluetooth_jni.so的原因是AdapterApp 類在啟動的時候加載了

public class AdapterApp extends Application
{
    private static final String TAG = "BluetoothAdapterApp";
    private static final boolean DBG = false;
    //For Debugging only
    private static int sRefCount = 0;

    static {
        if (DBG) {
            Log.d(TAG, "Loading JNI Library");
        }
        System.loadLibrary("bluetooth_jni");
    }

    ...
}

然后這個動作會觸發(fā)com_android_bluetooth_btservice_adapterService.cpp中的

jint JNI_OnLoad(JavaVM* jvm, void* reserved) {
    JNIEnv* e;
    int status;


    ALOGE("Bluetooth Adapter Service : loading JNI\n");
    ALOGV("Bluetooth Adapter Service : loading JNI\n");

    // Check JNI version
    if (jvm->GetEnv((void**)&e, JNI_VERSION_1_6)) {
      ALOGE("JNI version mismatch error");
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_btservice_AdapterService(e);
    if (status < 0) {
      ALOGE("jni adapter service registration failure, status: %d", status);
      return JNI_ERR;
  }

    status =
      android::register_com_android_bluetooth_btservice_BluetoothKeystore(e);
    if (status < 0) {
      ALOGE("jni BluetoothKeyStore registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_hfp(e);
    if (status < 0) {
      ALOGE("jni hfp registration failure, status: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_hfpclient(e);
    if (status < 0) {
      ALOGE("jni hfp client registration failure, status: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_a2dp(e);
    if (status < 0) {
      ALOGE("jni a2dp source registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_a2dp_sink(e);
    if (status < 0) {
      ALOGE("jni a2dp sink registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_avrcp_target(e);
    if (status < 0) {
      ALOGE("jni new avrcp target registration failure: %d", status);
  }

    status = android::register_com_android_bluetooth_avrcp_controller(e);
    if (status < 0) {
      ALOGE("jni avrcp controller registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_hid_host(e);
    if (status < 0) {
      ALOGE("jni hid registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_hid_device(e);
    if (status < 0) {
      ALOGE("jni hidd registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_pan(e);
    if (status < 0) {
      ALOGE("jni pan registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_gatt(e);
    if (status < 0) {
      ALOGE("jni gatt registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_sdp(e);
    if (status < 0) {
      ALOGE("jni sdp registration failure: %d", status);
      return JNI_ERR;
  }

    status = android::register_com_android_bluetooth_hearing_aid(e);
    if (status < 0) {
      ALOGE("jni hearing aid registration failure: %d", status);
      return JNI_ERR;
  }

    return JNI_VERSION_1_6;
}

步驟6:bluetooth jni的enableNative處理

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

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

其中sBluetoothInterface 是hal接口,定義如下:

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.
* The |is_atv| flag indicates whether the local device is an Android TV
*/
    int (*init)(bt_callbacks_t* callbacks, bool is_atv);

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

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

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

    /** Get all Bluetooth Adapter properties at init */
    int (*get_adapter_properties)(void);

    /** Get Bluetooth Adapter property of 'type' */
    int (*get_adapter_property)(bt_property_type_t type);

    /** Set Bluetooth Adapter property of 'type' */
    /* Based on the type, val shall be one of
* RawAddress or bt_bdname_t or bt_scanmode_t etc
*/
    int (*set_adapter_property)(const bt_property_t *property);

    /** Get all Remote Device properties */
    int (*get_remote_device_properties)(RawAddress *remote_addr);

    /** Get Remote Device property of 'type' */
    int (*get_remote_device_property)(RawAddress *remote_addr,
                                      bt_property_type_t type);

    /** Set Remote Device property of 'type' */
    int (*set_remote_device_property)(RawAddress *remote_addr,
                                      const bt_property_t *property);

    /** Get Remote Device's service record  for the given UUID */
    int (*get_remote_service_record)(const RawAddress& remote_addr,
                                     const bluetooth::Uuid& uuid);

    /** Start SDP to get remote services */
    int (*get_remote_services)(RawAddress *remote_addr);

    /** Start Discovery */
    int (*start_discovery)(void);

    /** Cancel Discovery */
    int (*cancel_discovery)(void);

    /** Create Bluetooth Bonding */
    int (*create_bond)(const RawAddress *bd_addr, int transport);

    /** Create Bluetooth Bond using out of band data */
    int (*create_bond_out_of_band)(const RawAddress *bd_addr, int transport,
                                   const bt_out_of_band_data_t *oob_data);

    /** 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);

    /** BT Legacy PinKey Reply */
    /** If accept==FALSE, then pin_len and pin_code shall be 0x0 */
    int (*pin_reply)(const RawAddress *bd_addr, uint8_t accept,
                     uint8_t pin_len, bt_pin_code_t *pin_code);

    /** BT SSP Reply - Just Works, Numeric Comparison and Passkey
* passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON &
* BT_SSP_VARIANT_CONSENT
* For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey
* shall be zero */
    int (*ssp_reply)(const RawAddress *bd_addr, bt_ssp_variant_t variant,
                     uint8_t accept, uint32_t passkey);

    /** Get Bluetooth profile interface */
    const void* (*get_profile_interface) (const char *profile_id);

    /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */
    /* Configure DUT Mode - Use this mode to enter/exit DUT mode */
    int (*dut_mode_configure)(uint8_t enable);

    /* Send any test HCI (vendor-specific) command to the controller. Must be in DUT Mode */
    int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len);
    /** BLE Test Mode APIs */
    /* opcode MUST be one of: LE_Receiver_Test, LE_Transmitter_Test, LE_Test_End */
    int (*le_test_mode)(uint16_t opcode, uint8_t *buf, uint8_t len);

    /** Sets the OS call-out functions that bluedroid needs for alarms and wake locks.
* This should be called immediately after a successful |init|.
*/
    int (*set_os_callouts)(bt_os_callouts_t *callouts);

    /** 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)();

    /**
* Native support for dumpsys function
* Function is synchronous and |fd| is owned by caller.
* |arguments| are arguments which may affect the output, encoded as
* UTF-8 strings.
*/
    void (*dump)(int fd, const char **arguments);

    /**
* Clear /data/misc/bt_config.conf and erase all stored connections
*/
    int (*config_clear)(void);

    /**
* Clear (reset) the dynamic portion of the device interoperability database.
*/
    void (*interop_database_clear)(void);

    /**
* Add a new device interoperability workaround for a remote device whose
* first |len| bytes of the its device address match |addr|.
* NOTE: |feature| has to match an item defined in interop_feature_t (interop.h).
*/
    void (*interop_database_add)(uint16_t feature, const RawAddress *addr, size_t len);
} bt_interface_t;

這個enable是調(diào)用libbluetooth.so中的enable,也就是bluedroid bluetooth.cc或者android8之前的bluetooth.c

static int enable() {
    if (!interface_ready()) return BT_STATUS_NOT_READY;

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

然后就是走bluedroid流程了,host的初始化流程可以看我協(xié)議棧的其他文章

步驟7:底層bluedroid enable成功后回調(diào)處理

bluedroid底層enable跟controller交互成功后,調(diào)用這個函數(shù),通過HAL_CBACK回調(diào)到bt service apk的jni

static void event_signal_stack_up(UNUSED_ATTR void* context) {
  // Notify BTIF connect queue that we've brought up the stack. It's
  // now time to dispatch all the pending profile connect requests.
  btif_queue_connect_next();
  HAL_CBACK(bt_hal_cbacks, adapter_state_changed_cb, BT_STATE_ON);
}

思考:為什么能調(diào)用到callback呢?

是因為adapterService 服務(wù)啟動的時候調(diào)用到onCreate方法,里面有

public void onCreate() {
    super.onCreate();
    debugLog("onCreate()");
    ...
    // 調(diào)用jni的方法
    initNative(isGuest(), isNiapMode(), configCompareResult, isAtvDevice);
    ...
}
static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest,
                       jboolean isNiapMode, int configCompareResult,
                       jboolean isAtvDevice) {
    ALOGV("%s", __func__);

    // 注冊jni的callback到bluedroid,bluedroid有回調(diào)的時候回調(diào)用到sBluetoothCallbacks
    int ret = sBluetoothInterface->init(
      &sBluetoothCallbacks, isGuest == JNI_TRUE ? 1 : 0,
      isNiapMode == JNI_TRUE ? 1 : 0, configCompareResult,
      isAtvDevice == JNI_TRUE ? 1 : 0);
    if (ret != BT_STATUS_SUCCESS) {
      ALOGE("Error while setting the callbacks: %d\n", ret);
      sBluetoothInterface = NULL;
      return JNI_FALSE;
  }

}

好了,回歸會提,如果bluedroid enable成功后,會調(diào)用到sBluetoothCallbacks的adapter_state_change_callback函數(shù)

static void adapter_state_change_callback(bt_state_t status) {
    ALOGE("Bluetooth adapter_state_change_callback:%d\n",status);
    
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  ALOGV("%s: Status is: %d", __func__, status);

    // 通過jni的回調(diào)方法調(diào)用到AdapterService的stateChangeCallback
  sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback,
                               (jint)status);
}

步驟8:bt service的處理enable成功后的回調(diào)過程

void stateChangeCallback(int status) {
    Log.e(TAG, "stateChangeCallback:"+status);

    if (status == AbstractionLayer.BT_STATE_OFF) {
        debugLog("stateChangeCallback: disableNative() completed");
        mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED);
    } else if (status == AbstractionLayer.BT_STATE_ON) {
        mAdapterStateMachine.sendMessage(AdapterState.BLE_STARTED);
    } else {
        Log.e(TAG, "Incorrect status " + status + " in stateChangeCallback");
    }
}

此時進(jìn)入這個類中的processMessage處理

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

遷徙到mBleOnState狀態(tài),然后處理,另外狀態(tài)概念,會觸發(fā)AdapterService.java中的updateAdapterState

void updateAdapterState(int prevState, int newState) {
    mAdapterProperties.setState(newState);
    invalidateBluetoothGetStateCache();
    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);
            } catch (RemoteException e) {
                debugLog("updateAdapterState() - Callback #" + i + " failed (" + e + ")");
            }
        }
        mCallbacks.finishBroadcast();
    }

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

case處理

case MESSAGE_BLUETOOTH_STATE_CHANGE: {


    ....
    bluetoothStateChangeHandler(prevState, newState);

    break;
}
private void bluetoothStateChangeHandler(int prevState, int newState) {
    
    if (newState == BluetoothAdapter.STATE_BLE_ON || newState == BluetoothAdapter.STATE_OFF) {
            .......
            continueFromBleOnState();
    }
 
}
private void continueFromBleOnState() {
    ...
    mBluetooth.onLeServiceUp();
    ...
}
public void onLeServiceUp() {
    AdapterService service = getService();
    if (service == null || !callerIsSystemOrActiveUser(TAG, "onLeServiceUp")) {
        return;
    }

    enforceBluetoothPrivilegedPermission(service);

    service.mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);
}
private class BleOnState extends BaseAdapterState {

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

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

            case BLE_TURN_OFF:
                transitionTo(mTurningBleOffState);
                break;

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

然后進(jìn)入到TurningOnState class的enter處理

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

步驟9:開啟所有profile的service

void startProfileServices() {
    ...
    setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
    
}
private static final ProfileConfig[] PROFILE_SERVICES_AND_FLAGS = {
            new ProfileConfig(HeadsetService.class, R.bool.profile_supported_hs_hfp,
                    (1 << BluetoothProfile.HEADSET)),
            new ProfileConfig(A2dpService.class, R.bool.profile_supported_a2dp,
                    (1 << BluetoothProfile.A2DP)),
            new ProfileConfig(A2dpSinkService.class, R.bool.profile_supported_a2dp_sink,
                    (1 << BluetoothProfile.A2DP_SINK)),
            new ProfileConfig(HidHostService.class, R.bool.profile_supported_hid_host,
                    (1 << BluetoothProfile.HID_HOST)),
            new ProfileConfig(PanService.class, R.bool.profile_supported_pan,
                    (1 << BluetoothProfile.PAN)),
            new ProfileConfig(GattService.class, R.bool.profile_supported_gatt,
                    (1 << BluetoothProfile.GATT)),
            new ProfileConfig(BluetoothMapService.class, R.bool.profile_supported_map,
                    (1 << BluetoothProfile.MAP)),
            new ProfileConfig(HeadsetClientService.class, R.bool.profile_supported_hfpclient,
                    (1 << BluetoothProfile.HEADSET_CLIENT)),
            new ProfileConfig(AvrcpTargetService.class, R.bool.profile_supported_avrcp_target,
                    (1 << BluetoothProfile.AVRCP)),
            new ProfileConfig(AvrcpControllerService.class,
                    R.bool.profile_supported_avrcp_controller,
                    (1 << BluetoothProfile.AVRCP_CONTROLLER)),
            new ProfileConfig(SapService.class, R.bool.profile_supported_sap,
                    (1 << BluetoothProfile.SAP)),
            new ProfileConfig(PbapClientService.class, R.bool.profile_supported_pbapclient,
                    (1 << BluetoothProfile.PBAP_CLIENT)),
            new ProfileConfig(MapClientService.class, R.bool.profile_supported_mapmce,
                    (1 << BluetoothProfile.MAP_CLIENT)),
            new ProfileConfig(HidDeviceService.class, R.bool.profile_supported_hid_device,
                    (1 << BluetoothProfile.HID_DEVICE)),
            new ProfileConfig(BluetoothOppService.class, R.bool.profile_supported_opp,
                    (1 << BluetoothProfile.OPP)),
            new ProfileConfig(BluetoothPbapService.class, R.bool.profile_supported_pbap,
                    (1 << BluetoothProfile.PBAP)),
            new ProfileConfig(HearingAidService.class,
                    com.android.internal.R.bool.config_hearing_aid_profile_supported,
                    (1 << BluetoothProfile.HEARING_AID))
    };

因為我們之前在前面說過,開啟成功后就會調(diào)用profileService change的消息,所以如下文章來源地址http://www.zghlxwxcb.cn/news/detail-486355.html

 private void processProfileServiceStateChanged(ProfileService profile, int state) {
            switch (state) {
                case BluetoothAdapter.STATE_ON:
                        ........
                    if (GattService.class.getSimpleName().equals(profile.getName())) {
                        enableNative();
                    } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length
                            && mRegisteredProfiles.size() == mRunningProfiles.size()) {  //所有ProfileService都啟動完畢
                       .......
                        mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED);
                    }
                    break;
public boolean processMessage(Message msg) {
    switch (msg.what) {
        case BREDR_STARTED:
            transitionTo(mOnState);
            break;

    }
    return true;
}
private void bluetoothStateChangeHandler(int prevState, int newState) {
    ...
    sendBluetoothStateCallback(isUp); //廣播發(fā)出數(shù)據(jù)
    sendBleStateChanged(prevState, newState);
    ...
}

到了這里,關(guān)于Android藍(lán)牙使能流程圖(Android Bluetooth enable) -- java & jni層的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Qt (高仿Visio)流程圖組件開發(fā)(七) 流程圖 簡單操作界面搭建

    Qt (高仿Visio)流程圖組件開發(fā)(七) 流程圖 簡單操作界面搭建

    Qt (高仿Visio)流程圖組件開發(fā)(一) 效果展示及基本開發(fā)框架構(gòu)思 Qt (高仿Visio)流程圖組件開發(fā)(二) 基本圖元繪制 圖元間連線繪制 Qt (高仿Visio)流程圖組件開發(fā)(三) 圖元基類如何定義,流程圖多種圖元類型實現(xiàn) Qt (高仿Visio)流程圖組件開發(fā)(四) 流程圖 圖元

    2023年04月25日
    瀏覽(26)
  • Python 代碼一鍵轉(zhuǎn)流程圖---python=>flowchart-dsl=>流程圖

    Python 代碼一鍵轉(zhuǎn)流程圖---python=>flowchart-dsl=>流程圖

    這個項目是基于大名鼎鼎的 flowchart.js。 下面貼幾張運行圖片: ?如果直接輸入dsl代碼,再進(jìn)行轉(zhuǎn)化就可以很好的畫出流程圖 ? ? ? 如果你使用 Typora,可能知道在 Typora 中用?flow?可以用一種簡單的文本語言來寫流程圖,根據(jù)?Typora 的文檔,這個功能來自開源的?flowchart.js。

    2024年02月08日
    瀏覽(35)
  • 提升繪圖效率不再難,看看這8款A(yù)I流程圖軟件,一鍵快速生成流程圖!

    提升繪圖效率不再難,看看這8款A(yù)I流程圖軟件,一鍵快速生成流程圖!

    流程圖是表示流程、系統(tǒng)和思想的重要視覺輔助工具。在當(dāng)今數(shù)字時代,AI技術(shù)的出現(xiàn)已經(jīng)徹底改變了制作流程圖的方式。 在本文中,我們將與各位分享 8款好用的AI流程圖軟件 ,借助每款軟件內(nèi)置的AI能力,可以快速繪制出一份完整的流程圖,以簡化和增強(qiáng)你的繪圖體驗。

    2024年02月03日
    瀏覽(29)
  • springboot啟動流程源碼解析(帶流程圖)

    springboot啟動流程源碼解析(帶流程圖)

    本文自己寫的(頭條也有這篇文章),若有問題,請指正。 大致流程如下: 1. 初始化SpringApplication,從META-INF下的spring.factories讀取 ApplicationListener/ApplicationContextInitializer 2.運行SpringApplication的run方法 3.讀取項目中環(huán)境變量、jvm配置信息、配置文件信息等 4.創(chuàng)建Spring容器對象(

    2024年02月08日
    瀏覽(26)
  • Flowable 生成流程圖

    Flowable 生成流程圖

    2024年01月18日
    瀏覽(23)
  • 純css流程圖

    純css流程圖

    ? ?

    2024年02月11日
    瀏覽(22)
  • Mermaid流程圖

    Mermaid流程圖

    mermaid簡介 Mermaid是一個基于JavaScript的繪圖工具,使用類似于Markdown的語法,允許用戶通過代碼創(chuàng)建各種圖表,包括流程圖、狀態(tài)圖、時序圖和甘特圖等。它可以將代碼塊轉(zhuǎn)化為HTML代碼,并支持多種圖表的方向。Mermaid極大地簡化了復(fù)雜圖的繪制和維護(hù),對于熟悉Markdown語法的用

    2024年01月19日
    瀏覽(55)
  • 產(chǎn)品流程圖

    產(chǎn)品流程圖

    3.1業(yè)務(wù)流程圖 | 泳道圖(給產(chǎn)品經(jīng)理看) 3.2任務(wù)流程圖(給程序員看) 3.3頁面流程圖(給UI設(shè)計人員看) 4.1調(diào)查研究 4.2梳理提煉 4.3 確認(rèn)評估 4.4 維護(hù)更新 3.1業(yè)務(wù)流程圖 | 泳道圖(給產(chǎn)品經(jīng)理看) 3.2任務(wù)流程圖(給程序員看) 3.3頁面流程圖(給UI設(shè)計人員看) 4.1調(diào)查研究

    2024年02月16日
    瀏覽(23)
  • 讓流程圖動起來

    讓流程圖動起來

    我們平時畫流程,然后貼到文檔,就完事了。但是過程演示的時候,如果只是一張靜態(tài)圖,很難吸引到聽眾的注意力,表達(dá)效果并不太好。常用的方法是可以用PPT進(jìn)行動態(tài)演示,做PPT也是需要花一些時間,同時表達(dá)也比較有限。下面介紹一下基于突突圖(Procviz)的流程圖動畫生

    2024年04月28日
    瀏覽(54)
  • 【需求輸出】流程圖輸出

    【需求輸出】流程圖輸出

    2024年02月13日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包