Home | History | Annotate | Download | only in contexthubhal
      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