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