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