1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciimport { DataMessage } from '../message/DataMessage';
17fb726d48Sopenharmony_ciimport { HdcClient } from './HdcClient';
18fb726d48Sopenharmony_ciimport { FormatCommand } from './FormatCommand';
19fb726d48Sopenharmony_ciimport { HdcCommand } from './HdcCommand';
20fb726d48Sopenharmony_ciimport { Utils } from '../common/Utils';
21fb726d48Sopenharmony_ciimport { AsyncQueue } from './AsyncQueue';
22fb726d48Sopenharmony_ciimport { PayloadHead } from '../message/PayloadHead';
23fb726d48Sopenharmony_ciimport { Serialize } from '../common/Serialize';
24fb726d48Sopenharmony_ci
25fb726d48Sopenharmony_ciexport class HdcStream {
26fb726d48Sopenharmony_ci  private dataMessages: AsyncQueue<DataMessage> = new AsyncQueue<DataMessage>();
27fb726d48Sopenharmony_ci  private readonly channelId: number;
28fb726d48Sopenharmony_ci  private interactiveShellMode: boolean = false;
29fb726d48Sopenharmony_ci  private hdcClient: HdcClient;
30fb726d48Sopenharmony_ci  public fileSize: number = -1;
31fb726d48Sopenharmony_ci
32fb726d48Sopenharmony_ci  constructor(hdcClient: HdcClient, isStopCmd: boolean) {
33fb726d48Sopenharmony_ci    this.hdcClient = hdcClient;
34fb726d48Sopenharmony_ci    this.channelId = Utils.getLocalId();
35fb726d48Sopenharmony_ci    this.hdcClient.bindStream(this.channelId, this);
36fb726d48Sopenharmony_ci  }
37fb726d48Sopenharmony_ci
38fb726d48Sopenharmony_ci  public async DoCommand(cmd: string): Promise<boolean> {
39fb726d48Sopenharmony_ci    let formatCommand;
40fb726d48Sopenharmony_ci    if (this.interactiveShellMode) {
41fb726d48Sopenharmony_ci      formatCommand = new FormatCommand(HdcCommand.CMD_SHELL_DATA, cmd, false);
42fb726d48Sopenharmony_ci    } else {
43fb726d48Sopenharmony_ci      formatCommand = Utils.formatCommand(cmd);
44fb726d48Sopenharmony_ci    }
45fb726d48Sopenharmony_ci    return this.DoCommandRemote(formatCommand);
46fb726d48Sopenharmony_ci  }
47fb726d48Sopenharmony_ci
48fb726d48Sopenharmony_ci  public async DoCommandRemote(command: FormatCommand): Promise<boolean> {
49fb726d48Sopenharmony_ci    switch (command.cmdFlag) {
50fb726d48Sopenharmony_ci      case HdcCommand.CMD_SHELL_INIT:
51fb726d48Sopenharmony_ci      case HdcCommand.CMD_SHELL_DATA:
52fb726d48Sopenharmony_ci      case HdcCommand.CMD_UNITY_EXECUTE:
53fb726d48Sopenharmony_ci      case HdcCommand.CMD_UNITY_TERMINATE:
54fb726d48Sopenharmony_ci      case HdcCommand.CMD_UNITY_REMOUNT:
55fb726d48Sopenharmony_ci      case HdcCommand.CMD_UNITY_REBOOT:
56fb726d48Sopenharmony_ci      case HdcCommand.CMD_UNITY_RUNMODE:
57fb726d48Sopenharmony_ci      case HdcCommand.CMD_UNITY_HILOG: {
58fb726d48Sopenharmony_ci        let textEncoder = new TextEncoder();
59fb726d48Sopenharmony_ci        let data = textEncoder.encode(command.parameters);
60fb726d48Sopenharmony_ci        let sendResult = await this.sendToDaemon(command, data, data.length);
61fb726d48Sopenharmony_ci        if (sendResult) {
62fb726d48Sopenharmony_ci          if (HdcCommand.CMD_SHELL_INIT === command.cmdFlag) {
63fb726d48Sopenharmony_ci            this.interactiveShellMode = true;
64fb726d48Sopenharmony_ci          }
65fb726d48Sopenharmony_ci        }
66fb726d48Sopenharmony_ci        break;
67fb726d48Sopenharmony_ci      }
68fb726d48Sopenharmony_ci      case HdcCommand.CMD_FILE_INIT: {
69fb726d48Sopenharmony_ci        await this.FileRecvCommand(command);
70fb726d48Sopenharmony_ci        break;
71fb726d48Sopenharmony_ci      }
72fb726d48Sopenharmony_ci      case HdcCommand.CMD_FILE_FINISH:
73fb726d48Sopenharmony_ci      case HdcCommand.CMD_KERNEL_CHANNEL_CLOSE: {
74fb726d48Sopenharmony_ci        let dataView = new DataView(new ArrayBuffer(1));
75fb726d48Sopenharmony_ci        if (command.parameters === '0') {
76fb726d48Sopenharmony_ci          dataView.setUint8(0, 0);
77fb726d48Sopenharmony_ci        } else {
78fb726d48Sopenharmony_ci          dataView.setUint8(0, 1);
79fb726d48Sopenharmony_ci        }
80fb726d48Sopenharmony_ci        await this.sendToDaemon(command, new Uint8Array(dataView.buffer), 1);
81fb726d48Sopenharmony_ci        break;
82fb726d48Sopenharmony_ci      }
83fb726d48Sopenharmony_ci    }
84fb726d48Sopenharmony_ci    return false;
85fb726d48Sopenharmony_ci  }
86fb726d48Sopenharmony_ci
87fb726d48Sopenharmony_ci  async FileRecvCommand(command: FormatCommand): Promise<void> {
88fb726d48Sopenharmony_ci    let cmdFlag: string = '';
89fb726d48Sopenharmony_ci    let sizeCmdFlag: number = 0;
90fb726d48Sopenharmony_ci    if (HdcCommand.CMD_FILE_INIT === command.cmdFlag) {
91fb726d48Sopenharmony_ci      cmdFlag = 'send ';
92fb726d48Sopenharmony_ci      sizeCmdFlag = 5; // 5: cmdFlag send size
93fb726d48Sopenharmony_ci    }
94fb726d48Sopenharmony_ci    if (!(command.parameters.length > cmdFlag.length)) {
95fb726d48Sopenharmony_ci    } else {
96fb726d48Sopenharmony_ci      let textEncoder = new TextEncoder();
97fb726d48Sopenharmony_ci      let data = textEncoder.encode(command.parameters);
98fb726d48Sopenharmony_ci      let aa = data.slice(5);
99fb726d48Sopenharmony_ci      await this.sendToDaemon(command, aa, aa.length);
100fb726d48Sopenharmony_ci      let fileRecvDataMessage = await this.getMessage();
101fb726d48Sopenharmony_ci      let fileRecvPlayHeadArray = fileRecvDataMessage.body!.buffer.slice(0, PayloadHead.getPayloadHeadLength());
102fb726d48Sopenharmony_ci      let fileRecvResultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(fileRecvPlayHeadArray));
103fb726d48Sopenharmony_ci      let fileRecvHeadSize = fileRecvResultPayloadHead.headSize;
104fb726d48Sopenharmony_ci      let resPlayProtectBuffer = fileRecvDataMessage.body!.buffer.slice(11, 11 + fileRecvHeadSize);
105fb726d48Sopenharmony_ci      Serialize.parsePayloadProtect(resPlayProtectBuffer);
106fb726d48Sopenharmony_ci      await this.handleCommandFileCheck();
107fb726d48Sopenharmony_ci    }
108fb726d48Sopenharmony_ci  }
109fb726d48Sopenharmony_ci
110fb726d48Sopenharmony_ci  private async handleCommandFileCheck(): Promise<void> {
111fb726d48Sopenharmony_ci    let fileCheckDataMessage = await this.getMessage();
112fb726d48Sopenharmony_ci    let fileCheckPlayHeadArray = fileCheckDataMessage.body!.buffer.slice(0, PayloadHead.getPayloadHeadLength());
113fb726d48Sopenharmony_ci    let fileCheckResultPayloadHead: PayloadHead = PayloadHead.parsePlayHead(new DataView(fileCheckPlayHeadArray));
114fb726d48Sopenharmony_ci    let fileCheckHeadSize = fileCheckResultPayloadHead.headSize;
115fb726d48Sopenharmony_ci    let fileCheckDataSize = fileCheckResultPayloadHead.dataSize;
116fb726d48Sopenharmony_ci    let fileCheckResPlayProtectBuffer = fileCheckDataMessage.body!.buffer.slice(
117fb726d48Sopenharmony_ci      PayloadHead.getPayloadHeadLength(),
118fb726d48Sopenharmony_ci      PayloadHead.getPayloadHeadLength() + fileCheckHeadSize
119fb726d48Sopenharmony_ci    );
120fb726d48Sopenharmony_ci    let fileCheckPayloadProtect = Serialize.parsePayloadProtect(fileCheckResPlayProtectBuffer);
121fb726d48Sopenharmony_ci    if (fileCheckPayloadProtect.commandFlag === HdcCommand.CMD_FILE_CHECK) {
122fb726d48Sopenharmony_ci      if (fileCheckDataSize > 0) {
123fb726d48Sopenharmony_ci        let fileCheckTransferConfigBuffer = fileCheckDataMessage.body!.buffer.slice(
124fb726d48Sopenharmony_ci          PayloadHead.getPayloadHeadLength() + fileCheckHeadSize,
125fb726d48Sopenharmony_ci          PayloadHead.getPayloadHeadLength() + fileCheckHeadSize + fileCheckDataSize
126fb726d48Sopenharmony_ci        );
127fb726d48Sopenharmony_ci        let fileCheckTransferConfig = Serialize.parseTransferConfig(fileCheckTransferConfigBuffer);
128fb726d48Sopenharmony_ci        this.fileSize = fileCheckTransferConfig.fileSize;
129fb726d48Sopenharmony_ci      }
130fb726d48Sopenharmony_ci      let fileBegin = new FormatCommand(HdcCommand.CMD_FILE_BEGIN, '', false);
131fb726d48Sopenharmony_ci      await this.sendToDaemon(fileBegin, new Uint8Array(0), 0);
132fb726d48Sopenharmony_ci    }
133fb726d48Sopenharmony_ci  }
134fb726d48Sopenharmony_ci
135fb726d48Sopenharmony_ci  async sendToDaemon(command: FormatCommand, payload: Uint8Array, dataLength: number): Promise<boolean> {
136fb726d48Sopenharmony_ci    return await this.hdcClient.readDataProcessing.send(
137fb726d48Sopenharmony_ci      this.hdcClient.sessionId,
138fb726d48Sopenharmony_ci      this.channelId,
139fb726d48Sopenharmony_ci      command.cmdFlag,
140fb726d48Sopenharmony_ci      payload,
141fb726d48Sopenharmony_ci      dataLength
142fb726d48Sopenharmony_ci    );
143fb726d48Sopenharmony_ci  }
144fb726d48Sopenharmony_ci
145fb726d48Sopenharmony_ci  putMessageInQueue(dataMessage: DataMessage): void {
146fb726d48Sopenharmony_ci    this.dataMessages.enqueue(dataMessage);
147fb726d48Sopenharmony_ci  }
148fb726d48Sopenharmony_ci
149fb726d48Sopenharmony_ci  getMessage(): Promise<DataMessage> {
150fb726d48Sopenharmony_ci    return this.dataMessages.dequeue();
151fb726d48Sopenharmony_ci  }
152fb726d48Sopenharmony_ci
153fb726d48Sopenharmony_ci  async closeStream(): Promise<void> {
154fb726d48Sopenharmony_ci    this.hdcClient.unbindStream(this.channelId);
155fb726d48Sopenharmony_ci  }
156fb726d48Sopenharmony_ci}
157