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