1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "daemon.h"
16fb299fa2Sopenharmony_ci
17fb299fa2Sopenharmony_ci#include <openssl/sha.h>
18fb299fa2Sopenharmony_ci#include "daemon_updater.h"
19fb299fa2Sopenharmony_ci#include "flashd_define.h"
20fb299fa2Sopenharmony_ci#include "serial_struct.h"
21fb299fa2Sopenharmony_ci
22fb299fa2Sopenharmony_cinamespace Hdc {
23fb299fa2Sopenharmony_ciHdcDaemon::HdcDaemon(bool serverOrDaemonIn)
24fb299fa2Sopenharmony_ci    : HdcSessionBase(serverOrDaemonIn)
25fb299fa2Sopenharmony_ci{
26fb299fa2Sopenharmony_ci    clsTCPServ = nullptr;
27fb299fa2Sopenharmony_ci    clsUSBServ = nullptr;
28fb299fa2Sopenharmony_ci    clsJdwp = nullptr;
29fb299fa2Sopenharmony_ci    enableSecure = false;
30fb299fa2Sopenharmony_ci}
31fb299fa2Sopenharmony_ci
32fb299fa2Sopenharmony_ciHdcDaemon::~HdcDaemon()
33fb299fa2Sopenharmony_ci{
34fb299fa2Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "~HdcDaemon");
35fb299fa2Sopenharmony_ci}
36fb299fa2Sopenharmony_ci
37fb299fa2Sopenharmony_civoid HdcDaemon::ClearInstanceResource()
38fb299fa2Sopenharmony_ci{
39fb299fa2Sopenharmony_ci    TryStopInstance();
40fb299fa2Sopenharmony_ci    Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon");
41fb299fa2Sopenharmony_ci    if (clsTCPServ) {
42fb299fa2Sopenharmony_ci        delete (HdcDaemonTCP *)clsTCPServ;
43fb299fa2Sopenharmony_ci        clsTCPServ = nullptr;
44fb299fa2Sopenharmony_ci    }
45fb299fa2Sopenharmony_ci    if (clsUSBServ) {
46fb299fa2Sopenharmony_ci        delete (HdcDaemonUSB *)clsUSBServ;
47fb299fa2Sopenharmony_ci        clsUSBServ = nullptr;
48fb299fa2Sopenharmony_ci    }
49fb299fa2Sopenharmony_ci    if (clsJdwp) {
50fb299fa2Sopenharmony_ci        delete (HdcJdwp *)clsJdwp;
51fb299fa2Sopenharmony_ci        clsJdwp = nullptr;
52fb299fa2Sopenharmony_ci    }
53fb299fa2Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish");
54fb299fa2Sopenharmony_ci}
55fb299fa2Sopenharmony_ci
56fb299fa2Sopenharmony_civoid HdcDaemon::TryStopInstance()
57fb299fa2Sopenharmony_ci{
58fb299fa2Sopenharmony_ci    ClearSessions();
59fb299fa2Sopenharmony_ci    if (clsTCPServ) {
60fb299fa2Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "Stop TCP");
61fb299fa2Sopenharmony_ci        ((HdcDaemonTCP *)clsTCPServ)->Stop();
62fb299fa2Sopenharmony_ci    }
63fb299fa2Sopenharmony_ci    if (clsUSBServ) {
64fb299fa2Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "Stop USB");
65fb299fa2Sopenharmony_ci        ((HdcDaemonUSB *)clsUSBServ)->Stop();
66fb299fa2Sopenharmony_ci    }
67fb299fa2Sopenharmony_ci    ((HdcJdwp *)clsJdwp)->Stop();
68fb299fa2Sopenharmony_ci    // workaround temply remove MainLoop instance clear
69fb299fa2Sopenharmony_ci    ReMainLoopForInstanceClear();
70fb299fa2Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "Stop loopmain");
71fb299fa2Sopenharmony_ci}
72fb299fa2Sopenharmony_ci
73fb299fa2Sopenharmony_civoid HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB)
74fb299fa2Sopenharmony_ci{
75fb299fa2Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod");
76fb299fa2Sopenharmony_ci    if (bEnableTCP) {
77fb299fa2Sopenharmony_ci        // tcp
78fb299fa2Sopenharmony_ci        clsTCPServ = new HdcDaemonTCP(false, this);
79fb299fa2Sopenharmony_ci        ((HdcDaemonTCP *)clsTCPServ)->Initial();
80fb299fa2Sopenharmony_ci    }
81fb299fa2Sopenharmony_ci    if (bEnableUSB) {
82fb299fa2Sopenharmony_ci        // usb
83fb299fa2Sopenharmony_ci        clsUSBServ = new HdcDaemonUSB(false, this);
84fb299fa2Sopenharmony_ci        ((HdcDaemonUSB *)clsUSBServ)->Initial();
85fb299fa2Sopenharmony_ci    }
86fb299fa2Sopenharmony_ci
87fb299fa2Sopenharmony_ci    clsJdwp = new HdcJdwp(&loopMain);
88fb299fa2Sopenharmony_ci    ((HdcJdwp *)clsJdwp)->Initial();
89fb299fa2Sopenharmony_ci
90fb299fa2Sopenharmony_ci    // enable security
91fb299fa2Sopenharmony_ci    string secure;
92fb299fa2Sopenharmony_ci    SystemDepend::GetDevItem("ro.hdc.secure", secure);
93fb299fa2Sopenharmony_ci    enableSecure = (Base::Trim(secure) == "1");
94fb299fa2Sopenharmony_ci}
95fb299fa2Sopenharmony_ci
96fb299fa2Sopenharmony_ci// clang-format off
97fb299fa2Sopenharmony_cibool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId,
98fb299fa2Sopenharmony_ci    const uint16_t command, uint8_t *payload, const int payloadSize)
99fb299fa2Sopenharmony_ci{
100fb299fa2Sopenharmony_ci    bool ret = true;
101fb299fa2Sopenharmony_ci    hTaskInfo->ownerSessionClass = this;
102fb299fa2Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "RedirectToTask command %d", command);
103fb299fa2Sopenharmony_ci    switch (command) {
104fb299fa2Sopenharmony_ci#ifndef UPDATER_BUILD_VARIANT_USER
105fb299fa2Sopenharmony_ci        case CMD_UNITY_EXECUTE:
106fb299fa2Sopenharmony_ci            ret = TaskCommandDispatch<HdcDaemonUnity>(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
107fb299fa2Sopenharmony_ci            break;
108fb299fa2Sopenharmony_ci        case CMD_SHELL_INIT:
109fb299fa2Sopenharmony_ci        case CMD_SHELL_DATA:
110fb299fa2Sopenharmony_ci            ret = TaskCommandDispatch<HdcShell>(hTaskInfo, TYPE_SHELL, command, payload, payloadSize);
111fb299fa2Sopenharmony_ci            break;
112fb299fa2Sopenharmony_ci        case CMD_FILE_CHECK:
113fb299fa2Sopenharmony_ci        case CMD_FILE_DATA:
114fb299fa2Sopenharmony_ci        case CMD_FILE_FINISH:
115fb299fa2Sopenharmony_ci        case CMD_FILE_INIT:
116fb299fa2Sopenharmony_ci        case CMD_FILE_BEGIN:
117fb299fa2Sopenharmony_ci            ret = TaskCommandDispatch<HdcFile>(hTaskInfo, TASK_FILE, command, payload, payloadSize);
118fb299fa2Sopenharmony_ci            break;
119fb299fa2Sopenharmony_ci#endif
120fb299fa2Sopenharmony_ci        case CMD_UNITY_REBOOT:
121fb299fa2Sopenharmony_ci        case CMD_UNITY_HILOG:
122fb299fa2Sopenharmony_ci            ret = TaskCommandDispatch<HdcDaemonUnity>(hTaskInfo, TYPE_UNITY, command, payload, payloadSize);
123fb299fa2Sopenharmony_ci            break;
124fb299fa2Sopenharmony_ci        // One-way function, so fewer options
125fb299fa2Sopenharmony_ci        case CMD_UPDATER_UPDATE_INIT:
126fb299fa2Sopenharmony_ci        case CMD_UPDATER_FLASH_INIT:
127fb299fa2Sopenharmony_ci        case CMD_UPDATER_CHECK:
128fb299fa2Sopenharmony_ci        case CMD_UPDATER_BEGIN:
129fb299fa2Sopenharmony_ci        case CMD_UPDATER_DATA:
130fb299fa2Sopenharmony_ci        case CMD_UPDATER_FINISH:
131fb299fa2Sopenharmony_ci        case CMD_UPDATER_ERASE:
132fb299fa2Sopenharmony_ci        case CMD_UPDATER_FORMAT:
133fb299fa2Sopenharmony_ci        case CMD_UPDATER_PROGRESS:
134fb299fa2Sopenharmony_ci            ret = TaskCommandDispatch<DaemonUpdater>(hTaskInfo, TASK_UPDATER, command, payload, payloadSize);
135fb299fa2Sopenharmony_ci            break;
136fb299fa2Sopenharmony_ci        case CMD_UNITY_REMOUNT:
137fb299fa2Sopenharmony_ci        case CMD_UNITY_RUNMODE:
138fb299fa2Sopenharmony_ci        case CMD_UNITY_ROOTRUN:
139fb299fa2Sopenharmony_ci        case CMD_UNITY_BUGREPORT_INIT:
140fb299fa2Sopenharmony_ci        case CMD_JDWP_LIST:
141fb299fa2Sopenharmony_ci        case CMD_JDWP_TRACK:
142fb299fa2Sopenharmony_ci            ret = TaskCommandDispatch<InvalidDaemon>(hTaskInfo, TASK_FAKE, command, payload, payloadSize);
143fb299fa2Sopenharmony_ci            break;
144fb299fa2Sopenharmony_ci        default:
145fb299fa2Sopenharmony_ci            break;
146fb299fa2Sopenharmony_ci    }
147fb299fa2Sopenharmony_ci    return ret;
148fb299fa2Sopenharmony_ci}
149fb299fa2Sopenharmony_ci
150fb299fa2Sopenharmony_cibool HdcDaemon::HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake)
151fb299fa2Sopenharmony_ci{
152fb299fa2Sopenharmony_ci    bool ret = false;
153fb299fa2Sopenharmony_ci    switch (handshake.authType) {
154fb299fa2Sopenharmony_ci        case AUTH_NONE: {  // AUTH_NONE -> AUTH
155fb299fa2Sopenharmony_ci            hSession->tokenRSA = Base::GetRandomString(SHA_DIGEST_LENGTH);
156fb299fa2Sopenharmony_ci            handshake.authType = AUTH_TOKEN;
157fb299fa2Sopenharmony_ci            handshake.buf = hSession->tokenRSA;
158fb299fa2Sopenharmony_ci            string bufString = SerialStruct::SerializeToString(handshake);
159fb299fa2Sopenharmony_ci            Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size());
160fb299fa2Sopenharmony_ci            ret = true;
161fb299fa2Sopenharmony_ci            break;
162fb299fa2Sopenharmony_ci        }
163fb299fa2Sopenharmony_ci        case AUTH_SIGNATURE: {
164fb299fa2Sopenharmony_ci            // When Host is first connected to the device, the signature authentication is inevitable, and the
165fb299fa2Sopenharmony_ci            // certificate verification must be triggered.
166fb299fa2Sopenharmony_ci            //
167fb299fa2Sopenharmony_ci            // When the certificate is verified, the client sends a public key to the device, triggered the system UI
168fb299fa2Sopenharmony_ci            // jump out dialog, and click the system, the system will store the Host public key certificate in the
169fb299fa2Sopenharmony_ci            // device locally, and the signature authentication will be correct when the subsequent connection is
170fb299fa2Sopenharmony_ci            // connected.
171fb299fa2Sopenharmony_ci            if (!HdcAuth::AuthVerify((uint8_t *)hSession->tokenRSA.c_str(),
172fb299fa2Sopenharmony_ci                (uint8_t *)handshake.buf.c_str(), handshake.buf.size())) {
173fb299fa2Sopenharmony_ci                // Next auth
174fb299fa2Sopenharmony_ci                handshake.authType = AUTH_TOKEN;
175fb299fa2Sopenharmony_ci                handshake.buf = hSession->tokenRSA;
176fb299fa2Sopenharmony_ci                string bufString = SerialStruct::SerializeToString(handshake);
177fb299fa2Sopenharmony_ci                Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(),
178fb299fa2Sopenharmony_ci                     bufString.size());
179fb299fa2Sopenharmony_ci                break;
180fb299fa2Sopenharmony_ci            }
181fb299fa2Sopenharmony_ci            ret = true;
182fb299fa2Sopenharmony_ci            break;
183fb299fa2Sopenharmony_ci        }
184fb299fa2Sopenharmony_ci        case AUTH_PUBLICKEY: {
185fb299fa2Sopenharmony_ci            ret = HdcAuth::PostUIConfirm(handshake.buf);
186fb299fa2Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "Auth host OK, postUIConfirm");
187fb299fa2Sopenharmony_ci            break;
188fb299fa2Sopenharmony_ci        }
189fb299fa2Sopenharmony_ci        default:
190fb299fa2Sopenharmony_ci            break;
191fb299fa2Sopenharmony_ci    }
192fb299fa2Sopenharmony_ci    return ret;
193fb299fa2Sopenharmony_ci}
194fb299fa2Sopenharmony_ci
195fb299fa2Sopenharmony_cibool HdcDaemon::DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize)
196fb299fa2Sopenharmony_ci{
197fb299fa2Sopenharmony_ci    // session handshake step2
198fb299fa2Sopenharmony_ci    string s = string((char *)payload, payloadSize);
199fb299fa2Sopenharmony_ci    SessionHandShake handshake;
200fb299fa2Sopenharmony_ci    string err;
201fb299fa2Sopenharmony_ci    SerialStruct::ParseFromString(handshake, s);
202fb299fa2Sopenharmony_ci    // banner to check is parse ok...
203fb299fa2Sopenharmony_ci    if (handshake.banner != HANDSHAKE_MESSAGE) {
204fb299fa2Sopenharmony_ci        hSession->availTailIndex = 0;
205fb299fa2Sopenharmony_ci        WRITE_LOG(LOG_FATAL, "Recv server-hello failed");
206fb299fa2Sopenharmony_ci        return false;
207fb299fa2Sopenharmony_ci    }
208fb299fa2Sopenharmony_ci    if (handshake.authType == AUTH_NONE) {
209fb299fa2Sopenharmony_ci        // daemon handshake 1st packet
210fb299fa2Sopenharmony_ci        uint32_t unOld = hSession->sessionId;
211fb299fa2Sopenharmony_ci        hSession->sessionId = handshake.sessionId;
212fb299fa2Sopenharmony_ci        hSession->connectKey = handshake.connectKey;
213fb299fa2Sopenharmony_ci        AdminSession(OP_UPDATE, unOld, hSession);
214fb299fa2Sopenharmony_ci        if (clsUSBServ != nullptr) {
215fb299fa2Sopenharmony_ci            (reinterpret_cast<HdcDaemonUSB *>(clsUSBServ))->OnNewHandshakeOK(hSession->sessionId);
216fb299fa2Sopenharmony_ci        }
217fb299fa2Sopenharmony_ci
218fb299fa2Sopenharmony_ci        handshake.sessionId = 0;
219fb299fa2Sopenharmony_ci        handshake.connectKey = "";
220fb299fa2Sopenharmony_ci    }
221fb299fa2Sopenharmony_ci    if (enableSecure && !HandDaemonAuth(hSession, channelId, handshake)) {
222fb299fa2Sopenharmony_ci        return false;
223fb299fa2Sopenharmony_ci    }
224fb299fa2Sopenharmony_ci    // handshake auth OK.Can append the sending device information to HOST
225fb299fa2Sopenharmony_ci    char hostName[BUF_SIZE_MEDIUM] = "";
226fb299fa2Sopenharmony_ci    size_t len = sizeof(hostName);
227fb299fa2Sopenharmony_ci    uv_os_gethostname(hostName, &len);
228fb299fa2Sopenharmony_ci    handshake.authType = AUTH_OK;
229fb299fa2Sopenharmony_ci    handshake.buf = hostName;
230fb299fa2Sopenharmony_ci    string bufString = SerialStruct::SerializeToString(handshake);
231fb299fa2Sopenharmony_ci    Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size());
232fb299fa2Sopenharmony_ci    hSession->handshakeOK = true;
233fb299fa2Sopenharmony_ci    return true;
234fb299fa2Sopenharmony_ci}
235fb299fa2Sopenharmony_ci
236fb299fa2Sopenharmony_cibool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload,
237fb299fa2Sopenharmony_ci                             int payloadSize)
238fb299fa2Sopenharmony_ci{
239fb299fa2Sopenharmony_ci    WRITE_LOG(LOG_DEBUG, "FetchCommand command %d", command);
240fb299fa2Sopenharmony_ci    bool ret = true;
241fb299fa2Sopenharmony_ci    if (!hSession->handshakeOK && command != CMD_KERNEL_HANDSHAKE) {
242fb299fa2Sopenharmony_ci        ret = false;
243fb299fa2Sopenharmony_ci        return ret;
244fb299fa2Sopenharmony_ci    }
245fb299fa2Sopenharmony_ci    switch (command) {
246fb299fa2Sopenharmony_ci        case CMD_KERNEL_HANDSHAKE: {
247fb299fa2Sopenharmony_ci            // session handshake step2
248fb299fa2Sopenharmony_ci            ret = DaemonSessionHandshake(hSession, channelId, payload, payloadSize);
249fb299fa2Sopenharmony_ci            break;
250fb299fa2Sopenharmony_ci        }
251fb299fa2Sopenharmony_ci        case CMD_KERNEL_CHANNEL_CLOSE: {  // Daemon is only cleaning up the Channel task
252fb299fa2Sopenharmony_ci            ClearOwnTasks(hSession, channelId);
253fb299fa2Sopenharmony_ci            if (*payload != 0) {
254fb299fa2Sopenharmony_ci                --(*payload);
255fb299fa2Sopenharmony_ci                Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1);
256fb299fa2Sopenharmony_ci            }
257fb299fa2Sopenharmony_ci            ret = true;
258fb299fa2Sopenharmony_ci            break;
259fb299fa2Sopenharmony_ci        }
260fb299fa2Sopenharmony_ci        default:
261fb299fa2Sopenharmony_ci            ret = DispatchTaskData(hSession, channelId, command, payload, payloadSize);
262fb299fa2Sopenharmony_ci            break;
263fb299fa2Sopenharmony_ci    }
264fb299fa2Sopenharmony_ci    return ret;
265fb299fa2Sopenharmony_ci}
266fb299fa2Sopenharmony_ci
267fb299fa2Sopenharmony_cibool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask)
268fb299fa2Sopenharmony_ci{
269fb299fa2Sopenharmony_ci    bool ret = true;
270fb299fa2Sopenharmony_ci    switch (hTask->taskType) {
271fb299fa2Sopenharmony_ci        case TYPE_UNITY:
272fb299fa2Sopenharmony_ci            ret = DoTaskRemove<HdcDaemonUnity>(hTask, op);
273fb299fa2Sopenharmony_ci            break;
274fb299fa2Sopenharmony_ci        case TYPE_SHELL:
275fb299fa2Sopenharmony_ci            ret = DoTaskRemove<HdcShell>(hTask, op);
276fb299fa2Sopenharmony_ci            break;
277fb299fa2Sopenharmony_ci        case TASK_FILE:
278fb299fa2Sopenharmony_ci            ret = DoTaskRemove<HdcTransferBase>(hTask, op);
279fb299fa2Sopenharmony_ci            break;
280fb299fa2Sopenharmony_ci        case TASK_FORWARD:
281fb299fa2Sopenharmony_ci            ret = DoTaskRemove<HdcDaemonForward>(hTask, op);
282fb299fa2Sopenharmony_ci            break;
283fb299fa2Sopenharmony_ci        case TASK_APP:
284fb299fa2Sopenharmony_ci            ret = DoTaskRemove<HdcDaemonApp>(hTask, op);
285fb299fa2Sopenharmony_ci            break;
286fb299fa2Sopenharmony_ci        case TASK_UPDATER:
287fb299fa2Sopenharmony_ci            ret = DoTaskRemove<DaemonUpdater>(hTask, op);
288fb299fa2Sopenharmony_ci            break;
289fb299fa2Sopenharmony_ci        default:
290fb299fa2Sopenharmony_ci            ret = false;
291fb299fa2Sopenharmony_ci            break;
292fb299fa2Sopenharmony_ci    }
293fb299fa2Sopenharmony_ci    return ret;
294fb299fa2Sopenharmony_ci}
295fb299fa2Sopenharmony_ci
296fb299fa2Sopenharmony_cibool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command,
297fb299fa2Sopenharmony_ci                              uint8_t *bufPtr, const int size)
298fb299fa2Sopenharmony_ci{
299fb299fa2Sopenharmony_ci    return Send(sessionId, channelId, command, (uint8_t *)bufPtr, size) > 0;
300fb299fa2Sopenharmony_ci}
301fb299fa2Sopenharmony_ci
302fb299fa2Sopenharmony_civoid HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO)
303fb299fa2Sopenharmony_ci{
304fb299fa2Sopenharmony_ci    uint32_t pid = *(uint32_t *)(buf + 1);
305fb299fa2Sopenharmony_ci    uint32_t fd = *(uint32_t *)(buf + 5);  // 5 : fd offset
306fb299fa2Sopenharmony_ci    ((HdcJdwp *)clsJdwp)->SendJdwpNewFD(pid, fd);
307fb299fa2Sopenharmony_ci};
308fb299fa2Sopenharmony_ci
309fb299fa2Sopenharmony_civoid HdcDaemon::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear)
310fb299fa2Sopenharmony_ci{
311fb299fa2Sopenharmony_ci    if (!freeOrClear) {
312fb299fa2Sopenharmony_ci        return;  // ignore step 1
313fb299fa2Sopenharmony_ci    }
314fb299fa2Sopenharmony_ci    if (clsUSBServ != nullptr) {
315fb299fa2Sopenharmony_ci        auto clsUsbModule = reinterpret_cast<HdcDaemonUSB *>(clsUSBServ);
316fb299fa2Sopenharmony_ci        clsUsbModule->OnSessionFreeFinally(hSession);
317fb299fa2Sopenharmony_ci    }
318fb299fa2Sopenharmony_ci}
319fb299fa2Sopenharmony_ci}  // namespace Hdc
320