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 #ifndef _NANOHUB_SYSTEM_COMMS_H_
     18 #define _NANOHUB_SYSTEM_COMMS_H_
     19 
     20 #include <utils/Condition.h>
     21 
     22 #include <chrono>
     23 #include <condition_variable>
     24 #include <map>
     25 #include <mutex>
     26 #include <vector>
     27 
     28 #include <hardware/context_hub.h>
     29 #include <nanohub/nanohub.h>
     30 
     31 #include "nanohubhal.h"
     32 #include "message_buf.h"
     33 
     34 //rx: return 0 if handled, > 0 if not handled, < 0 if error happened
     35 
     36 #define MSG_HANDLED 0
     37 
     38 //messages to the HostIf nanoapp & their replies (mesages and replies both begin with u8 message_type)
     39 #define NANOHUB_HAL_APP_MGMT      0x10 // (char cmd, u64 appId, u64 appMsk) -> (int errno, u32 results)
     40 
     41 #define NANOHUB_HAL_APP_MGMT_START      0
     42 #define NANOHUB_HAL_APP_MGMT_STOP       1
     43 #define NANOHUB_HAL_APP_MGMT_UNLOAD     2
     44 #define NANOHUB_HAL_APP_MGMT_DELETE     3
     45 
     46 #define NANOHUB_HAL_SYS_MGMT      0x11 // (char cmd) -> (int errno)
     47 
     48 #define NANOHUB_HAL_SYS_MGMT_ERASE      0
     49 #define NANOHUB_HAL_SYS_MGMT_REBOOT     1
     50 
     51 #define NANOHUB_HAL_APP_INFO      0x12
     52 
     53 #define NANOHUB_HAL_APP_INFO_APPID          0x00
     54 #define NANOHUB_HAL_APP_INFO_CRC            0x01
     55 #define NANOHUB_HAL_APP_INFO_TID            0x02
     56 #define NANOHUB_HAL_APP_INFO_VERSION        0x03
     57 #define NANOHUB_HAL_APP_INFO_ADDR           0x04
     58 #define NANOHUB_HAL_APP_INFO_SIZE           0x05
     59 #define NANOHUB_HAL_APP_INFO_HEAP           0x06
     60 #define NANOHUB_HAL_APP_INFO_DATA           0x07
     61 #define NANOHUB_HAL_APP_INFO_BSS            0x08
     62 #define NANOHUB_HAL_APP_INFO_CHRE_MAJOR     0x09
     63 #define NANOHUB_HAL_APP_INFO_CHRE_MINOR     0x0A
     64 #define NANOHUB_HAL_APP_INFO_END            0xFF
     65 
     66 #define NANOHUB_HAL_SYS_INFO      0x13
     67 
     68 #define NANOHUB_HAL_SYS_INFO_HEAP_FREE      0x0F
     69 #define NANOHUB_HAL_SYS_INFO_RAM_SIZE       0x12
     70 #define NANOHUB_HAL_SYS_INFO_EEDATA_SIZE    0x13
     71 #define NANOHUB_HAL_SYS_INFO_EEDATA_FREE    0x14
     72 #define NANOHUB_HAL_SYS_INFO_CODE_SIZE      0x15
     73 #define NANOHUB_HAL_SYS_INFO_CODE_FREE      0x16
     74 #define NANOHUB_HAL_SYS_INFO_SHARED_SIZE    0x17
     75 #define NANOHUB_HAL_SYS_INFO_SHARED_FREE    0x18
     76 #define NANOHUB_HAL_SYS_INFO_END            0xFF
     77 
     78 #define NANOHUB_HAL_KEY_INFO      0x14
     79 #define NANOHUB_HAL_START_UPLOAD  0x16
     80 #define NANOHUB_HAL_CONT_UPLOAD   0x17
     81 #define NANOHUB_HAL_FINISH_UPLOAD 0x18
     82 
     83 #define NANOHUB_HAL_UPLOAD_ACCEPTED         0
     84 #define NANOHUB_HAL_UPLOAD_WAIT             1
     85 #define NANOHUB_HAL_UPLOAD_RESEND           2
     86 #define NANOHUB_HAL_UPLOAD_RESTART          3
     87 #define NANOHUB_HAL_UPLOAD_CANCEL           4
     88 #define NANOHUB_HAL_UPLOAD_CANCEL_NO_RETRY  5
     89 #define NANOHUB_HAL_UPLOAD_NO_SPACE         6
     90 
     91 #define NANOHUB_APP_NOT_LOADED  (-1)
     92 #define NANOHUB_APP_LOADED      (0)
     93 
     94 #define NANOHUB_UPLOAD_CHUNK_SZ_MAX 64
     95 #define NANOHUB_MEM_SZ_UNKNOWN      0xFFFFFFFFUL
     96 #define NANOHUB_TID_UNKNOWN         0xFFFFFFFFUL
     97 
     98 #define CONTEXT_HUB_START_APPS      8
     99 
    100 namespace android {
    101 
    102 namespace nanohub {
    103 
    104 int system_comms_handle_rx(const nano_message_raw *msg);
    105 int system_comms_handle_tx(const hub_message_t *outMsg);
    106 
    107 struct MgmtStatus {
    108     union {
    109         uint32_t value;
    110         struct {
    111             uint8_t app;
    112             uint8_t task;
    113             uint8_t op;
    114             uint8_t erase;
    115         } __attribute__((packed));
    116     };
    117 } __attribute__((packed));
    118 
    119 struct NanohubMemInfo {
    120     //sizes
    121     uint32_t flashSz, blSz, osSz, sharedSz, eeSz;
    122     uint32_t ramSz;
    123 
    124     //use
    125     uint32_t blUse, osUse, sharedUse, eeUse;
    126     uint32_t ramUse;
    127 } __attribute__((packed));
    128 
    129 struct NanohubRsp {
    130     uint32_t mCmd;
    131     uint32_t mTransactionId;
    132     int32_t mStatus;
    133     explicit NanohubRsp(MessageBuf &buf, uint32_t transactionId, bool chre);
    134 };
    135 
    136 inline bool operator == (const hub_app_name_t &a, const hub_app_name_t &b) {
    137     return a.id == b.id;
    138 }
    139 
    140 inline bool operator != (const hub_app_name_t &a, const hub_app_name_t &b) {
    141     return !(a == b);
    142 }
    143 
    144 class SystemComm {
    145 private:
    146 
    147     class AppManager;
    148 
    149     /*
    150      * Nanohub HAL sessions
    151      *
    152      * Session is an object that can group several message exchanges with FW,
    153      * maintain state, and be waited for completion by someone else.
    154      *
    155      * As of this moment, since all sessions are triggered by client thread,
    156      * and all the exchange is happening in local worker thread, it is only possible
    157      * for client thread to wait on session completion.
    158      * Allowing sessions to wait on each other will require a worker thread pool.
    159      * It is now unnecessary, and not implemented.
    160      */
    161     class ISession {
    162     public:
    163         virtual int setup(const hub_message_t *app_msg, uint32_t transactionId, AppManager &appManager) = 0;
    164         virtual int handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre) = 0;
    165         virtual int getState() const = 0; // FSM state
    166         virtual int getStatus() const = 0; // execution status (result code)
    167         virtual void abort(int32_t) = 0;
    168         virtual ~ISession() {}
    169     };
    170 
    171     class SessionManager;
    172 
    173     class Session : public ISession {
    174         friend class SessionManager;
    175 
    176         mutable std::mutex mDoneMutex; // controls condition and state transitions
    177         std::condition_variable mDoneCond;
    178         volatile int mState;
    179 
    180     protected:
    181         mutable std::mutex mLock; // serializes message handling
    182         int32_t mStatus;
    183 
    184         enum {
    185             SESSION_INIT = 0,
    186             SESSION_DONE = 1,
    187             SESSION_USER = 2,
    188         };
    189 
    190         void complete() {
    191             std::unique_lock<std::mutex> lk(mDoneMutex);
    192             if (mState != SESSION_DONE) {
    193                 mState = SESSION_DONE;
    194                 lk.unlock();
    195                 mDoneCond.notify_all();
    196             }
    197         }
    198         void abort(int32_t status) {
    199             std::lock_guard<std::mutex> _l(mLock);
    200             mStatus = status;
    201             complete();
    202         }
    203         void setState(int state) {
    204             if (state == SESSION_DONE) {
    205                 complete();
    206             } else {
    207                 std::lock_guard<std::mutex> _l(mDoneMutex);
    208                 mState = state;
    209             }
    210         }
    211     public:
    212         Session() { mState = SESSION_INIT; mStatus = -1; }
    213         int getStatus() const {
    214             std::lock_guard<std::mutex> _l(mLock);
    215             return mStatus;
    216         }
    217         int wait() {
    218             std::unique_lock<std::mutex> lk(mDoneMutex);
    219             bool success = mDoneCond.wait_for(
    220                     lk, std::chrono::seconds(30),
    221                     [this] { return mState == SESSION_DONE; });
    222             if (!success) {
    223                 ALOGE("Timed out waiting for response");
    224             }
    225             return success ? 0 : -1;
    226         }
    227         virtual int getState() const override {
    228             std::lock_guard<std::mutex> _l(mDoneMutex);
    229             return mState;
    230         }
    231         virtual bool isDone() const {
    232             std::lock_guard<std::mutex> _l(mDoneMutex);
    233             return mState == SESSION_DONE;
    234         }
    235         virtual bool isRunning() const {
    236             std::lock_guard<std::mutex> _l(mDoneMutex);
    237             return mState > SESSION_DONE;
    238         }
    239     };
    240 
    241     class AppMgmtSession : public Session {
    242         enum {
    243             TRANSFER = SESSION_USER,
    244             QUERY_START,
    245             START,
    246             STOP_TRANSFER,
    247             FINISH,
    248             RUN,
    249             STOP_RUN,
    250             RUN_FAILED,
    251             REBOOT,
    252             ERASE_TRANSFER,
    253             MGMT,
    254             INFO,
    255         };
    256         uint32_t mCmd; // LOAD_APP, UNLOAD_APP, ENABLE_APP, DISABLE_APP
    257         uint32_t mResult;
    258         std::vector<uint8_t> mData;
    259         uint32_t mLen;
    260         uint32_t mPos;
    261         uint32_t mNextPos;
    262         uint32_t mErrCnt;
    263         hub_app_name_t mAppName;
    264         uint32_t mFlashAddr;
    265         std::vector<hub_app_name_t> mAppList;
    266 
    267         int setupMgmt(const hub_message_t *appMsg, uint32_t transactionId, uint32_t cmd, AppManager &appManager);
    268         int handleTransfer(NanohubRsp &rsp, MessageBuf &, AppManager &appManager);
    269         int handleStopTransfer(NanohubRsp &rsp, MessageBuf &buf, AppManager &);
    270         int handleQueryStart(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager);
    271         int handleStart(NanohubRsp &rsp, MessageBuf &buf, AppManager &);
    272         int handleFinish(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager);
    273         int handleRun(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager);
    274         int handleStopRun(NanohubRsp &rsp, MessageBuf &buf, AppManager &);
    275         int handleReboot(NanohubRsp &rsp, MessageBuf &buf, AppManager &);
    276         int handleEraseTransfer(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager);
    277         int handleMgmt(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager);
    278         int handleInfo(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager);
    279     public:
    280         AppMgmtSession() {
    281             mCmd = 0;
    282             mResult = 0;
    283             mPos = 0;
    284             mLen = 0;
    285             memset(&mAppName, 0, sizeof(mAppName));
    286         }
    287         virtual int handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre) override;
    288         virtual int setup(const hub_message_t *app_msg, uint32_t transactionId, AppManager &appManager) override;
    289     };
    290 
    291     class MemInfoSession : public Session {
    292     public:
    293         virtual int setup(const hub_message_t *app_msg, uint32_t transactionId, AppManager &) override;
    294         virtual int handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &, bool chre) override;
    295     };
    296 
    297     class KeyInfoSession  : public Session {
    298         std::vector<uint8_t> mRsaKeyData;
    299         uint32_t mKeyNum;
    300         uint32_t mKeyOffset;
    301         int requestRsaKeys(uint32_t transactionId);
    302     public:
    303         virtual int setup(const hub_message_t *, uint32_t, AppManager &) override;
    304         virtual int handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &, bool chre) override;
    305         bool haveKeys() const {
    306             std::lock_guard<std::mutex> _l(mLock);
    307             return mRsaKeyData.size() > 0 && !isRunning();
    308         }
    309     };
    310 
    311     class AppManager {
    312         struct AppData {
    313             uint32_t version, flashUse, ramUse;
    314             uint32_t tid, crc, flashAddr;
    315             uint8_t chre_major, chre_minor;
    316             bool chre, running, loaded;
    317 
    318             bool cached_start, cached_napp;
    319             uint32_t cached_version, cached_crc;
    320         };
    321 
    322         typedef std::map<uint64_t, std::unique_ptr<AppData>> AppMap;
    323 
    324         AppMap apps_;
    325 
    326     public:
    327         AppManager() {
    328             restoreApps();
    329         }
    330         void dumpAppInfo(std::string &result);
    331         bool saveApps();
    332         bool restoreApps();
    333         bool eraseApps();
    334         bool writeApp(hub_app_name_t &appName, const uint8_t *data, int32_t len);
    335         int32_t readApp(hub_app_name_t &appName, void **data);
    336         bool cmpApp(hub_app_name_t &appName, const uint8_t *data, uint32_t len);
    337         uint32_t readNanohubAppInfo(MessageBuf &buf);
    338         void sendAppInfoToApp(uint32_t transactionId);
    339         int getAppsToStart(std::vector<hub_app_name_t> &apps);
    340         bool setCachedCrc(hub_app_name_t &appName, uint32_t crc) {
    341             if (!isAppPresent(appName))
    342                 return false;
    343             else {
    344                 apps_[appName.id]->cached_napp = true;
    345                 apps_[appName.id]->cached_crc = crc;
    346                 apps_[appName.id]->cached_start = false;
    347                 saveApps();
    348                 return true;
    349             }
    350         }
    351         bool clearCachedApp(hub_app_name_t &appName) {
    352             if (!isAppPresent(appName))
    353                 return false;
    354             else {
    355                 apps_[appName.id]->cached_napp = false;
    356                 apps_[appName.id]->cached_start = false;
    357                 saveApps();
    358                 return true;
    359             }
    360         }
    361         bool clearRunning(hub_app_name_t &appName) {
    362             if (!isAppLoaded(appName))
    363                 return false;
    364             else {
    365                 apps_[appName.id]->running = false;
    366                 return true;
    367             }
    368         }
    369 
    370         bool setCachedVersion(hub_app_name_t &appName, uint32_t version) {
    371             if (!isAppPresent(appName))
    372                 return false;
    373             else {
    374                 apps_[appName.id]->cached_version = version;
    375                 return true;
    376             }
    377         }
    378         bool setCachedStart(hub_app_name_t &appName, bool start) {
    379             if (!isAppPresent(appName))
    380                 return false;
    381             else {
    382                 apps_[appName.id]->cached_start = start;
    383                 saveApps();
    384                 return true;
    385             }
    386         }
    387         bool addNewApp(hub_app_name_t &appName, uint32_t version) {
    388             if (isAppLoaded(appName))
    389                 return false;
    390             else
    391                 apps_[appName.id] = std::unique_ptr<AppData>(new AppData);
    392             apps_[appName.id]->loaded = false;
    393             apps_[appName.id]->running = false;
    394             apps_[appName.id]->chre = false;
    395             apps_[appName.id]->cached_napp = false;
    396             apps_[appName.id]->cached_version = version;
    397             return true;
    398         }
    399         bool isAppPresent(hub_app_name_t &appName) {
    400             return apps_.count(appName.id) != 0;
    401         }
    402         bool isAppLoaded(hub_app_name_t &appName) {
    403             return apps_.count(appName.id) != 0 && apps_[appName.id]->loaded;
    404         }
    405         bool isAppRunning(hub_app_name_t &appName) {
    406             return apps_.count(appName.id) != 0 && apps_[appName.id]->running;
    407         }
    408         uint32_t getFlashAddr(hub_app_name_t &appName) {
    409             if (isAppPresent(appName))
    410                 return apps_[appName.id]->flashAddr;
    411             else
    412                 return 0xFFFFFFFF;
    413         }
    414     };
    415 
    416     class SessionManager {
    417         typedef std::map<int, Session* > SessionMap;
    418 
    419         std::mutex lock;
    420         SessionMap sessions_;
    421 
    422         bool isActive(const SessionMap::iterator &pos) const
    423         {
    424             return !pos->second->isDone();
    425         }
    426         void next(SessionMap::iterator &pos)
    427         {
    428             isActive(pos) ? pos++ : pos = sessions_.erase(pos);
    429         }
    430 
    431     public:
    432         int handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre, bool &reboot, uint32_t &rebootStatus);
    433         int setup_and_add(int id, Session *session, const hub_message_t *appMsg, uint32_t transactionId, AppManager &appManager);
    434     } mSessions;
    435 
    436     const hub_app_name_t mHostIfAppName = {
    437         .id = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0)
    438     };
    439 
    440     static SystemComm *getSystem() {
    441         // this is thread-safe in c++11
    442         static SystemComm theInstance;
    443         return &theInstance;
    444     }
    445 
    446     SystemComm () = default;
    447     ~SystemComm() = default;
    448 
    449     int doHandleTx(const hub_message_t *txMsg, uint32_t transactionId);
    450     int doHandleRx(uint64_t appId, uint32_t transactionId, const char *data, int len, bool chre);
    451     void doDumpAppInfo(std::string &result);
    452 
    453     int doHandleRx(const nano_message_raw *rxMsg) {
    454         return doHandleRx(rxMsg->hdr.appId, 0, reinterpret_cast<const char*>(rxMsg->data), rxMsg->hdr.len, false);
    455     }
    456 
    457     int doHandleRx(const nano_message_chre *rxMsg) {
    458         return doHandleRx(rxMsg->hdr.appId, rxMsg->hdr.appEventId, reinterpret_cast<const char*>(rxMsg->data), rxMsg->hdr.len, true);
    459     }
    460 
    461     static void sendToApp(uint32_t typ, uint32_t transactionId, const void *data, uint32_t len) {
    462         if (NanoHub::messageTracingEnabled()) {
    463             dumpBuffer("HAL -> APP", get_hub_info()->os_app_name, transactionId, 0, data, len);
    464         }
    465         NanoHub::sendToApp(HubMessage(&get_hub_info()->os_app_name, typ, transactionId, ENDPOINT_BROADCAST, data, len));
    466     }
    467     static int sendToSystem(const void *data, size_t len, uint32_t transactionId);
    468 
    469     KeyInfoSession mKeySession;
    470     AppMgmtSession mAppMgmtSession;
    471     MemInfoSession mMemInfoSession;
    472     AppManager     mAppManager;
    473 
    474 public:
    475     static int handleTx(const hub_message_t *txMsg, uint32_t transactionId) {
    476         return getSystem()->doHandleTx(txMsg, transactionId);
    477     }
    478     static int handleRx(const nano_message_raw *rxMsg) {
    479         return getSystem()->doHandleRx(rxMsg);
    480     }
    481     static int handleRx(const nano_message_chre *rxMsg) {
    482         return getSystem()->doHandleRx(rxMsg);
    483     }
    484     static void dumpAppInfo(std::string &result) {
    485         return getSystem()->doDumpAppInfo(result);
    486     }
    487 };
    488 
    489 }; // namespace nanohub
    490 
    491 }; // namespace android
    492 
    493 #endif
    494