OpenHarmony 源碼解析之分布式任務調度(一)
前言
鴻蒙系統(HarmonyOS)支持在本地程序里調起遠程任務,這個功能是更底層的分布式任務調度子系統支撐的,并且已經貢獻到開源鴻蒙(OpenHarmony)代碼里。為了更全面地理解與掌握分布式任務調度子系統,我先從分布式遠程啟動這個簡單的功能開始,利用開源鴻蒙開放的源代碼,進行深入學習。
以下行文如無特別說明,所述說的鴻蒙系統均指開源鴻蒙系統(OpenHarmony 3.0 LTS版本)。

OpenHarmony 架構圖
概述
先從開源鴻蒙文檔入手:
分布式任務調度模塊,通過主從設備服務代理機制,在OpenHarmony操作系統上建立起分布式服務平臺,支持主設備(搭載OpenHarmony的智慧屏設備)啟動從設備(IP Camera、運動手表等小內存OpenHarmony設備)FA的能力。
以智慧屏節目開播提醒為例,智慧屏上在喜歡的節目菜單中,點擊“開播后提醒我”按鈕,等節目開播后,智慧屏會拉起運動手表上的節目開播提醒FA。通過該FA用戶可以快速知道喜歡的節目已經開始,達到協同互助的作用。
FA : Feature Ability代表有界面的Ability,用于與用戶進行交互。
遠程啟動:即跨設備啟動FA,與本地啟動FA相對應。
開源鴻蒙系統里的應用程序以Ability為單位,分為FA和PA, 可以簡單理解為FA就是有界面的應用程序。
分布式服務平臺
分布式任務調度的前提,是設備必須建立分布式服務平臺,并且注冊自身能力。
開源鴻蒙支持3種體量的設備:輕量、小型、標準。
在標準設備里,開源鴻蒙默認已經開啟了分布式服務平臺,開發者一般無需做額外工作,即可使用分布式任務調度功能。
而輕量和小型設備則需要自行在啟動代碼中實現分布式服務平臺功能調用,具體可以參考【分布式軟總線子系統】。相關代碼倉及調用API可以參考:【分布式軟總線】,【分布式軟總線lite】。
同一個局域網
在上述代碼倉的說明中,一再強調了:
需要保證發現端設備與被發現端設備在同一個局域網內
是因為目前開源鴻蒙系統使用了coap協議,并且暫時只支持coap協議。從源代碼中可以看到,以后應該會擴展到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協議默認使用的端口是5684,在局域網通過udp廣播方式發布。如果調試過程中找不到設備,可以通過這個端口抓包分析。
- #define COAP_DEFAULT_PORT 5684
分布式任務調度流程
手頭正好有兩塊支持開源鴻蒙標準系統的開發板Hi3516D,因此以標準系統的分布式任務調度為例,說明開源鴻蒙系統的分布式任務調度流程。輕量系統和小型系統除了開發語言不同,基本步驟是一致的。
開源鴻蒙系統開發FA目前只支持js/eTS語言。
這個demo參考了分布式計算器,為說明方便,做了大量簡化處理,并且此處忽略了錯誤處理。
具體api參考代碼倉:DeviceManager組件。
步驟1:創建設備管理器
- import deviceManager from '@ohos.distributedHardware.deviceManager';
- let self = this;
- deviceManager.createDeviceManager("com.example.myapplication", (err, val)=>{self.deviceManager_ = val;});
使用DeviceManager相關接口之前,需要通過createDeviceManager接口創建DeviceManager實例;
步驟2:獲取可信設備列表
- var array = this.deviceManager_.getTrustedDeviceListSync();
步驟3:注冊周邊設備動態監控回調函數
- this.deviceManager_.on('deviceFound', (data) => {
- let extraInfo = {
- "targetPkgName": 'com.example.myapplication',
- "appName": '分布式例子',
- "appDescription": '一個簡單的分布式例子',
- "business": '0'
- };
- let authParam = {
- "authType": 1,
- "appIcon": '',
- "appThumbnail": '',
- "extraInfo": extraInfo
- };
- self.deviceManager_.authenticateDevice(data.device, authParam, (err) => { ... });
- });
- this.deviceManager_.on('deviceStateChange', (data) => { ... });
步驟4:發現周邊新設備,并認證
- 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);
新設備需要認證才能互聯使用。開源鴻蒙系統沒有用戶注冊機制,因此認證需要另外開發框架支持,開源鴻蒙在標準系統提供了一個簡單的HAP程序支持彈窗PIN碼認證機制,可以簡單使用。
當前版本只支持PIN碼認證,需要提供PIN碼認證的授權提示界面、PIN碼顯示界面、PIN碼輸入界面;
當前,由于系統通過native層直接進行彈窗的能力尚不具備,這里使用一個臨時的FA來進行對應界面的彈窗。
該FA為:DeviceManager_UI.hap,作為系統應用進行預置。
具體行為是:
- 遠程設備在屏幕顯示一個巨大的6位數字PIN碼
- 控制設備彈出一個PIN碼輸入窗口
- 用戶在控制設備輸入遠程設備所顯示的PIN碼,通過驗證即可繼續遠程控制
- PIN碼輸入成功后,該設備成為可信設備存儲于系統,下次再次連接時不需要再次驗證
步驟5:遠程調用FA
以上步驟1~步驟4是標準的周圍設備管理步驟,因此可以封裝成函數庫,方便后續使用。
在獲取到可信設備數組后,可以在適當的彈窗或者選擇界面,讓用戶選擇其中一個進行連接。
- 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;
- });
- },
啟動遠程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));
- });
遠程設備收到請求后,就會以對應的參數啟動相應的FA,并且在啟動時可以獲取到參數:
- onReady() {
- featureAbility.getWant((error, want) => {
- console.info('myapplication: featureAbility.getWant =' + JSON.stringify(want.parameters));
- // 這里isFA就是上面遠程請求的參數
- if (want.parameters.isFA && want.parameters.isFA === 'FA') {
- this.initKVManager(()=>{
- console.log('myapplication: kvmanager started.')
- });
- }
- else{
- this.findDevices();
- }
- });
- },
具體api可以參考華為鴻蒙開發文檔,請注意里面部分內容可能與開源鴻蒙系統有區別,請自行確定。
編譯運行
以上步驟,均已在DevEco Studio 3.0.0.600 x64中編寫成功,并且在兩臺Hi3516D設備間成功運行,附代碼(分布式遠程啟動.zip)。
想在開源鴻蒙系統上安裝HAP程序,必須要先進行簽名,并且在DevEco Studio中進行相關設置。具體步驟參考開源鴻蒙文檔。
上傳安裝HAP程序,需要使用開發工具hdc,具體參考文檔。
小結
開源鴻蒙系統的分布式任務調度基本功能已經初步完善了,使用文檔比較分散,需要到各個子系統去查閱,略有不便。
下一步,學習一下分布式軟總線、分布式數據,看看開源鴻蒙系統是如何封裝應用之間數據交互能力的。
另外看源代碼,開源鴻蒙系統已經有分布式應用流轉(遷移)運行功能,有時間可以學習一下。