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; ~ISession()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 complete()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 } abort(int32_t status)198 void abort(int32_t status) { 199 std::lock_guard<std::mutex> _l(mLock); 200 mStatus = status; 201 complete(); 202 } setState(int state)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: Session()212 Session() { mState = SESSION_INIT; mStatus = -1; } getStatus()213 int getStatus() const { 214 std::lock_guard<std::mutex> _l(mLock); 215 return mStatus; 216 } wait()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 } getState()227 virtual int getState() const override { 228 std::lock_guard<std::mutex> _l(mDoneMutex); 229 return mState; 230 } isDone()231 virtual bool isDone() const { 232 std::lock_guard<std::mutex> _l(mDoneMutex); 233 return mState == SESSION_DONE; 234 } isRunning()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: AppMgmtSession()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; haveKeys()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: AppManager()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); setCachedCrc(hub_app_name_t & appName,uint32_t crc)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 } clearCachedApp(hub_app_name_t & appName)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 } clearRunning(hub_app_name_t & appName)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 setCachedVersion(hub_app_name_t & appName,uint32_t version)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 } setCachedStart(hub_app_name_t & appName,bool start)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 } addNewApp(hub_app_name_t & appName,uint32_t version)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 } isAppPresent(hub_app_name_t & appName)399 bool isAppPresent(hub_app_name_t &appName) { 400 return apps_.count(appName.id) != 0; 401 } isAppLoaded(hub_app_name_t & appName)402 bool isAppLoaded(hub_app_name_t &appName) { 403 return apps_.count(appName.id) != 0 && apps_[appName.id]->loaded; 404 } isAppRunning(hub_app_name_t & appName)405 bool isAppRunning(hub_app_name_t &appName) { 406 return apps_.count(appName.id) != 0 && apps_[appName.id]->running; 407 } getFlashAddr(hub_app_name_t & appName)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 isActive(const SessionMap::iterator & pos)422 bool isActive(const SessionMap::iterator &pos) const 423 { 424 return !pos->second->isDone(); 425 } next(SessionMap::iterator & pos)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 getSystem()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 doHandleRx(const nano_message_raw * rxMsg)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 doHandleRx(const nano_message_chre * rxMsg)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 sendToApp(uint32_t typ,uint32_t transactionId,const void * data,uint32_t len)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: handleTx(const hub_message_t * txMsg,uint32_t transactionId)475 static int handleTx(const hub_message_t *txMsg, uint32_t transactionId) { 476 return getSystem()->doHandleTx(txMsg, transactionId); 477 } handleRx(const nano_message_raw * rxMsg)478 static int handleRx(const nano_message_raw *rxMsg) { 479 return getSystem()->doHandleRx(rxMsg); 480 } handleRx(const nano_message_chre * rxMsg)481 static int handleRx(const nano_message_chre *rxMsg) { 482 return getSystem()->doHandleRx(rxMsg); 483 } dumpAppInfo(std::string & result)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