1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "NanohubHAL" 18 19 #include "file.h" 20 #include <json/json.h> 21 22 #include <cassert> 23 #include <cerrno> 24 #include <cinttypes> 25 #include <string> 26 27 #include <endian.h> 28 29 #include <vector> 30 31 #include <log/log.h> 32 33 #include <endian.h> 34 #include <sys/stat.h> 35 36 #include <media/stagefright/foundation/ADebug.h> 37 38 #include <hardware/context_hub.h> 39 #include "nanohub_perdevice.h" 40 #include "system_comms.h" 41 #include "nanohubhal.h" 42 43 #define CHRE_APP_DIR "/data/vendor/sensor/chre" 44 #define CHRE_APP_DIR_PERMS (S_IRUSR | S_IWUSR | S_IXUSR) 45 #define CHRE_APP_FILE_PERMS (S_IRUSR | S_IWUSR) 46 #define CHRE_APP_SETTINGS CHRE_APP_DIR "/apps.json" 47 48 namespace android { 49 50 namespace nanohub { 51 52 static void readAppName(MessageBuf &buf, hub_app_name_t &name) 53 { 54 name.id = buf.readU64(); 55 } 56 57 static void writeAppName(MessageBuf &buf, const hub_app_name_t &name) 58 { 59 buf.writeU64(name.id); 60 } 61 62 static void readNanohubMemInfo(MessageBuf &buf, NanohubMemInfo &mi) 63 { 64 uint8_t type, len; 65 uint32_t ramFree = NANOHUB_MEM_SZ_UNKNOWN; 66 uint32_t eeFree = NANOHUB_MEM_SZ_UNKNOWN; 67 uint32_t sharedFree = NANOHUB_MEM_SZ_UNKNOWN; 68 uint32_t osFree = NANOHUB_MEM_SZ_UNKNOWN; 69 70 mi.flashSz = NANOHUB_MEM_SZ_UNKNOWN; 71 mi.blSz = NANOHUB_MEM_SZ_UNKNOWN; 72 mi.osSz = NANOHUB_MEM_SZ_UNKNOWN; 73 mi.sharedSz = NANOHUB_MEM_SZ_UNKNOWN; 74 mi.eeSz = NANOHUB_MEM_SZ_UNKNOWN; 75 mi.ramSz = NANOHUB_MEM_SZ_UNKNOWN; 76 77 mi.blUse = NANOHUB_MEM_SZ_UNKNOWN; 78 mi.osUse = NANOHUB_MEM_SZ_UNKNOWN; 79 mi.sharedUse = NANOHUB_MEM_SZ_UNKNOWN; 80 mi.eeUse = NANOHUB_MEM_SZ_UNKNOWN; 81 mi.ramUse = NANOHUB_MEM_SZ_UNKNOWN; 82 83 while (buf.getRoom() >= 2) { 84 type = buf.readU8(); 85 len = buf.readU8(); 86 if (buf.getRoom() >= len) { 87 switch(type) { 88 case NANOHUB_HAL_SYS_INFO_HEAP_FREE: 89 if (len == sizeof(ramFree)) 90 ramFree = buf.readU32(); 91 else 92 buf.readRaw(len); 93 break; 94 case NANOHUB_HAL_SYS_INFO_RAM_SIZE: 95 if (len == sizeof(mi.ramSz)) 96 mi.ramSz = buf.readU32(); 97 else 98 buf.readRaw(len); 99 break; 100 case NANOHUB_HAL_SYS_INFO_EEDATA_SIZE: 101 if (len == sizeof(mi.ramSz)) 102 mi.eeSz = buf.readU32(); 103 else 104 buf.readRaw(len); 105 break; 106 case NANOHUB_HAL_SYS_INFO_EEDATA_FREE: 107 if (len == sizeof(eeFree)) 108 eeFree = buf.readU32(); 109 else 110 buf.readRaw(len); 111 break; 112 case NANOHUB_HAL_SYS_INFO_CODE_SIZE: 113 if (len == sizeof(mi.osSz)) 114 mi.osSz = buf.readU32(); 115 else 116 buf.readRaw(len); 117 break; 118 case NANOHUB_HAL_SYS_INFO_CODE_FREE: 119 if (len == sizeof(osFree)) 120 osFree = buf.readU32(); 121 else 122 buf.readRaw(len); 123 break; 124 case NANOHUB_HAL_SYS_INFO_SHARED_SIZE: 125 if (len == sizeof(mi.sharedSz)) 126 mi.sharedSz = buf.readU32(); 127 else 128 buf.readRaw(len); 129 break; 130 case NANOHUB_HAL_SYS_INFO_SHARED_FREE: 131 if (len == sizeof(sharedFree)) 132 sharedFree = buf.readU32(); 133 else 134 buf.readRaw(len); 135 break; 136 case NANOHUB_HAL_SYS_INFO_END: 137 if (len != 0 || buf.getRoom() != 0) { 138 ALOGE("%s: failed to read object", __func__); 139 return; 140 } 141 break; 142 default: 143 ALOGI("%s: unsupported type: %d", __func__, type); 144 buf.readRaw(len); 145 break; 146 } 147 } else { 148 ALOGE("%s: failed to read object", __func__); 149 return; 150 } 151 } 152 153 if (buf.getRoom() != 0) { 154 ALOGE("%s: failed to read object", __func__); 155 return; 156 } 157 158 if (mi.ramSz != NANOHUB_MEM_SZ_UNKNOWN && ramFree != NANOHUB_MEM_SZ_UNKNOWN) 159 mi.ramUse = mi.ramSz - ramFree; 160 if (mi.eeSz != NANOHUB_MEM_SZ_UNKNOWN && eeFree != NANOHUB_MEM_SZ_UNKNOWN) 161 mi.eeUse = mi.eeSz - eeFree; 162 if (mi.osSz != NANOHUB_MEM_SZ_UNKNOWN && osFree != NANOHUB_MEM_SZ_UNKNOWN) 163 mi.osUse = mi.osSz - osFree; 164 if (mi.sharedSz != NANOHUB_MEM_SZ_UNKNOWN && sharedFree != NANOHUB_MEM_SZ_UNKNOWN) 165 mi.sharedUse = mi.sharedSz - sharedFree; 166 } 167 168 NanohubRsp::NanohubRsp(MessageBuf &buf, uint32_t transactionId, bool chre) 169 { 170 // all responses start with command and have a 4-byte status (result code) 171 buf.reset(); 172 if (buf.getSize() < 5) { 173 mStatus = -EINVAL; 174 } else { 175 mCmd = buf.readU8(); 176 mStatus = buf.readU32(); 177 if (chre) 178 mTransactionId = transactionId; 179 else 180 mTransactionId = 0; 181 } 182 } 183 184 int SystemComm::sendToSystem(const void *data, size_t len, uint32_t transactionId) 185 { 186 if (NanoHub::messageTracingEnabled()) { 187 dumpBuffer("HAL -> SYS", getSystem()->mHostIfAppName, transactionId, 0, data, len); 188 } 189 return NanoHub::sendToDevice(&getSystem()->mHostIfAppName, data, len, transactionId); 190 } 191 192 inline hub_app_name_t deviceAppNameToHost(const hub_app_name_t src) 193 { 194 hub_app_name_t res = { .id = le64toh(src.id) }; 195 return res; 196 } 197 198 inline hub_app_name_t hostAppNameToDevice(const hub_app_name_t src) 199 { 200 hub_app_name_t res = { .id = htole64(src.id) }; 201 return res; 202 } 203 204 const uint8_t app_info_tags[] = 205 { 206 NANOHUB_HAL_APP_INFO_APPID, 207 NANOHUB_HAL_APP_INFO_CRC, 208 NANOHUB_HAL_APP_INFO_TID, 209 NANOHUB_HAL_APP_INFO_VERSION, 210 NANOHUB_HAL_APP_INFO_ADDR, 211 NANOHUB_HAL_APP_INFO_SIZE, 212 NANOHUB_HAL_APP_INFO_HEAP, 213 NANOHUB_HAL_APP_INFO_DATA, 214 NANOHUB_HAL_APP_INFO_BSS, 215 NANOHUB_HAL_APP_INFO_CHRE_MAJOR, 216 NANOHUB_HAL_APP_INFO_CHRE_MINOR, 217 NANOHUB_HAL_APP_INFO_END, 218 }; 219 220 const uint8_t sys_info_tags[] = 221 { 222 NANOHUB_HAL_SYS_INFO_HEAP_FREE, 223 NANOHUB_HAL_SYS_INFO_RAM_SIZE, 224 NANOHUB_HAL_SYS_INFO_EEDATA_SIZE, 225 NANOHUB_HAL_SYS_INFO_EEDATA_FREE, 226 NANOHUB_HAL_SYS_INFO_CODE_SIZE, 227 NANOHUB_HAL_SYS_INFO_CODE_FREE, 228 NANOHUB_HAL_SYS_INFO_SHARED_SIZE, 229 NANOHUB_HAL_SYS_INFO_SHARED_FREE, 230 NANOHUB_HAL_SYS_INFO_END, 231 }; 232 233 int SystemComm::MemInfoSession::setup(const hub_message_t *, uint32_t transactionId, AppManager &) 234 { 235 std::lock_guard<std::mutex> _l(mLock); 236 char data[MAX_RX_PACKET]; 237 MessageBuf buf(data, sizeof(data)); 238 buf.writeU8(NANOHUB_HAL_SYS_INFO); 239 buf.writeRaw(sys_info_tags, sizeof(sys_info_tags)); 240 241 setState(SESSION_USER); 242 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 243 } 244 245 int SystemComm::MemInfoSession::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &, bool chre) 246 { 247 std::lock_guard<std::mutex> _l(mLock); 248 NanohubRsp rsp(buf, transactionId, chre); 249 250 if (rsp.mCmd != NANOHUB_HAL_SYS_INFO) 251 return 1; 252 253 size_t len = buf.getRoom(); 254 255 if (getState() != SESSION_USER) { 256 ALOGE("%s: Invalid state; have %d, need %d", __func__, getState(), SESSION_USER); 257 return -EINVAL; 258 } 259 260 std::vector<mem_range_t> ranges; 261 ranges.reserve(4); 262 if (len) { 263 NanohubMemInfo mi; 264 readNanohubMemInfo(buf, mi); 265 266 //if each is valid, copy to output area 267 if (mi.sharedSz != NANOHUB_MEM_SZ_UNKNOWN && 268 mi.sharedUse != NANOHUB_MEM_SZ_UNKNOWN) 269 ranges.push_back({ 270 .type = HUB_MEM_TYPE_MAIN, 271 .total_bytes = mi.sharedSz, 272 .free_bytes = mi.sharedSz - mi.sharedUse, 273 }); 274 275 if (mi.osSz != NANOHUB_MEM_SZ_UNKNOWN && 276 mi.osUse != NANOHUB_MEM_SZ_UNKNOWN) 277 ranges.push_back({ 278 .type = HUB_MEM_TYPE_OS, 279 .total_bytes = mi.osSz, 280 .free_bytes = mi.osSz - mi.osUse, 281 }); 282 283 if (mi.eeSz != NANOHUB_MEM_SZ_UNKNOWN && 284 mi.eeUse != NANOHUB_MEM_SZ_UNKNOWN) 285 ranges.push_back({ 286 .type = HUB_MEM_TYPE_EEDATA, 287 .total_bytes = mi.eeSz, 288 .free_bytes = mi.eeSz - mi.eeUse, 289 }); 290 291 if (mi.ramSz != NANOHUB_MEM_SZ_UNKNOWN && 292 mi.ramUse != NANOHUB_MEM_SZ_UNKNOWN) 293 ranges.push_back({ 294 .type = HUB_MEM_TYPE_RAM, 295 .total_bytes = mi.ramSz, 296 .free_bytes = mi.ramSz - mi.ramUse, 297 }); 298 } 299 300 //send it out 301 sendToApp(CONTEXT_HUB_QUERY_MEMORY, transactionId, 302 static_cast<const void *>(ranges.data()), 303 ranges.size() * sizeof(ranges[0])); 304 305 complete(); 306 return 0; 307 } 308 309 int SystemComm::AppMgmtSession::setup(const hub_message_t *appMsg, uint32_t transactionId, AppManager &appManager) 310 { 311 std::lock_guard<std::mutex> _l(mLock); 312 313 char data[MAX_RX_PACKET]; 314 MessageBuf buf(data, sizeof(data)); 315 const uint8_t *msgData = static_cast<const uint8_t*>(appMsg->message); 316 317 mCmd = appMsg->message_type; 318 mLen = appMsg->message_len; 319 mPos = 0; 320 mNextPos = 0; 321 mErrCnt = 0; 322 323 switch (mCmd) { 324 case CONTEXT_HUB_APPS_ENABLE: 325 return setupMgmt(appMsg, transactionId, NANOHUB_HAL_APP_MGMT_START, appManager); 326 case CONTEXT_HUB_APPS_DISABLE: 327 return setupMgmt(appMsg, transactionId, NANOHUB_HAL_APP_MGMT_STOP, appManager); 328 case CONTEXT_HUB_UNLOAD_APP: 329 return setupMgmt(appMsg, transactionId, NANOHUB_HAL_APP_MGMT_UNLOAD, appManager); 330 case CONTEXT_HUB_LOAD_APP: 331 { 332 const load_app_request_t *appReq = static_cast<const load_app_request_t*>(appMsg->message); 333 if (appReq == nullptr || mLen <= sizeof(*appReq)) { 334 ALOGE("%s: Invalid app header: too short\n", __func__); 335 return -EINVAL; 336 } 337 mAppName = appReq->app_binary.app_id; 338 if (!appManager.isAppLoaded(mAppName)) { 339 appManager.addNewApp(mAppName, appReq->app_binary.app_version); 340 appManager.writeApp(mAppName, msgData, mLen); 341 mData.clear(); 342 mData = std::vector<uint8_t>(msgData, msgData + mLen); 343 setState(TRANSFER); 344 345 buf.writeU8(NANOHUB_HAL_START_UPLOAD); 346 buf.writeU8(0); 347 buf.writeU32(mLen); 348 349 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 350 } else { 351 if (appManager.cmpApp(mAppName, msgData, mLen)) { 352 mFlashAddr = appManager.getFlashAddr(mAppName); 353 if (appManager.isAppRunning(mAppName)) { 354 setState(STOP_RUN); 355 356 buf.writeU8(NANOHUB_HAL_APP_MGMT); 357 writeAppName(buf, mAppName); 358 buf.writeU8(NANOHUB_HAL_APP_MGMT_STOP); 359 360 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 361 } else { 362 setState(RUN); 363 364 buf.writeU8(NANOHUB_HAL_APP_MGMT); 365 writeAppName(buf, mAppName); 366 buf.writeU8(NANOHUB_HAL_APP_MGMT_START); 367 368 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 369 } 370 } else { 371 appManager.setCachedVersion(mAppName, appReq->app_binary.app_version); 372 appManager.writeApp(mAppName, msgData, mLen); 373 mData.clear(); 374 mData = std::vector<uint8_t>(msgData, msgData + mLen); 375 if (appManager.isAppRunning(mAppName)) { 376 setState(STOP_TRANSFER); 377 378 buf.writeU8(NANOHUB_HAL_APP_MGMT); 379 writeAppName(buf, mAppName); 380 buf.writeU8(NANOHUB_HAL_APP_MGMT_STOP); 381 382 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 383 } else { 384 setState(TRANSFER); 385 386 buf.writeU8(NANOHUB_HAL_START_UPLOAD); 387 buf.writeU8(0); 388 buf.writeU32(mLen); 389 390 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 391 } 392 } 393 } 394 } 395 case CONTEXT_HUB_OS_REBOOT: 396 setState(REBOOT); 397 398 buf.writeU8(NANOHUB_HAL_SYS_MGMT); 399 buf.writeU8(NANOHUB_HAL_SYS_MGMT_REBOOT); 400 401 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 402 403 case CONTEXT_HUB_START_APPS: 404 if (mLen == sizeof(mStatus)) 405 memcpy(&mStatus, msgData, mLen); 406 appManager.eraseApps(); 407 setState(QUERY_START); 408 409 buf.writeU8(NANOHUB_HAL_APP_INFO); 410 buf.writeU32(0); 411 buf.writeRaw(app_info_tags, sizeof(app_info_tags)); 412 413 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 414 } 415 416 return -EINVAL; 417 } 418 419 int SystemComm::AppMgmtSession::setupMgmt(const hub_message_t *appMsg, uint32_t transactionId, uint32_t cmd, AppManager &appManager) 420 { 421 int32_t result = -1; // results are only directly returned on failure 422 const hub_app_name_t &appName = *static_cast<const hub_app_name_t*>(appMsg->message); 423 if (appMsg->message_len != sizeof(appName)) { 424 return -EINVAL; 425 } 426 mAppName = appName; 427 428 switch (cmd) { 429 case NANOHUB_HAL_APP_MGMT_START: 430 if (appManager.isAppRunning(mAppName)) { 431 appManager.setCachedStart(mAppName, true); 432 sendToApp(mCmd, transactionId, &result, sizeof(result)); 433 complete(); 434 return 0; 435 } 436 break; 437 case NANOHUB_HAL_APP_MGMT_STOP: 438 case NANOHUB_HAL_APP_MGMT_UNLOAD: 439 appManager.setCachedStart(mAppName, false); 440 if (!appManager.isAppRunning(mAppName)) { 441 sendToApp(mCmd, transactionId, &result, sizeof(result)); 442 complete(); 443 return 0; 444 } 445 break; 446 } 447 char data[MAX_RX_PACKET]; 448 MessageBuf buf(data, sizeof(data)); 449 buf.writeU8(NANOHUB_HAL_APP_MGMT); 450 writeAppName(buf, appName); 451 buf.writeU8(cmd); 452 setState(MGMT); 453 454 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 455 } 456 457 int SystemComm::AppMgmtSession::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre) 458 { 459 int ret = 0; 460 std::lock_guard<std::mutex> _l(mLock); 461 NanohubRsp rsp(buf, transactionId, chre); 462 463 switch (getState()) { 464 case TRANSFER: 465 ret = handleTransfer(rsp, buf, appManager); 466 break; 467 case STOP_TRANSFER: 468 ret = handleStopTransfer(rsp, buf, appManager); 469 break; 470 case QUERY_START: 471 ret = handleQueryStart(rsp, buf, appManager); 472 break; 473 case START: 474 ret = handleStart(rsp, buf, appManager); 475 break; 476 case FINISH: 477 ret = handleFinish(rsp, buf, appManager); 478 break; 479 case RUN: 480 ret = handleRun(rsp, buf, appManager); 481 break; 482 case STOP_RUN: 483 ret = handleStopRun(rsp, buf, appManager); 484 break; 485 case REBOOT: 486 ret = handleReboot(rsp, buf, appManager); 487 break; 488 case ERASE_TRANSFER: 489 ret = handleEraseTransfer(rsp, buf, appManager); 490 break; 491 case MGMT: 492 ret = handleMgmt(rsp, buf, appManager); 493 break; 494 case INFO: 495 ret = handleInfo(rsp, buf, appManager); 496 break; 497 } 498 499 return ret; 500 } 501 502 int SystemComm::AppMgmtSession::handleTransfer(NanohubRsp &rsp, MessageBuf &, AppManager &appManager) 503 { 504 if (rsp.mCmd != NANOHUB_HAL_CONT_UPLOAD && rsp.mCmd != NANOHUB_HAL_START_UPLOAD) 505 return 1; 506 507 char data[MAX_RX_PACKET]; 508 MessageBuf buf(data, sizeof(data)); 509 int32_t result = 0; 510 511 static_assert(NANOHUB_UPLOAD_CHUNK_SZ_MAX <= (MAX_RX_PACKET-5), 512 "Invalid chunk size"); 513 514 if (rsp.mStatus == NANOHUB_HAL_UPLOAD_ACCEPTED) { 515 mPos = mNextPos; 516 mErrCnt = 0; 517 } else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_RESEND) { 518 mErrCnt ++; 519 } else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_RESTART) { 520 mPos = 0; 521 mErrCnt ++; 522 } else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_CANCEL || 523 rsp.mStatus == NANOHUB_HAL_UPLOAD_CANCEL_NO_RETRY) { 524 mPos = mLen; 525 result = NANOHUB_APP_NOT_LOADED; 526 } else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_NO_SPACE) { 527 mPos = 0; 528 mErrCnt = 0; 529 setState(ERASE_TRANSFER); 530 531 buf.writeU8(NANOHUB_HAL_SYS_MGMT); 532 buf.writeU8(NANOHUB_HAL_SYS_MGMT_ERASE); 533 534 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 535 } else if (mErrCnt > 5) { 536 mPos = mLen; 537 result = NANOHUB_APP_NOT_LOADED; 538 } else { 539 mErrCnt ++; 540 } 541 542 if (result != 0) { 543 appManager.clearCachedApp(mAppName); 544 545 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 546 complete(); 547 return 0; 548 } else if (mPos < mLen) { 549 uint32_t chunkSize = mLen - mPos; 550 551 if (chunkSize > NANOHUB_UPLOAD_CHUNK_SZ_MAX) { 552 chunkSize = NANOHUB_UPLOAD_CHUNK_SZ_MAX; 553 } 554 555 buf.writeU8(NANOHUB_HAL_CONT_UPLOAD); 556 buf.writeU32(mPos); 557 buf.writeRaw(&mData[mPos], chunkSize); 558 mNextPos = mPos + chunkSize; 559 } else { 560 buf.writeU8(NANOHUB_HAL_FINISH_UPLOAD); 561 setState(FINISH); 562 } 563 564 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 565 } 566 567 int SystemComm::AppMgmtSession::handleStopTransfer(NanohubRsp &rsp, MessageBuf &buf, AppManager &) 568 { 569 if (rsp.mCmd != NANOHUB_HAL_APP_MGMT) 570 return 1; 571 572 uint8_t cmd = buf.readU8(); 573 574 if (cmd != NANOHUB_HAL_APP_MGMT_STOP) 575 return 1; 576 577 MgmtStatus sts = { .value = buf.readU32() }; 578 579 ALOGI("Nanohub NEW APP STOP: %08" PRIX32 "\n", sts.value); 580 if (rsp.mStatus == 0) { 581 char data[MAX_RX_PACKET]; 582 MessageBuf buf(data, sizeof(data)); 583 setState(TRANSFER); 584 585 buf.writeU8(NANOHUB_HAL_START_UPLOAD); 586 buf.writeU8(0); 587 buf.writeU32(mLen); 588 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 589 } else { 590 int32_t result = NANOHUB_APP_NOT_LOADED; 591 592 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 593 complete(); 594 return 0; 595 } 596 } 597 598 int SystemComm::AppMgmtSession::handleQueryStart(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager) 599 { 600 601 if (rsp.mCmd != NANOHUB_HAL_APP_INFO) 602 return 1; 603 604 size_t len = buf.getRoom(); 605 if (len) { 606 uint32_t nextAddr = appManager.readNanohubAppInfo(buf); 607 608 if (nextAddr) { 609 char data[MAX_RX_PACKET]; 610 MessageBuf buf(data, sizeof(data)); 611 612 buf.writeU8(NANOHUB_HAL_APP_INFO); 613 buf.writeU32(nextAddr); 614 buf.writeRaw(app_info_tags, sizeof(app_info_tags)); 615 616 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 617 } 618 } 619 620 appManager.getAppsToStart(mAppList); 621 if (mAppList.empty()) { 622 sendToApp(CONTEXT_HUB_OS_REBOOT, 0, &mStatus, sizeof(mStatus)); 623 complete(); 624 return 0; 625 } else { 626 char data[MAX_RX_PACKET]; 627 MessageBuf buf(data, sizeof(data)); 628 mAppName = mAppList.back(); 629 mAppList.pop_back(); 630 setState(START); 631 632 buf.writeU8(NANOHUB_HAL_APP_MGMT); 633 writeAppName(buf, mAppName); 634 buf.writeU8(NANOHUB_HAL_APP_MGMT_START); 635 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 636 } 637 } 638 639 int SystemComm::AppMgmtSession::handleStart(NanohubRsp &rsp, MessageBuf &buf, AppManager &) 640 { 641 if (rsp.mCmd != NANOHUB_HAL_APP_MGMT) 642 return 1; 643 644 uint8_t cmd = buf.readU8(); 645 646 if (cmd != NANOHUB_HAL_APP_MGMT_START) 647 return 1; 648 649 MgmtStatus sts = { .value = buf.readU32() }; 650 651 ALOGI("Nanohub EXISTING APP START: %08" PRIX32 "\n", sts.value); 652 if (mAppList.empty()) { 653 sendToApp(CONTEXT_HUB_OS_REBOOT, 0, &mStatus, sizeof(mStatus)); 654 complete(); 655 return 0; 656 } else { 657 char data[MAX_RX_PACKET]; 658 MessageBuf buf(data, sizeof(data)); 659 mAppName = mAppList.back(); 660 mAppList.pop_back(); 661 662 buf.writeU8(NANOHUB_HAL_APP_MGMT); 663 writeAppName(buf, mAppName); 664 buf.writeU8(NANOHUB_HAL_APP_MGMT_START); 665 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 666 } 667 } 668 669 int SystemComm::AppMgmtSession::handleFinish(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager) 670 { 671 if (rsp.mCmd != NANOHUB_HAL_FINISH_UPLOAD) 672 return 1; 673 674 mFlashAddr = buf.readU32(); 675 uint32_t crc = buf.readU32(); 676 mData.clear(); 677 678 if (rsp.mStatus == 0) { 679 appManager.setCachedCrc(mAppName, crc); 680 char data[MAX_RX_PACKET]; 681 MessageBuf buf(data, sizeof(data)); 682 setState(RUN); 683 684 buf.writeU8(NANOHUB_HAL_APP_MGMT); 685 writeAppName(buf, mAppName); 686 buf.writeU8(NANOHUB_HAL_APP_MGMT_START); 687 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 688 } else { 689 int32_t result = NANOHUB_APP_NOT_LOADED; 690 appManager.clearCachedApp(mAppName); 691 692 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 693 complete(); 694 return 0; 695 } 696 } 697 698 int SystemComm::AppMgmtSession::handleRun(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager) 699 { 700 if (rsp.mCmd != NANOHUB_HAL_APP_MGMT) 701 return 1; 702 703 uint8_t cmd = buf.readU8(); 704 705 if (cmd != NANOHUB_HAL_APP_MGMT_START) 706 return 1; 707 708 MgmtStatus sts = { .value = buf.readU32() }; 709 710 ALOGI("Nanohub NEW APP START: %08" PRIX32 "\n", sts.value); 711 if (rsp.mStatus == 0) { 712 appManager.setCachedStart(mAppName, true); 713 char data[MAX_RX_PACKET]; 714 MessageBuf buf(data, sizeof(data)); 715 setState(INFO); 716 717 buf.writeU8(NANOHUB_HAL_APP_INFO); 718 buf.writeU32(mFlashAddr); 719 buf.writeRaw(app_info_tags, sizeof(app_info_tags)); 720 721 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 722 } else { 723 appManager.setCachedStart(mAppName, false); 724 int32_t result = NANOHUB_APP_NOT_LOADED; 725 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 726 complete(); 727 return 0; 728 } 729 } 730 731 int SystemComm::AppMgmtSession::handleInfo(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager) 732 { 733 if (rsp.mCmd != NANOHUB_HAL_APP_INFO) 734 return 1; 735 int32_t result = 0; 736 size_t len = buf.getRoom(); 737 if (len) { 738 appManager.readNanohubAppInfo(buf); 739 appManager.saveApps(); 740 } 741 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 742 complete(); 743 return 0; 744 } 745 746 int SystemComm::AppMgmtSession::handleStopRun(NanohubRsp &rsp, MessageBuf &buf, AppManager &) 747 { 748 if (rsp.mCmd != NANOHUB_HAL_APP_MGMT) 749 return 1; 750 751 uint8_t cmd = buf.readU8(); 752 753 if (cmd != NANOHUB_HAL_APP_MGMT_STOP) 754 return 1; 755 756 MgmtStatus sts = { .value = buf.readU32() }; 757 758 ALOGI("Nanohub NEW APP STOP: %08" PRIX32 "\n", sts.value); 759 if (rsp.mStatus == 0) { 760 char data[MAX_RX_PACKET]; 761 MessageBuf buf(data, sizeof(data)); 762 setState(RUN); 763 764 buf.writeU8(NANOHUB_HAL_APP_MGMT); 765 writeAppName(buf, mAppName); 766 buf.writeU8(NANOHUB_HAL_APP_MGMT_START); 767 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 768 } else { 769 int32_t result = NANOHUB_APP_NOT_LOADED; 770 771 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 772 complete(); 773 return 0; 774 } 775 } 776 777 /* reboot notification, when triggered by App request */ 778 int SystemComm::AppMgmtSession::handleReboot(NanohubRsp &rsp, MessageBuf &buf, AppManager &) 779 { 780 if (rsp.mCmd != NANOHUB_HAL_SYS_MGMT) 781 return 1; 782 783 uint8_t cmd = buf.readU8(); 784 785 if (cmd == NANOHUB_HAL_SYS_MGMT_REBOOT) 786 ALOGI("Nanohub reboot status [USER REQ]: %08" PRIX32 "\n", rsp.mStatus); 787 788 // reboot notification is sent by SessionManager 789 complete(); 790 791 return 0; 792 } 793 794 int SystemComm::AppMgmtSession::handleEraseTransfer(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager) 795 { 796 if (rsp.mCmd != NANOHUB_HAL_SYS_MGMT) 797 return 1; 798 799 uint8_t cmd = buf.readU8(); 800 801 if (cmd == NANOHUB_HAL_SYS_MGMT_ERASE && rsp.mStatus == 0) { 802 char data[MAX_RX_PACKET]; 803 MessageBuf buf(data, sizeof(data)); 804 appManager.eraseApps(); 805 setState(TRANSFER); 806 807 buf.writeU8(NANOHUB_HAL_START_UPLOAD); 808 buf.writeU8(0); 809 buf.writeU32(mLen); 810 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 811 } else { 812 int32_t result = NANOHUB_APP_NOT_LOADED; 813 814 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 815 complete(); 816 return 0; 817 } 818 } 819 820 int SystemComm::AppMgmtSession::handleMgmt(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager) 821 { 822 if (rsp.mCmd != NANOHUB_HAL_APP_MGMT) 823 return 1; 824 825 uint8_t cmd = buf.readU8(); 826 MgmtStatus sts = { .value = buf.readU32() }; 827 828 bool valid = false; 829 830 int32_t result = rsp.mStatus; 831 832 if (result != 0) 833 result = -1; 834 835 switch (cmd) { 836 case NANOHUB_HAL_APP_MGMT_STOP: 837 valid = mCmd == CONTEXT_HUB_APPS_DISABLE; 838 if (valid && rsp.mStatus == 0) 839 appManager.clearRunning(mAppName); 840 break; 841 case NANOHUB_HAL_APP_MGMT_START: 842 valid = mCmd == CONTEXT_HUB_APPS_ENABLE; 843 if (valid && rsp.mStatus == 0) { 844 appManager.setCachedStart(mAppName, true); 845 char data[MAX_RX_PACKET]; 846 MessageBuf buf(data, sizeof(data)); 847 setState(INFO); 848 849 buf.writeU8(NANOHUB_HAL_APP_INFO); 850 buf.writeU32(appManager.getFlashAddr(mAppName)); 851 buf.writeRaw(app_info_tags, sizeof(app_info_tags)); 852 853 return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId); 854 } 855 break; 856 case NANOHUB_HAL_APP_MGMT_UNLOAD: 857 valid = mCmd == CONTEXT_HUB_UNLOAD_APP; 858 if (valid && rsp.mStatus == 0) 859 appManager.clearRunning(mAppName); 860 break; 861 default: 862 return 1; 863 } 864 865 ALOGI("Nanohub MGMT response: CMD=%02X; STATUS=%08" PRIX32, rsp.mCmd, sts.value); 866 if (!valid) { 867 ALOGE("Invalid response for this state: APP CMD=%02X", mCmd); 868 return -EINVAL; 869 } 870 871 sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result)); 872 complete(); 873 return 0; 874 } 875 876 int SystemComm::KeyInfoSession::setup(const hub_message_t *, uint32_t transactionId, AppManager &) { 877 std::lock_guard<std::mutex> _l(mLock); 878 mKeyNum = 0; 879 mKeyOffset = 0; 880 mRsaKeyData.clear(); 881 setState(SESSION_USER); 882 mStatus = -EBUSY; 883 return requestRsaKeys(transactionId); 884 } 885 886 int SystemComm::KeyInfoSession::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &, bool chre) 887 { 888 std::lock_guard<std::mutex> _l(mLock); 889 NanohubRsp rsp(buf, transactionId, chre); 890 891 if (getState() != SESSION_USER) { 892 // invalid state 893 mStatus = -EFAULT; 894 return mStatus; 895 } 896 897 uint32_t keyLen = buf.readU32(); 898 uint32_t dataLen = buf.getRoom(); 899 900 if (dataLen) { 901 mRsaKeyData.insert(mRsaKeyData.end(), 902 buf.getData() + buf.getPos(), 903 buf.getData() + buf.getSize()); 904 if (mKeyOffset + dataLen >= keyLen) { 905 mKeyNum++; 906 mKeyOffset = 0; 907 } else { 908 mKeyOffset += dataLen; 909 } 910 return requestRsaKeys(transactionId); 911 } else { 912 mStatus = 0; 913 complete(); 914 return 0; 915 } 916 } 917 918 int SystemComm::KeyInfoSession::requestRsaKeys(uint32_t transactionId) 919 { 920 char data[MAX_RX_PACKET]; 921 MessageBuf buf(data, sizeof(data)); 922 923 buf.writeU8(NANOHUB_HAL_KEY_INFO); 924 buf.writeU32(mKeyNum); 925 buf.writeU32(mKeyOffset); 926 927 return sendToSystem(buf.getData(), buf.getPos(), transactionId); 928 } 929 930 void SystemComm::AppManager::dumpAppInfo(std::string &result) 931 { 932 char buffer[256]; 933 934 for (auto &it : apps_) { 935 uint64_t id = it.first; 936 const auto &app = it.second; 937 938 snprintf(buffer, sizeof(buffer), "App: 0x%016" PRIx64 "\n", id); 939 result.append(buffer); 940 if (app->loaded) { 941 snprintf(buffer, sizeof(buffer), 942 " Version: 0x%08" PRIx32 "\n" 943 " flashAddr: 0x%08" PRIx32 "\n" 944 " Running: %s\n", 945 app->version, 946 app->flashAddr, 947 app->running ? "true" : "false"); 948 result.append(buffer); 949 950 if (app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) { 951 snprintf(buffer, sizeof(buffer), 952 " flashUse: %d\n" 953 " CRC: 0x%08" PRIx32 "\n", 954 app->flashUse, 955 app->crc); 956 result.append(buffer); 957 } 958 959 if (app->running) { 960 snprintf(buffer, sizeof(buffer), 961 " TID: %04x\n" 962 " ramUse: %d\n", 963 app->tid, 964 app->ramUse); 965 result.append(buffer); 966 } 967 968 if (app->chre) { 969 snprintf(buffer, sizeof(buffer), " CHRE: %d.%d\n", 970 app->chre_major, app->chre_minor); 971 result.append(buffer); 972 } 973 } 974 975 if (app->cached_napp) { 976 snprintf(buffer, sizeof(buffer), 977 " Cached Version: 0x%08" PRIx32 "\n" 978 " Cached Start: %s\n" 979 " Cached CRC: 0x%08" PRIx32 "\n", 980 app->cached_version, 981 app->cached_start ? "true" : "false", 982 app->cached_crc); 983 result.append(buffer); 984 } 985 } 986 } 987 988 bool SystemComm::AppManager::saveApps() 989 { 990 mkdir(CHRE_APP_DIR, CHRE_APP_DIR_PERMS); 991 File saved_apps_file(CHRE_APP_SETTINGS, "w"); 992 std::shared_ptr<Json::Value> appsObject(new Json::Value); 993 status_t err; 994 995 if ((err = saved_apps_file.initCheck()) != OK) { 996 ALOGW("saved_apps file open (w) failed %d (%s)", 997 err, 998 strerror(-err)); 999 return false; 1000 } 1001 1002 for (auto &it : apps_) { 1003 uint64_t id = it.first; 1004 const auto &app = it.second; 1005 1006 if (app->cached_napp) { 1007 char hexId[17]; 1008 snprintf(hexId, sizeof(hexId), "%016" PRIX64, id); 1009 Json::Value array(Json::arrayValue); 1010 array[0] = app->cached_version; 1011 array[1] = app->cached_start; 1012 array[2] = app->cached_crc; 1013 (*appsObject)[hexId] = array; 1014 } 1015 } 1016 1017 // Write the JSON string to disk. 1018 Json::StyledWriter writer; 1019 std::string serializedSettings(writer.write(*appsObject)); 1020 size_t size = serializedSettings.size(); 1021 if ((err = saved_apps_file.write(serializedSettings.c_str(), size)) != (ssize_t)size) { 1022 ALOGW("saved_apps file write failed %d (%s)", 1023 err, 1024 strerror(-err)); 1025 return false; 1026 } 1027 1028 return true; 1029 } 1030 1031 bool SystemComm::AppManager::restoreApps() 1032 { 1033 File saved_apps_file(CHRE_APP_SETTINGS, "r"); 1034 std::shared_ptr<Json::Value> appsObject; 1035 status_t err; 1036 1037 if ((err = saved_apps_file.initCheck()) != OK) { 1038 ALOGW("saved_apps file open (r) failed %d (%s)", 1039 err, 1040 strerror(-err)); 1041 return false; 1042 } 1043 1044 off64_t size = saved_apps_file.seekTo(0, SEEK_END); 1045 saved_apps_file.seekTo(0, SEEK_SET); 1046 1047 if (size > 0) { 1048 char *buf = (char *)malloc(size); 1049 CHECK_EQ(saved_apps_file.read(buf, size), (ssize_t)size); 1050 1051 std::string str(buf); 1052 std::shared_ptr<Json::Value> in(new Json::Value); 1053 Json::Reader reader; 1054 bool valid = reader.parse(str, *in); 1055 free(buf); 1056 1057 if (valid && in->isObject()) { 1058 appsObject = in; 1059 } 1060 } 1061 1062 if (appsObject == nullptr) { 1063 appsObject = std::shared_ptr<Json::Value>(new Json::Value(Json::objectValue)); 1064 } 1065 1066 Json::Value::Members apps = appsObject->getMemberNames(); 1067 for (auto &it : apps) { 1068 Json::Value &val = (*appsObject)[it]; 1069 if (val.isArray()) { 1070 uint32_t version = val[0].asUInt(); 1071 uint32_t start = val[1].asUInt(); 1072 uint32_t crc = val[2].asUInt(); 1073 1074 uint64_t id = strtoull(it.c_str(), nullptr, 16); 1075 apps_[id] = std::unique_ptr<AppData>(new AppData); 1076 apps_[id]->loaded = false; 1077 apps_[id]->running = false; 1078 apps_[id]->chre = false; 1079 apps_[id]->cached_napp = true; 1080 apps_[id]->cached_version = version; 1081 apps_[id]->cached_start = start; 1082 apps_[id]->cached_crc = crc; 1083 } 1084 } 1085 1086 return true; 1087 } 1088 1089 bool SystemComm::AppManager::eraseApps() 1090 { 1091 for (auto it=apps_.begin(); it != apps_.end();) { 1092 if (!it->second->cached_napp) 1093 it = apps_.erase(it); 1094 else { 1095 it->second->loaded = false; 1096 it->second->running = false; 1097 it->second->chre = false; 1098 ++it; 1099 } 1100 } 1101 1102 return true; 1103 } 1104 1105 bool SystemComm::AppManager::writeApp(hub_app_name_t &appName, const uint8_t *data, int32_t len) 1106 { 1107 mkdir(CHRE_APP_DIR, CHRE_APP_DIR_PERMS); 1108 char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1]; 1109 1110 snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id); 1111 1112 int fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, CHRE_APP_FILE_PERMS); 1113 if (fd == -1) 1114 return false; 1115 1116 if (write(fd, data, len) == len) { 1117 close(fd); 1118 return true; 1119 } else { 1120 close(fd); 1121 return false; 1122 } 1123 } 1124 1125 int32_t SystemComm::AppManager::readApp(hub_app_name_t &appName, void **data) 1126 { 1127 char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1]; 1128 1129 snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id); 1130 1131 int32_t ret = -1; 1132 *data = nullptr; 1133 int fd = open(file, O_RDONLY); 1134 1135 if (fd >= 0) { 1136 struct stat sb; 1137 if (fstat(fd, &sb) == 0) { 1138 *data = malloc(sb.st_size); 1139 if (*data != nullptr && read(fd, *data, sb.st_size) == sb.st_size) 1140 ret = sb.st_size; 1141 else { 1142 free(*data); 1143 *data = nullptr; 1144 } 1145 } 1146 close(fd); 1147 } 1148 return ret; 1149 } 1150 1151 bool SystemComm::AppManager::cmpApp(hub_app_name_t &appName, const uint8_t *data, uint32_t len) 1152 { 1153 char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1]; 1154 1155 snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id); 1156 1157 if (!isAppLoaded(appName)) 1158 return false; 1159 1160 if ((!apps_[appName.id]->cached_napp) || 1161 (apps_[appName.id]->crc != apps_[appName.id]->cached_crc)) 1162 return false; 1163 1164 bool success = false; 1165 int fd = open(file, O_RDONLY); 1166 1167 if (fd >= 0) { 1168 struct stat sb; 1169 if (fstat(fd, &sb) == 0 && sb.st_size == len) { 1170 void *buf = malloc(len); 1171 if (buf != nullptr && read(fd, buf, sb.st_size) == sb.st_size && memcmp(data, buf, len) == 0) 1172 success = true; 1173 free(buf); 1174 } 1175 close(fd); 1176 } 1177 return success; 1178 } 1179 1180 uint32_t SystemComm::AppManager::readNanohubAppInfo(MessageBuf &buf) 1181 { 1182 hub_app_name_t name; 1183 1184 uint8_t tag, len; 1185 uint32_t ramUse = 0; 1186 bool ramUseValid = true; 1187 1188 // first tag must be the appid 1189 if (buf.getRoom() < 2 + sizeof(name.id)) { 1190 ALOGE("%s: failed to read object", __func__); 1191 return 0; 1192 } 1193 1194 tag = buf.readU8(); 1195 len = buf.readU8(); 1196 if (tag != NANOHUB_HAL_APP_INFO_APPID || len != sizeof(name.id)) { 1197 ALOGE("%s: invalid first tag: %d", __func__, tag); 1198 return 0; 1199 } 1200 1201 readAppName(buf, name); 1202 if (!isAppPresent(name)) { 1203 apps_[name.id] = std::unique_ptr<AppData>(new AppData); 1204 apps_[name.id]->loaded = false; 1205 apps_[name.id]->chre = false; 1206 apps_[name.id]->running = false; 1207 apps_[name.id]->cached_napp = false; 1208 } 1209 const auto &app = apps_[name.id]; 1210 1211 while (buf.getRoom() >= 2) { 1212 tag = buf.readU8(); 1213 len = buf.readU8(); 1214 if (buf.getRoom() >= len) { 1215 switch(tag) { 1216 case NANOHUB_HAL_APP_INFO_CRC: 1217 if (len == 0) 1218 app->crc = 0; 1219 else if (len == sizeof(app->crc)) 1220 app->crc = buf.readU32(); 1221 else 1222 buf.readRaw(len); 1223 break; 1224 case NANOHUB_HAL_APP_INFO_TID: 1225 if (len == 0) { 1226 app->tid = NANOHUB_TID_UNKNOWN; 1227 ramUseValid = false; 1228 app->loaded = true; 1229 app->running = false; 1230 } else if (len == sizeof(app->tid)) { 1231 app->tid = buf.readU32(); 1232 app->loaded = true; 1233 app->running = true; 1234 } else 1235 buf.readRaw(len); 1236 break; 1237 case NANOHUB_HAL_APP_INFO_VERSION: 1238 if (len == sizeof(app->version)) 1239 app->version = buf.readU32(); 1240 else 1241 buf.readRaw(len); 1242 break; 1243 case NANOHUB_HAL_APP_INFO_ADDR: 1244 if (len == sizeof(app->flashAddr)) 1245 app->flashAddr = buf.readU32(); 1246 else 1247 buf.readRaw(len); 1248 break; 1249 case NANOHUB_HAL_APP_INFO_SIZE: 1250 if (len == 0) 1251 app->flashUse = NANOHUB_MEM_SZ_UNKNOWN; 1252 else if (len == sizeof(app->flashUse)) 1253 app->flashUse = buf.readU32(); 1254 else 1255 buf.readRaw(len); 1256 break; 1257 case NANOHUB_HAL_APP_INFO_HEAP: 1258 case NANOHUB_HAL_APP_INFO_DATA: 1259 case NANOHUB_HAL_APP_INFO_BSS: 1260 if (len == 0) 1261 ramUseValid = false; 1262 else if (len == sizeof(uint32_t)) 1263 ramUse += buf.readU32(); 1264 else 1265 buf.readRaw(len); 1266 break; 1267 case NANOHUB_HAL_APP_INFO_CHRE_MAJOR: 1268 if (len == 0) 1269 app->chre = false; 1270 else if (len == sizeof(app->chre_major)) { 1271 app->chre = true; 1272 app->chre_major = buf.readU8(); 1273 } else 1274 buf.readRaw(len); 1275 break; 1276 case NANOHUB_HAL_APP_INFO_CHRE_MINOR: 1277 if (len == 0) 1278 app->chre = false; 1279 else if (len == sizeof(app->chre_minor)) { 1280 app->chre = true; 1281 app->chre_minor = buf.readU8(); 1282 } else 1283 buf.readRaw(len); 1284 break; 1285 case NANOHUB_HAL_APP_INFO_END: 1286 if (len != 0 || buf.getRoom() != 0) { 1287 ALOGE("%s: failed to read object", __func__); 1288 return 0; 1289 } 1290 break; 1291 default: 1292 ALOGI("%s: unsupported tag: %d", __func__, tag); 1293 buf.readRaw(len); 1294 break; 1295 } 1296 } else { 1297 ALOGE("%s: failed to read object", __func__); 1298 return 0; 1299 } 1300 } 1301 1302 if (buf.getRoom() != 0) { 1303 ALOGE("%s: failed to read object", __func__); 1304 return 0; 1305 } 1306 1307 if (ramUseValid) 1308 app->ramUse = ramUse; 1309 else 1310 app->ramUse = NANOHUB_MEM_SZ_UNKNOWN; 1311 1312 return app->flashAddr + 1313 (app->flashUse != NANOHUB_MEM_SZ_UNKNOWN ? ((app->flashUse+3)&~3) : 4); 1314 } 1315 1316 void SystemComm::AppManager::sendAppInfoToApp(uint32_t transactionId) { 1317 std::vector<hub_app_info> appInfo; 1318 for (auto &it : apps_) { 1319 uint64_t id = it.first; 1320 const auto &app = it.second; 1321 1322 // TODO: Still have some non-chre apps that need to be reported 1323 // if (!app->chre || !app->running || app->flashUse == NANOHUB_MEM_SZ_UNKNOWN) 1324 if (!app->running || app->flashUse == NANOHUB_MEM_SZ_UNKNOWN) 1325 continue; 1326 1327 hub_app_info info; 1328 info.app_name = { .id = id }; 1329 info.version = app->version; 1330 info.num_mem_ranges = 0; 1331 if (app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) { 1332 mem_range_t &range = info.mem_usage[info.num_mem_ranges++]; 1333 range.type = HUB_MEM_TYPE_MAIN; 1334 range.total_bytes = app->flashUse; 1335 } 1336 if (app->ramUse != NANOHUB_MEM_SZ_UNKNOWN) { 1337 mem_range_t &range = info.mem_usage[info.num_mem_ranges++]; 1338 range.type = HUB_MEM_TYPE_RAM; 1339 range.total_bytes = app->ramUse; 1340 } 1341 1342 appInfo.push_back(info); 1343 } 1344 sendToApp(CONTEXT_HUB_QUERY_APPS, transactionId, 1345 static_cast<const void *>(appInfo.data()), 1346 appInfo.size() * sizeof(appInfo[0])); 1347 } 1348 1349 int SystemComm::AppManager::getAppsToStart(std::vector<hub_app_name_t> &apps) 1350 { 1351 int cnt = 0; 1352 apps.clear(); 1353 1354 for (auto &it : apps_) { 1355 uint64_t id = it.first; 1356 const auto &app = it.second; 1357 1358 if (app->cached_napp && app->cached_start && app->loaded && 1359 !app->running && app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) { 1360 apps.push_back({ .id = id }); 1361 cnt++; 1362 } 1363 } 1364 1365 return cnt; 1366 } 1367 1368 int SystemComm::doHandleRx(uint64_t appId, uint32_t transactionId, const char *data, int len, bool chre) 1369 { 1370 bool reboot = false; 1371 uint32_t rebootStatus; 1372 //we only care for messages from HostIF 1373 if (appId != mHostIfAppName.id) 1374 return 1; 1375 1376 //they must all be at least 1 byte long 1377 if (!len) { 1378 return -EINVAL; 1379 } 1380 MessageBuf buf(data, len); 1381 if (NanoHub::messageTracingEnabled()) { 1382 dumpBuffer("SYS -> HAL", mHostIfAppName, transactionId, 0, buf.getData(), buf.getSize()); 1383 } 1384 int status = mSessions.handleRx(buf, transactionId, mAppManager, chre, reboot, rebootStatus); 1385 if (status) { 1386 // provide default handler for any system message, that is not properly handled 1387 dumpBuffer(status > 0 ? "HAL (not handled)" : "HAL (error)", 1388 mHostIfAppName, transactionId, 0, buf.getData(), buf.getSize(), status); 1389 status = status > 0 ? 0 : status; 1390 } 1391 if (reboot) { 1392 hub_message_t msg = 1393 { 1394 .app_name.id = appId, 1395 .message_type = CONTEXT_HUB_START_APPS, 1396 .message_len = sizeof(rebootStatus), 1397 .message = &rebootStatus, 1398 }; 1399 1400 status = doHandleTx(&msg, 0xFFFFFFFF); 1401 } 1402 1403 return status; 1404 } 1405 1406 void SystemComm::doDumpAppInfo(std::string &result) 1407 { 1408 mAppManager.dumpAppInfo(result); 1409 } 1410 1411 int SystemComm::SessionManager::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre, bool &reboot, uint32_t &rebootStatus) 1412 { 1413 int status = 1; 1414 std::unique_lock<std::mutex> lk(lock); 1415 1416 // pass message to all active sessions, in arbitrary order 1417 // 1st session that handles the message terminates the loop 1418 for (auto pos = sessions_.begin(); pos != sessions_.end() && status > 0; next(pos)) { 1419 if (!isActive(pos)) { 1420 continue; 1421 } 1422 Session *session = pos->second; 1423 status = session->handleRx(buf, transactionId, appManager, chre); 1424 if (status < 0) { 1425 session->complete(); 1426 } 1427 } 1428 1429 NanohubRsp rsp(buf, transactionId, chre); 1430 if (rsp.mCmd == NANOHUB_HAL_SYS_MGMT) { 1431 uint8_t cmd = buf.readU8(); 1432 1433 if (cmd == NANOHUB_HAL_SYS_MGMT_REBOOT) { 1434 // if this is reboot notification, kill all sessions 1435 for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) { 1436 if (!isActive(pos)) { 1437 continue; 1438 } 1439 Session *session = pos->second; 1440 session->abort(-EINTR); 1441 } 1442 lk.unlock(); 1443 // log the reboot event, if not handled 1444 if (status > 0) { 1445 ALOGW("Nanohub reboot status [UNSOLICITED]: %08" PRIX32, rsp.mStatus); 1446 status = 0; 1447 } 1448 reboot = true; 1449 rebootStatus = rsp.mStatus; 1450 } 1451 } 1452 1453 return status; 1454 } 1455 1456 int SystemComm::SessionManager::setup_and_add(int id, Session *session, const hub_message_t *appMsg, uint32_t transactionId, AppManager &appManager) 1457 { 1458 std::lock_guard<std::mutex> _l(lock); 1459 1460 // scan sessions to release those that are already done 1461 for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) { 1462 continue; 1463 } 1464 1465 if (sessions_.count(id) == 0 && !session->isRunning()) { 1466 sessions_[id] = session; 1467 int ret = session->setup(appMsg, transactionId, appManager); 1468 if (ret < 0) { 1469 session->complete(); 1470 } 1471 return ret; 1472 } 1473 return -EBUSY; 1474 } 1475 1476 int SystemComm::doHandleTx(const hub_message_t *appMsg, uint32_t transactionId) 1477 { 1478 int status = 0; 1479 1480 switch (appMsg->message_type) { 1481 case CONTEXT_HUB_LOAD_APP: 1482 if (!mKeySession.haveKeys()) { 1483 status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mKeySession, appMsg, transactionId, mAppManager); 1484 if (status < 0) { 1485 break; 1486 } 1487 mKeySession.wait(); 1488 status = mKeySession.getStatus(); 1489 if (status < 0) { 1490 break; 1491 } 1492 } 1493 status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg, transactionId, mAppManager); 1494 break; 1495 case CONTEXT_HUB_APPS_ENABLE: 1496 case CONTEXT_HUB_APPS_DISABLE: 1497 case CONTEXT_HUB_UNLOAD_APP: 1498 // all APP-modifying commands share session key, to ensure they can't happen at the same time 1499 status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg, transactionId, mAppManager); 1500 break; 1501 1502 case CONTEXT_HUB_QUERY_APPS: 1503 mAppManager.sendAppInfoToApp(transactionId); 1504 break; 1505 1506 case CONTEXT_HUB_QUERY_MEMORY: 1507 status = mSessions.setup_and_add(CONTEXT_HUB_QUERY_MEMORY, &mMemInfoSession, appMsg, transactionId, mAppManager); 1508 break; 1509 1510 case CONTEXT_HUB_START_APPS: 1511 status = mSessions.setup_and_add(CONTEXT_HUB_START_APPS, &mAppMgmtSession, appMsg, transactionId, mAppManager); 1512 break; 1513 1514 default: 1515 ALOGW("Unknown os message type %u\n", appMsg->message_type); 1516 return -EINVAL; 1517 } 1518 1519 return status; 1520 } 1521 1522 }; // namespace nanohub 1523 1524 }; // namespace android 1525