1/* 2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import ArrayList from '@ohos.util.ArrayList'; 17import type { MessageEvent } from '@ohos/common'; 18import { Log } from '@ohos/common'; 19import CheckEmptyUtils from '@ohos/common'; 20import type { P2PDiscoveryListener } from './Discovery'; 21import worker from '@ohos.worker'; 22import { WorkerUtil } from '../utils/WorkerUtil'; 23import { WorkerRequest, RequestCode, ResponseCode } from '../model/WorkerData'; 24import type { WorkerResponse } from '../model/WorkerData'; 25 26const TAG = 'P2pMonitor'; 27 28export class P2PMonitor { 29 private readonly _listeners: ArrayList<P2PDiscoveryListener> = new ArrayList<P2PDiscoveryListener>(); 30 private _worker: worker.ThreadWorker; 31 32 constructor() { 33 this.initDiscoveryWorker(); 34 } 35 36 public discovery(listener: P2PDiscoveryListener): void { 37 Log.debug(TAG, 'start discovery enter'); 38 if (this._listeners.isEmpty()) { 39 Log.info(TAG, '_listeners is empty, start discover'); 40 this._listeners.add(listener); 41 let discoverRequest: WorkerRequest = new WorkerRequest(RequestCode.P2P_START_DISCOVERY); 42 WorkerUtil.postMessageToWorkerThread(this._worker, discoverRequest); 43 } else { 44 Log.info(TAG, '_listeners is not empty ignore'); 45 } 46 } 47 48 public stopDiscover(listener: P2PDiscoveryListener): void { 49 Log.debug(TAG, 'remove discovery listener'); 50 this._listeners.remove(listener); 51 if (this._listeners.isEmpty()) { 52 Log.debug(TAG, 'stop discovery'); 53 let initRequest: WorkerRequest = new WorkerRequest(RequestCode.P2P_CANCEL_DISCOVERY); 54 WorkerUtil.postMessageToWorkerThread(this._worker, initRequest); 55 } 56 } 57 58 handleP2pDiscoveryResult(responseCode: ResponseCode, data): void { 59 if (ResponseCode.ERROR === responseCode) { 60 Log.error(TAG, 'handleP2pDiscoveryResult ResponseCode is error'); 61 return; 62 } 63 if (data.found) { 64 for (let listener of this._listeners) { 65 listener.onPeerFound(data.p2pDevice); 66 } 67 } else { 68 for (let listener of this._listeners) { 69 listener.onPeerLost(data.p2pDevice); 70 } 71 } 72 } 73 74 private initDiscoveryWorker(): boolean { 75 if (this._worker === undefined) { 76 this._worker = new worker.ThreadWorker('entry/ets/workers/DiscoveryWorker.ts', { type: 'classic', name: 'DiscoveryWorkerOfExtension' }); 77 if (this._worker === undefined) { 78 Log.error(TAG, 'initWorker failed'); 79 return false; 80 } 81 this._worker.onmessage = this.onMessage; 82 this._worker.onmessageerror = (messageEvent: MessageEvent<object>): void => { 83 Log.error(TAG, 'onMessageError : ' + JSON.stringify(messageEvent)); 84 }; 85 this._worker.onerror = (errorEvent: object): void => { 86 Log.error(TAG, 'onError : ' + JSON.stringify(errorEvent)); 87 }; 88 this._worker.onexit = (code: number): void => { 89 Log.info(TAG, 'onExit : ' + code); 90 this._worker = undefined; 91 }; 92 Log.info(TAG, 'initDiscoveryWorker success'); 93 return true; 94 } 95 return false; 96 } 97 98 private onMessage = (messageEvent: MessageEvent<WorkerResponse>): void => { 99 if (CheckEmptyUtils.isEmpty(messageEvent)) { 100 Log.error(TAG, 'discovery worker response is empty'); 101 return; 102 } 103 if (!messageEvent.hasOwnProperty('data')) { 104 Log.error(TAG, 'messageEvent has not data'); 105 return; 106 } 107 let workerResponse: WorkerResponse = messageEvent.data; 108 if (workerResponse === undefined || workerResponse === null) { 109 Log.error(TAG, 'workerResponse is empty'); 110 return; 111 } 112 if (!workerResponse.hasOwnProperty('requestCode') || !workerResponse.hasOwnProperty('responseCode')) { 113 Log.error(TAG, 'workerResponse is error'); 114 return; 115 } 116 let requestCode = workerResponse.requestCode; 117 let responseCode = workerResponse.responseCode; 118 Log.debug(TAG, `requestCode: ${WorkerUtil.getStringByWorkerCode(requestCode)}, responseCode: ${responseCode}`); 119 switch (requestCode) { 120 case RequestCode.P2P_START_DISCOVERY: 121 this.handleP2pDiscoveryResult(responseCode, <object>workerResponse.data); 122 break; 123 default: 124 Log.error(TAG, 'onMessage response. error code'); 125 } 126 }; 127}