OpenHarmony 源碼解析之分布式任務(wù)調(diào)度(一)
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
鴻蒙系統(tǒng)(HarmonyOS)支持在本地程序里調(diào)起遠(yuǎn)程任務(wù),這個(gè)功能是更底層的分布式任務(wù)調(diào)度子系統(tǒng)支撐的,并且已經(jīng)貢獻(xiàn)到開源鴻蒙(OpenHarmony)代碼里。為了更全面地理解與掌握分布式任務(wù)調(diào)度子系統(tǒng),我先從分布式遠(yuǎn)程啟動(dòng)這個(gè)簡(jiǎn)單的功能開始,利用開源鴻蒙開放的源代碼,進(jìn)行深入學(xué)習(xí)。
以下行文如無(wú)特別說(shuō)明,所述說(shuō)的鴻蒙系統(tǒng)均指開源鴻蒙系統(tǒng)(OpenHarmony 3.0 LTS版本)。

OpenHarmony 架構(gòu)圖
概述
先從開源鴻蒙文檔入手:
分布式任務(wù)調(diào)度模塊,通過(guò)主從設(shè)備服務(wù)代理機(jī)制,在OpenHarmony操作系統(tǒng)上建立起分布式服務(wù)平臺(tái),支持主設(shè)備(搭載OpenHarmony的智慧屏設(shè)備)啟動(dòng)從設(shè)備(IP Camera、運(yùn)動(dòng)手表等小內(nèi)存OpenHarmony設(shè)備)FA的能力。
以智慧屏節(jié)目開播提醒為例,智慧屏上在喜歡的節(jié)目菜單中,點(diǎn)擊“開播后提醒我”按鈕,等節(jié)目開播后,智慧屏?xí)疬\(yùn)動(dòng)手表上的節(jié)目開播提醒FA。通過(guò)該FA用戶可以快速知道喜歡的節(jié)目已經(jīng)開始,達(dá)到協(xié)同互助的作用。
FA : Feature Ability代表有界面的Ability,用于與用戶進(jìn)行交互。
遠(yuǎn)程啟動(dòng):即跨設(shè)備啟動(dòng)FA,與本地啟動(dòng)FA相對(duì)應(yīng)。
開源鴻蒙系統(tǒng)里的應(yīng)用程序以Ability為單位,分為FA和PA, 可以簡(jiǎn)單理解為FA就是有界面的應(yīng)用程序。
分布式服務(wù)平臺(tái)
分布式任務(wù)調(diào)度的前提,是設(shè)備必須建立分布式服務(wù)平臺(tái),并且注冊(cè)自身能力。
開源鴻蒙支持3種體量的設(shè)備:輕量、小型、標(biāo)準(zhǔn)。
在標(biāo)準(zhǔn)設(shè)備里,開源鴻蒙默認(rèn)已經(jīng)開啟了分布式服務(wù)平臺(tái),開發(fā)者一般無(wú)需做額外工作,即可使用分布式任務(wù)調(diào)度功能。
而輕量和小型設(shè)備則需要自行在啟動(dòng)代碼中實(shí)現(xiàn)分布式服務(wù)平臺(tái)功能調(diào)用,具體可以參考【分布式軟總線子系統(tǒng)】。相關(guān)代碼倉(cāng)及調(diào)用API可以參考:【分布式軟總線】,【分布式軟總線lite】。
同一個(gè)局域網(wǎng)
在上述代碼倉(cāng)的說(shuō)明中,一再?gòu)?qiáng)調(diào)了:
需要保證發(fā)現(xiàn)端設(shè)備與被發(fā)現(xiàn)端設(shè)備在同一個(gè)局域網(wǎng)內(nèi)
是因?yàn)槟壳伴_源鴻蒙系統(tǒng)使用了coap協(xié)議,并且暫時(shí)只支持coap協(xié)議。從源代碼中可以看到,以后應(yīng)該會(huì)擴(kuò)展到BLE、USB等方式。
- /**
 - * @brief Enumerates media, such as Bluetooth, Wi-Fi and USB, used for publishing services.
 - *
 - * Currently, the media can only be set to coap.
 - *
 - */
 - typedef enum {
 - /** Automatic medium selection */
 - AUTO = 0,
 - /** Bluetooth */
 - BLE = 1,
 - /** Wi-Fi */
 - COAP = 2,
 - /** USB */
 - USB = 3,
 - } ExchangeMedium;
 
開源鴻蒙的coap協(xié)議默認(rèn)使用的端口是5684,在局域網(wǎng)通過(guò)udp廣播方式發(fā)布。如果調(diào)試過(guò)程中找不到設(shè)備,可以通過(guò)這個(gè)端口抓包分析。
- #define COAP_DEFAULT_PORT 5684
 
分布式任務(wù)調(diào)度流程
手頭正好有兩塊支持開源鴻蒙標(biāo)準(zhǔn)系統(tǒng)的開發(fā)板Hi3516D,因此以標(biāo)準(zhǔn)系統(tǒng)的分布式任務(wù)調(diào)度為例,說(shuō)明開源鴻蒙系統(tǒng)的分布式任務(wù)調(diào)度流程。輕量系統(tǒng)和小型系統(tǒng)除了開發(fā)語(yǔ)言不同,基本步驟是一致的。
開源鴻蒙系統(tǒng)開發(fā)FA目前只支持js/eTS語(yǔ)言。
這個(gè)demo參考了分布式計(jì)算器,為說(shuō)明方便,做了大量簡(jiǎn)化處理,并且此處忽略了錯(cuò)誤處理。
具體api參考代碼倉(cāng):DeviceManager組件。
步驟1:創(chuàng)建設(shè)備管理器
- import deviceManager from '@ohos.distributedHardware.deviceManager';
 - let self = this;
 - deviceManager.createDeviceManager("com.example.myapplication", (err, val)=>{self.deviceManager_ = val;});
 
使用DeviceManager相關(guān)接口之前,需要通過(guò)createDeviceManager接口創(chuàng)建DeviceManager實(shí)例;
步驟2:獲取可信設(shè)備列表
- var array = this.deviceManager_.getTrustedDeviceListSync();
 
步驟3:注冊(cè)周邊設(shè)備動(dòng)態(tài)監(jiān)控回調(diào)函數(shù)
- this.deviceManager_.on('deviceFound', (data) => {
 - let extraInfo = {
 - "targetPkgName": 'com.example.myapplication',
 - "appName": '分布式例子',
 - "appDescription": '一個(gè)簡(jiǎn)單的分布式例子',
 - "business": '0'
 - };
 - let authParam = {
 - "authType": 1,
 - "appIcon": '',
 - "appThumbnail": '',
 - "extraInfo": extraInfo
 - };
 - self.deviceManager_.authenticateDevice(data.device, authParam, (err) => { ... });
 - });
 - this.deviceManager_.on('deviceStateChange', (data) => { ... });
 
步驟4:發(fā)現(xiàn)周邊新設(shè)備,并認(rèn)證
- SUBSCRIBE_ID = Math.floor(65536 * Math.random());
 - var info = {
 - subscribeId: SUBSCRIBE_ID,
 - mode: 0xAA,
 - medium: 2,
 - freq: 2,
 - isSameAccount: false,
 - isWakeRemote: true,
 - capability: 0
 - };
 - this.deviceManager_.startDeviceDiscover(info);
 
新設(shè)備需要認(rèn)證才能互聯(lián)使用。開源鴻蒙系統(tǒng)沒(méi)有用戶注冊(cè)機(jī)制,因此認(rèn)證需要另外開發(fā)框架支持,開源鴻蒙在標(biāo)準(zhǔn)系統(tǒng)提供了一個(gè)簡(jiǎn)單的HAP程序支持彈窗PIN碼認(rèn)證機(jī)制,可以簡(jiǎn)單使用。
當(dāng)前版本只支持PIN碼認(rèn)證,需要提供PIN碼認(rèn)證的授權(quán)提示界面、PIN碼顯示界面、PIN碼輸入界面;
當(dāng)前,由于系統(tǒng)通過(guò)native層直接進(jìn)行彈窗的能力尚不具備,這里使用一個(gè)臨時(shí)的FA來(lái)進(jìn)行對(duì)應(yīng)界面的彈窗。
該FA為:DeviceManager_UI.hap,作為系統(tǒng)應(yīng)用進(jìn)行預(yù)置。
具體行為是:
- 遠(yuǎn)程設(shè)備在屏幕顯示一個(gè)巨大的6位數(shù)字PIN碼
 - 控制設(shè)備彈出一個(gè)PIN碼輸入窗口
 - 用戶在控制設(shè)備輸入遠(yuǎn)程設(shè)備所顯示的PIN碼,通過(guò)驗(yàn)證即可繼續(xù)遠(yuǎn)程控制
 - PIN碼輸入成功后,該設(shè)備成為可信設(shè)備存儲(chǔ)于系統(tǒng),下次再次連接時(shí)不需要再次驗(yàn)證
 
步驟5:遠(yuǎn)程調(diào)用FA
以上步驟1~步驟4是標(biāo)準(zhǔn)的周圍設(shè)備管理步驟,因此可以封裝成函數(shù)庫(kù),方便后續(xù)使用。
在獲取到可信設(shè)備數(shù)組后,可以在適當(dāng)?shù)膹棿盎蛘哌x擇界面,讓用戶選擇其中一個(gè)進(jìn)行連接。
- findDevices: function(){
 - let self = this;
 - this.remoteDevices.registerDeviceListCallback(() => {
 - var list = new Array();
 - var devs = self.remoteDevices.deviceList;
 - console.info('myapplication: on remote device updated, count=' + devs.length);
 - for (var i = 0; i < devs.length; i++) {
 - console.info('myapplication: device ' + i + '/' + devs.length +
 - ' deviceId=' + devs[i].deviceId + ' deviceName=' + devs[i].deviceName
 - + ' deviceType=' + devs[i].deviceType);
 - list[i + 1] = {
 - name: devs[i].deviceName,
 - did: devs[i].deviceId
 - };
 - }
 - self.devList = list;
 - });
 - },
 
啟動(dòng)遠(yuǎn)程FA的程序:
- import featureAbility from '@ohos.ability.featureability';
 - ......
 - featureAbility.startAbility({
 - want:{
 - bundleName: 'com.example.myapplication',
 - abilityName: 'com.example.myapplication.MainAbility',
 - deviceId: this.devList[idx].did,
 - parameters: {
 - isFA: 'FA'
 - }
 - }
 - }).then((data)=>{
 - console.log("myapplication: start ability finished:" + JSON.stringify(data));
 - });
 
遠(yuǎn)程設(shè)備收到請(qǐng)求后,就會(huì)以對(duì)應(yīng)的參數(shù)啟動(dòng)相應(yīng)的FA,并且在啟動(dòng)時(shí)可以獲取到參數(shù):
- onReady() {
 - featureAbility.getWant((error, want) => {
 - console.info('myapplication: featureAbility.getWant =' + JSON.stringify(want.parameters));
 - // 這里isFA就是上面遠(yuǎn)程請(qǐng)求的參數(shù)
 - if (want.parameters.isFA && want.parameters.isFA === 'FA') {
 - this.initKVManager(()=>{
 - console.log('myapplication: kvmanager started.')
 - });
 - }
 - else{
 - this.findDevices();
 - }
 - });
 - },
 
具體api可以參考華為鴻蒙開發(fā)文檔,請(qǐng)注意里面部分內(nèi)容可能與開源鴻蒙系統(tǒng)有區(qū)別,請(qǐng)自行確定。
編譯運(yùn)行
以上步驟,均已在DevEco Studio 3.0.0.600 x64中編寫成功,并且在兩臺(tái)Hi3516D設(shè)備間成功運(yùn)行,附代碼(分布式遠(yuǎn)程啟動(dòng).zip)。
想在開源鴻蒙系統(tǒng)上安裝HAP程序,必須要先進(jìn)行簽名,并且在DevEco Studio中進(jìn)行相關(guān)設(shè)置。具體步驟參考開源鴻蒙文檔。
上傳安裝HAP程序,需要使用開發(fā)工具h(yuǎn)dc,具體參考文檔。
小結(jié)
開源鴻蒙系統(tǒng)的分布式任務(wù)調(diào)度基本功能已經(jīng)初步完善了,使用文檔比較分散,需要到各個(gè)子系統(tǒng)去查閱,略有不便。
下一步,學(xué)習(xí)一下分布式軟總線、分布式數(shù)據(jù),看看開源鴻蒙系統(tǒng)是如何封裝應(yīng)用之間數(shù)據(jù)交互能力的。
另外看源代碼,開源鴻蒙系統(tǒng)已經(jīng)有分布式應(yīng)用流轉(zhuǎn)(遷移)運(yùn)行功能,有時(shí)間可以學(xué)習(xí)一下。
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)




















 
 
 














 
 
 
 