最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android藍牙服務啟動流程分析探索

 更新時間:2023年01月18日 11:21:16   作者:c小旭  
這篇文章主要介紹了Android藍牙服務啟動流程,了解內部原理是為了幫助我們做擴展,同時也是驗證了一個人的學習能力,如果你想讓自己的職業(yè)道路更上一層樓,這些底層的東西你是必須要會的

首先我們要知道,主要系統服務都是在 SystemServer 啟動的,藍牙也是如此:

1、SystemServer

源碼路徑:/frameworks/base/services/java/com/android/server/SystemServer.java

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

SystemServer 在啟動其他服務的方法里,啟動了 BluetoothService。

2、BluetoothService

class BluetoothService extends SystemService {
    private BluetoothManagerService mBluetoothManagerService;
    public BluetoothService(Context context) {
        super(context);
        //創(chuàng)建BluetoothManagerService的實例
        mBluetoothManagerService = new BluetoothManagerService(context);
    }
    ......
    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            //將BluetoothManagerService實例發(fā)布到系統中,這樣就可以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 而非 BluetoothService??梢酝ㄟ^ ServiceManager.getService(BLUETOOTH_MANAGER _SERVICE) 獲取藍牙服務。

onBootPhase(int):這個函數應該是 systemserver 在啟動的時候會多次調用,參數代表當前啟動進行到了什么階段,用戶定義的 service 針對各個階段需要做怎樣的處理或者是不做任何處理。

3、BluetoothManagerService

    BluetoothManagerService(Context context) {
        //創(chuàng)建內部處理msg的handler
        mHandler = new BluetoothHandler(IoThread.get().getLooper());
        mContext = context;
        ......
        //false表示此次enable需要觸發(fā)auto connect device和保存狀態(tài),BluetoothAdapter::enableNoAutoConnect()可以改變此狀態(tài)
        mQuietEnableExternal = false;
        mEnableExternal = false;
        ......
        IntentFilter filter = new IntentFilter();
        //監(jiān)聽App通過接口修改BT 名稱的廣播
        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
        //監(jiān)聽bt地址改變的廣播
        filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
        //監(jiān)聽當前設置需要restore回上一次設置的廣播,此時需要重新保存name和addr為上一次的信息
        filter.addAction(Intent.ACTION_SETTING_RESTORED);
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(mReceiver, filter);
        //從數據庫中加載本機Bt的local name和address
        loadStoredNameAndAddress();
        //查看上一次關機時,BT是否為enable狀態(tài);如果是,這次開機也需要enable BT
        if (isBluetoothPersistedStateOn()) {
            if (DBG) {
                Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
            }
            mEnableExternal = true;//表明開機過程中需要enable BT
        }
    }

在服務啟動到一定階段就會回調到 SystemService 的 onBootPhase(int) 方法,即 2 中的該方法,然后調用 BMS 中的 handleOnBootPhase() 方法。

    public void handleOnBootPhase() {   
        ......
        final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
        if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && && !isSafeMode) {
            sendEnableMsg(mQuietEnableExternal/*默認false,表示此次enable需要自動連接device/保存enable狀態(tài)*/,
                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
                    mContext.getPackageName());
        } else if (!isNameAndAddressSet()) {
            Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
            mHandler.sendMessage(getMsg);
        }
        ......
    }

handleOnBootPhase()的內容比較單一,根據一些flag判斷是否需要enable BT;而enable藍牙這里是通過觸發(fā)send msg實現。

private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
    //發(fā)送MESSAGE_ENABLE msg
    mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
    addActiveLog(reason, packageName, true);
    mLastEnabledTime = SystemClock.elapsedRealtime();
}
case MESSAGE_ENABLE:
    int quietEnable = msg.arg1;
    mQuietEnable = (quietEnable == 1);//此時為false
    //mBluetooth是后面綁定Bt apk中AdapterService時拿到的Binder代理對象;用以把操作bypass到BT核心框架中
    if (mBluetooth == null) {
        handleEnable(mQuietEnable);
    } else {//如果mBluetooth不是null,說明之前已經啟動過了;此時是Restart flow,以MESSAGE_RESTART_BLUETOOTH_SERVICE觸發(fā)
        mWaitForEnableRetry = 0;
        Message enableDelayedMsg = mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
        mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
    }
    break;

handleEnable() 去 Bind AdapterService 拿到它的Binder句柄。同樣的在調用 BluetoothManagerService 中的 enable()、disable()等方法時,也是調到 handleEnable() 方法,從而最終調用 AdapterService 中的 enable()、disable() 方法。

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;
            }
        }
    } finally {
        mBluetoothLock.writeLock().unlock();
    }
}

然后我們看一下 doBind() 方法中的 mConnection 參數:

private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
private class BluetoothServiceConnection implements ServiceConnection {
    public void onServiceConnected(ComponentName componentName, IBinder service) {
        String name = componentName.getClassName();
        Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
        if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
            msg.arg1 = SERVICE_IBLUETOOTH;
        } 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();
        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);
    }
}

拿到 AdapterService 服務后,發(fā)送MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息且 arg1 = SERVICE_IBLUETOOTH。

case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
    IBinder service = (IBinder) msg.obj;
    try {
        mBluetoothLock.writeLock().lock();
        mBinding = false;
        mBluetoothBinder = service;
        mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
        //Register callback object
        try {
            mBluetooth.registerCallback(mBluetoothCallback, mContext.getAttributionSource());
        } catch (RemoteException re) {
            Slog.e(TAG, "Unable to register BluetoothCallback", re);
        }
        //Inform BluetoothAdapter instances that service is up
        sendBluetoothServiceUpCallback();
        //Do enable request
        try {
            if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) {
                Slog.e(TAG, "IBluetooth.enable() returned false");
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Unable to call enable()", e);
        }
    } finally {
         mBluetoothLock.writeLock().unlock();
    }
    if (!mEnable) {
        waitForState(Set.of(BluetoothAdapter.STATE_ON));
        handleDisable();
        waitForState(Set.of(BluetoothAdapter.STATE_OFF,
        BluetoothAdapter.STATE_TURNING_ON,
        BluetoothAdapter.STATE_TURNING_OFF,
        BluetoothAdapter.STATE_BLE_TURNING_ON,
        BluetoothAdapter.STATE_BLE_ON,
        BluetoothAdapter.STATE_BLE_TURNING_OFF));
    }
}

主要操作:

1、拿到 bind 服務的 onBinder() 句柄,并轉成 IBluetooth 類型

2、通過 IBluetooth 類型的 obj,調用 enable() 接口,將 flow 轉到 AdapterService 中,做一些初始化、并向 stack 下 enable 藍牙的 cmd

至此,enable 藍牙的 flow 就從 BluetoothManagerService 轉到 AdapterService 中了;實際上,通過 BluetoothAdapter 下來的大部分 API 調用最終都是調用到 AdapterService,再通過它下cmd 給 stack。

兩個常見到的flag:

mEnable:用來標記系統運行時,藍牙狀態(tài)的變化,它有些時候跟 mEnableExternal 值一致。但如果藍牙的狀態(tài)是因為某些原因,如 stack 崩潰,導致藍牙需要重啟,重新啟動時,需要靠這個 flag 來標記這種 case 的 enable/disable 狀態(tài)。

mEnableExternal:它主要是記錄通過用戶手動操作導致的BT使能狀態(tài),如通過藍牙功能按鈕來 enable/disable 藍牙。

到此這篇關于Android藍牙服務啟動流程分析探索的文章就介紹到這了,更多相關Android藍牙服務啟動內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Android MediaPlayer 播放音頻的方式

    Android MediaPlayer 播放音頻的方式

    這篇文章主要介紹了Android MediaPlayer 播放音頻的方式,本文給大家詳細介紹了MediaPlayer的使用方式,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • Android使用GridView實現表格分割線效果

    Android使用GridView實現表格分割線效果

    這篇文章主要為大家詳細介紹了Android使用GridView實現表格分割線效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • 如何修改Android Studio創(chuàng)建module時默認的compileSdkVersion

    如何修改Android Studio創(chuàng)建module時默認的compileSdkVersion

    這篇文章主要給大家介紹了如何修改Android Studio創(chuàng)建module時默認的compileSdkVersion的相關資料,文中介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧。
    2017-05-05
  • Android實現下拉展示條目效果

    Android實現下拉展示條目效果

    這篇文章主要為大家詳細介紹了Android實現下拉展示條目效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 詳解Android單元測試方法與步驟

    詳解Android單元測試方法與步驟

    這篇文章給大家分享了Android單元測試方法與步驟的相關知識點,有興趣和需要的朋友參考學習下。
    2018-07-07
  • Android Studio綁定下拉框數據詳解

    Android Studio綁定下拉框數據詳解

    這篇文章主要為大家詳細介紹了Android Studio綁定下拉框數據,Android Studio綁定網絡JSON數據,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android Material Design 陰影實現示例

    Android Material Design 陰影實現示例

    這篇文章主要介紹了Android Material Design 陰影實現示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • Android批量修改文件格式/文件名的神操作分享

    Android批量修改文件格式/文件名的神操作分享

    最近工作中遇到了一個功能,需要批量修改文件格式,發(fā)現實現的過程挺值得分享的,所以下面這篇文章主要給大家介紹了關于Android批量修改文件格式/文件名的神操作,需要的朋友可以參考下
    2021-09-09
  • Android 實現自定義圓形進度條的功能

    Android 實現自定義圓形進度條的功能

    這篇文章主要介紹了Android 實現自定義圓形進度條的功能的相關資料,開發(fā)Android應用的朋友肯定對自定義View不陌生,很多都有重新寫的,這里就對實現圓形進度條介紹下,需要的朋友可以參考下
    2016-11-11
  • Android中Fragmen首選項使用自定義的ListPreference的方法

    Android中Fragmen首選項使用自定義的ListPreference的方法

    Android中Fragmen的首選項可以使用自定義的ListPreference,這樣Fragment的PreferenceFragment就可以更方便地保存配置信息,需要的朋友可以參考下
    2016-05-05

最新評論

嘉禾县| 铅山县| 万盛区| 彰武县| 井陉县| 紫金县| 萍乡市| 泸定县| 体育| 孝昌县| 阿勒泰市| 花莲县| 揭阳市| 新巴尔虎左旗| 灵石县| 双流县| 乐都县| 五河县| 松江区| 吉林市| 海淀区| 富蕴县| 襄垣县| 清水县| 韩城市| 高邑县| 五家渠市| 浦城县| 农安县| 资讯 | 义马市| 南雄市| 瑞金市| 永清县| 张北县| 枝江市| 汶川县| 汽车| 胶州市| 丹棱县| 拜泉县|