• 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 { DataMessage } from '../message/DataMessage';
17import { HdcClient } from './HdcClient';
18import { FormatCommand } from './FormatCommand';
19import { HdcCommand } from './HdcCommand';
20import { Utils } from '../common/Utils';
21import { AsyncQueue } from './AsyncQueue';
22import { PayloadHead } from '../message/PayloadHead';
23import { Serialize } from '../common/Serialize';
24
25export class HdcStream {
26  private dataMessages: AsyncQueue<DataMessage> = new AsyncQueue<DataMessage>();
27  private readonly channelId: number;
28  private interactiveShellMode: boolean = false;
29  private hdcClient: HdcClient;
30  public fileSize: number = -1;
31
32  constructor(hdcClient: HdcClient, isStopCmd: boolean) {
33    this.hdcClient = hdcClient;
34    this.channelId = Utils.getLocalId();
35    this.hdcClient.bindStream(this.channelId, this);
36  }
37
38  public async DoCommand(cmd: string): Promise<boolean> {
39    let formatCommand;
40    if (this.interactiveShellMode) {
41      formatCommand = new FormatCommand(HdcCommand.CMD_SHELL_DATA, cmd, false);
42    } else {
43      formatCommand = Utils.formatCommand(cmd);
44    }
45    return this.DoCommandRemote(formatCommand);
46  }
47
48  public async DoCommandRemote(command: FormatCommand): Promise<boolean> {
49    switch (command.cmdFlag) {
50      case HdcCommand.CMD_SHELL_INIT:
51      case HdcCommand.CMD_SHELL_DATA:
52      case HdcCommand.CMD_UNITY_EXECUTE:
53      case HdcCommand.CMD_UNITY_TERMINATE:
54      case HdcCommand.CMD_UNITY_REMOUNT:
55      case HdcCommand.CMD_UNITY_REBOOT:
56      case HdcCommand.CMD_UNITY_RUNMODE:
57      case HdcCommand.CMD_UNITY_HILOG: {
58        let textEncoder = new TextEncoder();
59        let data = textEncoder.encode(command.parameters);
60        let sendResult = await this.sendToDaemon(command, data, data.length);
61        if (sendResult) {
62          if (HdcCommand.CMD_SHELL_INIT === command.cmdFlag) {
63            this.interactiveShellMode = true;
64          }
65        }
66        break;
67      }
68      case HdcCommand.CMD_FILE_INIT: {
69        await this.FileRecvCommand(command);
70        break;
71      }
72      case HdcCommand.CMD_FILE_FINISH:
73      case HdcCommand.CMD_KERNEL_CHANNEL_CLOSE: {
74        let dataView = new DataView(new ArrayBuffer(1));
75        if (command.parameters === '0') {
76          dataView.setUint8(0, 0);
77        } else {
78          dataView.setUint8(0, 1);
79        }
80        await this.sendToDaemon(command, new Uint8Array(dataView.buffer), 1);
81        break;
82      }
83    }
84    return false;
85  }
86
87  async FileRecvCommand(command: FormatCommand): Promise<void> {
88    let cmdFlag: string = '';
89    let sizeCmdFlag: number = 0;
90    if (HdcCommand.CMD_FILE_INIT === command.cmdFlag) {
91      cmdFlag = 'send ';
92      sizeCmdFlag = 5; // 5: cmdFlag send size
93    }
94    if (!(command.parameters.length > cmdFlag.length)) {
95    } else {
96      let textEncoder = new TextEncoder();
97      let data = textEncoder.encode(command.parameters);
98      let aa = data.slice(5);
99      await this.sendToDaemon(command, aa, aa.length);
100      let fileRecvDataMessage = await this.getMessage();
101      let fileRecvPlayHeadArray = fileRecvDataMessage.body!.buffer.slice(0, PayloadHead.getPayloadHeadLength());
102      let fileRecvResultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(fileRecvPlayHeadArray));
103      let fileRecvHeadSize = fileRecvResultPayloadHead.headSize;
104      let resPlayProtectBuffer = fileRecvDataMessage.body!.buffer.slice(11, 11 + fileRecvHeadSize);
105    // @ts-ignore
106      Serialize.parsePayloadProtect(resPlayProtectBuffer);
107      await this.handleCommandFileCheck();
108    }
109  }
110
111  private async handleCommandFileCheck(): Promise<void> {
112    let fileCheckDataMessage = await this.getMessage();
113    let fileCheckPlayHeadArray = fileCheckDataMessage.body!.buffer.slice(0, PayloadHead.getPayloadHeadLength());
114    let fileCheckResultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(fileCheckPlayHeadArray));
115    let fileCheckHeadSize = fileCheckResultPayloadHead.headSize;
116    let fileCheckDataSize = fileCheckResultPayloadHead.dataSize;
117    let fileCheckResPlayProtectBuffer = fileCheckDataMessage.body!.buffer.slice(
118      PayloadHead.getPayloadHeadLength(),
119      PayloadHead.getPayloadHeadLength() + fileCheckHeadSize
120    );
121    // @ts-ignore
122    let fileCheckPayloadProtect = Serialize.parsePayloadProtect(fileCheckResPlayProtectBuffer);
123    if (fileCheckPayloadProtect.commandFlag === HdcCommand.CMD_FILE_CHECK) {
124      if (fileCheckDataSize > 0) {
125        let fileCheckTransferConfigBuffer = fileCheckDataMessage.body!.buffer.slice(
126          PayloadHead.getPayloadHeadLength() + fileCheckHeadSize,
127          PayloadHead.getPayloadHeadLength() + fileCheckHeadSize + fileCheckDataSize
128        );
129        // @ts-ignore
130        let fileCheckTransferConfig = Serialize.parseTransferConfig(fileCheckTransferConfigBuffer);
131        this.fileSize = fileCheckTransferConfig.fileSize;
132      }
133      let fileBegin = new FormatCommand(HdcCommand.CMD_FILE_BEGIN, '', false);
134      await this.sendToDaemon(fileBegin, new Uint8Array(0), 0);
135    }
136  }
137
138  async sendToDaemon(command: FormatCommand, payload: Uint8Array, dataLength: number): Promise<boolean> {
139    return await this.hdcClient.readDataProcessing.send(
140      this.hdcClient.sessionId,
141      this.channelId,
142      command.cmdFlag,
143      payload,
144      dataLength
145    );
146  }
147
148  putMessageInQueue(dataMessage: DataMessage): void {
149    this.dataMessages.enqueue(dataMessage);
150  }
151
152  getMessage(): Promise<DataMessage> {
153    return this.dataMessages.dequeue();
154  }
155
156  async closeStream(): Promise<void> {
157    this.hdcClient.unbindStream(this.channelId);
158  }
159}
160