• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 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 {HdcClient} from "./hdcclient/HdcClient.js";
17import {UsbTransmissionChannel} from "./transmission/UsbTransmissionChannel.js";
18import {HDC_DEVICE_FILTERS} from "./common/ConstantType.js";
19import {FormatCommand} from "./hdcclient/FormatCommand.js";
20import {log} from "../log/Log.js";
21import {HdcStream} from "./hdcclient/HdcStream.js";
22import {HdcCommand} from "./hdcclient/HdcCommand.js";
23import {SpRecordTrace} from "../trace/component/SpRecordTrace.js";
24
25export class HdcDeviceManager {
26    private static clientList: Map<string, HdcClient> = new Map();
27    private static currentHdcClient: HdcClient;
28    private static FILE_RECV_PREFIX_STRING = "hdc file recv -cwd C:\\ "
29
30    /**
31     * getDevices
32     */
33    public static async getDevices(): Promise<USBDevice[]> {
34        return navigator.usb.getDevices();
35    }
36
37    /**
38     * findDevice
39     */
40    public static findDevice() {
41        if (!('usb' in navigator)) {
42            throw new Error('WebUSB not supported by the browser (requires HTTPS)');
43        }
44        return navigator.usb.requestDevice({filters: HDC_DEVICE_FILTERS});
45    }
46
47    /**
48     * connect by serialNumber
49     *
50     * @param serialNumber serialNumber
51     */
52    public static async connect(serialNumber: string): Promise<boolean> {
53        let client = this.clientList.get(serialNumber);
54        if (client) {
55            if (client.usbDevice!.opened) {
56                log("device Usb is Open")
57                return true;
58            } else {
59                if (SpRecordTrace.serialNumber == serialNumber) {
60                    SpRecordTrace.serialNumber = ''
61                }
62                log("device Usb not Open")
63                return false;
64            }
65        } else {
66            let connectDevice = await this.getDeviceBySerialNumber(serialNumber);
67            let usbChannel = await UsbTransmissionChannel.openHdcDevice(connectDevice);
68            if (usbChannel) {
69                let hdcClient = new HdcClient(usbChannel, connectDevice);
70                let connected = await hdcClient.connectDevice();
71                if (connected) {
72                    this.currentHdcClient = hdcClient;
73                    this.clientList.set(serialNumber, hdcClient);
74                }
75                log("device Usb connected : " + connected)
76                return connected
77            } else {
78                log("device Usb connected failed: ")
79                return false;
80            }
81        }
82    }
83
84    public static async getDeviceBySerialNumber(serialNumber: string): Promise<USBDevice> {
85        const devices = await navigator.usb.getDevices();
86        // @ts-ignore
87        return devices.find(dev => dev.serialNumber === serialNumber);
88    }
89
90    /**
91     * disConnect by serialNumber
92     *
93     * @param serialNumber
94     */
95    public static async disConnect(serialNumber: string): Promise<boolean> {
96        let hdcClient = this.clientList.get(serialNumber);
97        if (hdcClient) {
98            await hdcClient.disconnect();
99            this.clientList.delete(serialNumber);
100            return true;
101        } else {
102            return true;
103        }
104    }
105
106    /**
107     * Execute shell on the currently connected device and return the result as a string
108     *
109     * @param cmd cmd
110     */
111    public static async shellResultAsString(cmd: string, isSkipResult: boolean): Promise<string> {
112        if (this.currentHdcClient) {
113            let hdcStream = new HdcStream(this.currentHdcClient, false);
114            await hdcStream.DoCommand(cmd);
115            let result: string = '';
116            while (true) {
117                let dataMessage = await hdcStream.getMessage();
118                if (dataMessage.channelClose || isSkipResult) {
119                    result += dataMessage.getDataToString();
120                    await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false));
121                    log("result is end, close")
122                    break;
123                }
124                if (dataMessage.usbHead.sessionId == -1) {
125                    return Promise.resolve("The device is abnormal");
126                }
127                result += dataMessage.getDataToString();
128            }
129            await hdcStream.closeStream();
130            await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false));
131            return Promise.resolve(result);
132        }
133        return Promise.reject("not select device");
134    }
135
136
137    /**
138     * Execute shell on the currently connected device and return the result as a string
139     *
140     * @param cmd cmd
141     */
142    public static async stopHiprofiler(cmd: string, isSkipResult: boolean): Promise<string> {
143        if (this.currentHdcClient) {
144            let hdcStream = new HdcStream(this.currentHdcClient, true);
145            await hdcStream.DoCommand(cmd);
146            let result: string = '';
147            while (true) {
148                let dataMessage = await hdcStream.getMessage();
149                if (dataMessage.channelClose || isSkipResult) {
150                    await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false));
151                    log("result is end, close")
152                    break;
153                }
154                result += dataMessage.getDataToString();
155            }
156            await hdcStream.closeStopStream();
157            await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "0", false));
158            return Promise.resolve(result);
159        }
160        return Promise.reject("not select device");
161    }
162
163    /**
164     * Execute shell on the currently connected device, the result is returned as Blob
165     *
166     * @param cmd cmd
167     */
168    public static async shellResultAsBlob(cmd: string, isSkipResult: boolean): Promise<Blob> {
169        if (this.currentHdcClient) {
170            let hdcStream = new HdcStream(this.currentHdcClient, false);
171            log("cmd is " + cmd);
172            await hdcStream.DoCommand(cmd);
173            let finalBuffer;
174            while (true) {
175                let dataMessage = await hdcStream.getMessage();
176                if (dataMessage.channelClose || isSkipResult) {
177                    log("result is end, close")
178                    break;
179                }
180                let res = dataMessage.getData();
181                if (res) {
182                    if (!finalBuffer) {
183                        finalBuffer = new Uint8Array(res);
184                    } else {
185                        finalBuffer = HdcDeviceManager.appendBuffer(finalBuffer, new Uint8Array(res));
186                    }
187                }
188            }
189            await hdcStream.closeStream();
190            if (finalBuffer) {
191                return Promise.resolve(new Blob([finalBuffer]));
192            }
193            return Promise.resolve(new Blob());
194        }
195        return Promise.reject("not select device");
196    }
197
198    /**
199     * appendBuffer
200     *
201     * @param buffer1 firstBuffer
202     * @param buffer2 secondBuffer
203     * @private
204     */
205    private static appendBuffer(buffer1: Uint8Array, buffer2: Uint8Array) {
206        let tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
207        tmp.set(buffer1, 0);
208        tmp.set(buffer2, buffer1.byteLength);
209        return tmp;
210    };
211
212    /**
213     * Pull the corresponding file from the device side
214     *
215     * @param filename filename
216     */
217    public static async fileRecv(filename: string, callBack: Function): Promise<Blob> {
218        let finalBuffer;
219        if (this.currentHdcClient) {
220            let hdcStream = new HdcStream(this.currentHdcClient, false);
221            await hdcStream.DoCommand(HdcDeviceManager.FILE_RECV_PREFIX_STRING + filename + " ./");
222            if (!finalBuffer && hdcStream.fileSize > 0) {
223                finalBuffer = new Uint8Array(hdcStream.fileSize);
224                log("Uint8Array size is " + finalBuffer.byteLength);
225            }
226            let offset = 0;
227            while (true) {
228                let dataMessage = await hdcStream.getMessage();
229                if (dataMessage.channelClose) {
230                    log("result is end, close")
231                    break;
232                }
233                if (dataMessage.commandFlag == HdcCommand.CMD_FILE_FINISH) {
234                    await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_KERNEL_CHANNEL_CLOSE, "", false));
235                    log("CMD_FILE_FINISH is end, close")
236                    break;
237                }
238                let res = dataMessage.getData();
239                if (res) {
240                    let resRS: ArrayBuffer = res.slice(64);
241                    if (finalBuffer) {
242                        finalBuffer.set(new Uint8Array(resRS), offset);
243                        offset += resRS.byteLength;
244                        callBack((offset / hdcStream.fileSize * 100).toFixed(3))
245                    }
246                }
247                if (hdcStream.fileSize != -1 && offset >= hdcStream.fileSize) {
248                    callBack(100)
249                    await hdcStream.DoCommandRemote(new FormatCommand(HdcCommand.CMD_FILE_FINISH, "", false));
250                }
251            }
252        }
253        if (finalBuffer) {
254            return Promise.resolve(new Blob([finalBuffer]));
255        } else {
256            return Promise.resolve(new Blob([]));
257        }
258    }
259
260}
261