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::StreamWriterBuilder factory;
1019 std::string serializedSettings(Json::writeString(factory, *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::CharReaderBuilder builder;
1054 std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
1055 bool valid = reader->parse(
1056 str.data(), str.data() + str.size(), in.get(), /* errorMessage = */ nullptr);
1057 free(buf);
1058
1059 if (valid && in->isObject()) {
1060 appsObject = in;
1061 }
1062 }
1063
1064 if (appsObject == nullptr) {
1065 appsObject = std::shared_ptr<Json::Value>(new Json::Value(Json::objectValue));
1066 }
1067
1068 Json::Value::Members apps = appsObject->getMemberNames();
1069 for (auto &it : apps) {
1070 Json::Value &val = (*appsObject)[it];
1071 if (val.isArray()) {
1072 uint32_t version = val[0].asUInt();
1073 uint32_t start = val[1].asUInt();
1074 uint32_t crc = val[2].asUInt();
1075
1076 uint64_t id = strtoull(it.c_str(), nullptr, 16);
1077 apps_[id] = std::unique_ptr<AppData>(new AppData);
1078 apps_[id]->loaded = false;
1079 apps_[id]->running = false;
1080 apps_[id]->chre = false;
1081 apps_[id]->cached_napp = true;
1082 apps_[id]->cached_version = version;
1083 apps_[id]->cached_start = start;
1084 apps_[id]->cached_crc = crc;
1085 }
1086 }
1087
1088 return true;
1089 }
1090
eraseApps()1091 bool SystemComm::AppManager::eraseApps()
1092 {
1093 for (auto it=apps_.begin(); it != apps_.end();) {
1094 if (!it->second->cached_napp)
1095 it = apps_.erase(it);
1096 else {
1097 it->second->loaded = false;
1098 it->second->running = false;
1099 it->second->chre = false;
1100 ++it;
1101 }
1102 }
1103
1104 return true;
1105 }
1106
writeApp(hub_app_name_t & appName,const uint8_t * data,int32_t len)1107 bool SystemComm::AppManager::writeApp(hub_app_name_t &appName, const uint8_t *data, int32_t len)
1108 {
1109 mkdir(CHRE_APP_DIR, CHRE_APP_DIR_PERMS);
1110 char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1];
1111
1112 snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id);
1113
1114 int fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, CHRE_APP_FILE_PERMS);
1115 if (fd == -1)
1116 return false;
1117
1118 if (write(fd, data, len) == len) {
1119 close(fd);
1120 return true;
1121 } else {
1122 close(fd);
1123 return false;
1124 }
1125 }
1126
readApp(hub_app_name_t & appName,void ** data)1127 int32_t SystemComm::AppManager::readApp(hub_app_name_t &appName, void **data)
1128 {
1129 char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1];
1130
1131 snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id);
1132
1133 int32_t ret = -1;
1134 *data = nullptr;
1135 int fd = open(file, O_RDONLY);
1136
1137 if (fd >= 0) {
1138 struct stat sb;
1139 if (fstat(fd, &sb) == 0) {
1140 *data = malloc(sb.st_size);
1141 if (*data != nullptr && read(fd, *data, sb.st_size) == sb.st_size)
1142 ret = sb.st_size;
1143 else {
1144 free(*data);
1145 *data = nullptr;
1146 }
1147 }
1148 close(fd);
1149 }
1150 return ret;
1151 }
1152
cmpApp(hub_app_name_t & appName,const uint8_t * data,uint32_t len)1153 bool SystemComm::AppManager::cmpApp(hub_app_name_t &appName, const uint8_t *data, uint32_t len)
1154 {
1155 char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1];
1156
1157 snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id);
1158
1159 if (!isAppLoaded(appName))
1160 return false;
1161
1162 if ((!apps_[appName.id]->cached_napp) ||
1163 (apps_[appName.id]->crc != apps_[appName.id]->cached_crc))
1164 return false;
1165
1166 bool success = false;
1167 int fd = open(file, O_RDONLY);
1168
1169 if (fd >= 0) {
1170 struct stat sb;
1171 if (fstat(fd, &sb) == 0 && sb.st_size == len) {
1172 void *buf = malloc(len);
1173 if (buf != nullptr && read(fd, buf, sb.st_size) == sb.st_size && memcmp(data, buf, len) == 0)
1174 success = true;
1175 free(buf);
1176 }
1177 close(fd);
1178 }
1179 return success;
1180 }
1181
readNanohubAppInfo(MessageBuf & buf)1182 uint32_t SystemComm::AppManager::readNanohubAppInfo(MessageBuf &buf)
1183 {
1184 hub_app_name_t name;
1185
1186 uint8_t tag, len;
1187 uint32_t ramUse = 0;
1188 bool ramUseValid = true;
1189
1190 // first tag must be the appid
1191 if (buf.getRoom() < 2 + sizeof(name.id)) {
1192 ALOGE("%s: failed to read object", __func__);
1193 return 0;
1194 }
1195
1196 tag = buf.readU8();
1197 len = buf.readU8();
1198 if (tag != NANOHUB_HAL_APP_INFO_APPID || len != sizeof(name.id)) {
1199 ALOGE("%s: invalid first tag: %d", __func__, tag);
1200 return 0;
1201 }
1202
1203 readAppName(buf, name);
1204 if (!isAppPresent(name)) {
1205 apps_[name.id] = std::unique_ptr<AppData>(new AppData);
1206 apps_[name.id]->loaded = false;
1207 apps_[name.id]->chre = false;
1208 apps_[name.id]->running = false;
1209 apps_[name.id]->cached_napp = false;
1210 }
1211 const auto &app = apps_[name.id];
1212
1213 while (buf.getRoom() >= 2) {
1214 tag = buf.readU8();
1215 len = buf.readU8();
1216 if (buf.getRoom() >= len) {
1217 switch(tag) {
1218 case NANOHUB_HAL_APP_INFO_CRC:
1219 if (len == 0)
1220 app->crc = 0;
1221 else if (len == sizeof(app->crc))
1222 app->crc = buf.readU32();
1223 else
1224 buf.readRaw(len);
1225 break;
1226 case NANOHUB_HAL_APP_INFO_TID:
1227 if (len == 0) {
1228 app->tid = NANOHUB_TID_UNKNOWN;
1229 ramUseValid = false;
1230 app->loaded = true;
1231 app->running = false;
1232 } else if (len == sizeof(app->tid)) {
1233 app->tid = buf.readU32();
1234 app->loaded = true;
1235 app->running = true;
1236 } else
1237 buf.readRaw(len);
1238 break;
1239 case NANOHUB_HAL_APP_INFO_VERSION:
1240 if (len == sizeof(app->version))
1241 app->version = buf.readU32();
1242 else
1243 buf.readRaw(len);
1244 break;
1245 case NANOHUB_HAL_APP_INFO_ADDR:
1246 if (len == sizeof(app->flashAddr))
1247 app->flashAddr = buf.readU32();
1248 else
1249 buf.readRaw(len);
1250 break;
1251 case NANOHUB_HAL_APP_INFO_SIZE:
1252 if (len == 0)
1253 app->flashUse = NANOHUB_MEM_SZ_UNKNOWN;
1254 else if (len == sizeof(app->flashUse))
1255 app->flashUse = buf.readU32();
1256 else
1257 buf.readRaw(len);
1258 break;
1259 case NANOHUB_HAL_APP_INFO_HEAP:
1260 case NANOHUB_HAL_APP_INFO_DATA:
1261 case NANOHUB_HAL_APP_INFO_BSS:
1262 if (len == 0)
1263 ramUseValid = false;
1264 else if (len == sizeof(uint32_t))
1265 ramUse += buf.readU32();
1266 else
1267 buf.readRaw(len);
1268 break;
1269 case NANOHUB_HAL_APP_INFO_CHRE_MAJOR:
1270 if (len == 0)
1271 app->chre = false;
1272 else if (len == sizeof(app->chre_major)) {
1273 app->chre = true;
1274 app->chre_major = buf.readU8();
1275 } else
1276 buf.readRaw(len);
1277 break;
1278 case NANOHUB_HAL_APP_INFO_CHRE_MINOR:
1279 if (len == 0)
1280 app->chre = false;
1281 else if (len == sizeof(app->chre_minor)) {
1282 app->chre = true;
1283 app->chre_minor = buf.readU8();
1284 } else
1285 buf.readRaw(len);
1286 break;
1287 case NANOHUB_HAL_APP_INFO_END:
1288 if (len != 0 || buf.getRoom() != 0) {
1289 ALOGE("%s: failed to read object", __func__);
1290 return 0;
1291 }
1292 break;
1293 default:
1294 ALOGI("%s: unsupported tag: %d", __func__, tag);
1295 buf.readRaw(len);
1296 break;
1297 }
1298 } else {
1299 ALOGE("%s: failed to read object", __func__);
1300 return 0;
1301 }
1302 }
1303
1304 if (buf.getRoom() != 0) {
1305 ALOGE("%s: failed to read object", __func__);
1306 return 0;
1307 }
1308
1309 if (ramUseValid)
1310 app->ramUse = ramUse;
1311 else
1312 app->ramUse = NANOHUB_MEM_SZ_UNKNOWN;
1313
1314 return app->flashAddr +
1315 (app->flashUse != NANOHUB_MEM_SZ_UNKNOWN ? ((app->flashUse+3)&~3) : 4);
1316 }
1317
sendAppInfoToApp(uint32_t transactionId)1318 void SystemComm::AppManager::sendAppInfoToApp(uint32_t transactionId) {
1319 std::vector<hub_app_info> appInfo;
1320 for (auto &it : apps_) {
1321 uint64_t id = it.first;
1322 const auto &app = it.second;
1323
1324 // TODO: Still have some non-chre apps that need to be reported
1325 // if (!app->chre || !app->running || app->flashUse == NANOHUB_MEM_SZ_UNKNOWN)
1326 if (!app->running || app->flashUse == NANOHUB_MEM_SZ_UNKNOWN)
1327 continue;
1328
1329 hub_app_info info;
1330 info.app_name = { .id = id };
1331 info.version = app->version;
1332 info.num_mem_ranges = 0;
1333 if (app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) {
1334 mem_range_t &range = info.mem_usage[info.num_mem_ranges++];
1335 range.type = HUB_MEM_TYPE_MAIN;
1336 range.total_bytes = app->flashUse;
1337 }
1338 if (app->ramUse != NANOHUB_MEM_SZ_UNKNOWN) {
1339 mem_range_t &range = info.mem_usage[info.num_mem_ranges++];
1340 range.type = HUB_MEM_TYPE_RAM;
1341 range.total_bytes = app->ramUse;
1342 }
1343
1344 appInfo.push_back(info);
1345 }
1346 sendToApp(CONTEXT_HUB_QUERY_APPS, transactionId,
1347 static_cast<const void *>(appInfo.data()),
1348 appInfo.size() * sizeof(appInfo[0]));
1349 }
1350
getAppsToStart(std::vector<hub_app_name_t> & apps)1351 int SystemComm::AppManager::getAppsToStart(std::vector<hub_app_name_t> &apps)
1352 {
1353 int cnt = 0;
1354 apps.clear();
1355
1356 for (auto &it : apps_) {
1357 uint64_t id = it.first;
1358 const auto &app = it.second;
1359
1360 if (app->cached_napp && app->cached_start && app->loaded &&
1361 !app->running && app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) {
1362 apps.push_back({ .id = id });
1363 cnt++;
1364 }
1365 }
1366
1367 return cnt;
1368 }
1369
doHandleRx(uint64_t appId,uint32_t transactionId,const char * data,int len,bool chre)1370 int SystemComm::doHandleRx(uint64_t appId, uint32_t transactionId, const char *data, int len, bool chre)
1371 {
1372 bool reboot = false;
1373 uint32_t rebootStatus;
1374 //we only care for messages from HostIF
1375 if (appId != mHostIfAppName.id)
1376 return 1;
1377
1378 //they must all be at least 1 byte long
1379 if (!len) {
1380 return -EINVAL;
1381 }
1382 MessageBuf buf(data, len);
1383 if (NanoHub::messageTracingEnabled()) {
1384 dumpBuffer("SYS -> HAL", mHostIfAppName, transactionId, 0, buf.getData(), buf.getSize());
1385 }
1386 int status = mSessions.handleRx(buf, transactionId, mAppManager, chre, reboot, rebootStatus);
1387 if (status) {
1388 // provide default handler for any system message, that is not properly handled
1389 dumpBuffer(status > 0 ? "HAL (not handled)" : "HAL (error)",
1390 mHostIfAppName, transactionId, 0, buf.getData(), buf.getSize(), status);
1391 status = status > 0 ? 0 : status;
1392 }
1393 if (reboot) {
1394 hub_message_t msg =
1395 {
1396 .app_name.id = appId,
1397 .message_type = CONTEXT_HUB_START_APPS,
1398 .message_len = sizeof(rebootStatus),
1399 .message = &rebootStatus,
1400 };
1401
1402 status = doHandleTx(&msg, 0xFFFFFFFF);
1403 }
1404
1405 return status;
1406 }
1407
doDumpAppInfo(std::string & result)1408 void SystemComm::doDumpAppInfo(std::string &result)
1409 {
1410 mAppManager.dumpAppInfo(result);
1411 }
1412
handleRx(MessageBuf & buf,uint32_t transactionId,AppManager & appManager,bool chre,bool & reboot,uint32_t & rebootStatus)1413 int SystemComm::SessionManager::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre, bool &reboot, uint32_t &rebootStatus)
1414 {
1415 int status = 1;
1416 std::unique_lock<std::mutex> lk(lock);
1417
1418 // pass message to all active sessions, in arbitrary order
1419 // 1st session that handles the message terminates the loop
1420 for (auto pos = sessions_.begin(); pos != sessions_.end() && status > 0; next(pos)) {
1421 if (!isActive(pos)) {
1422 continue;
1423 }
1424 Session *session = pos->second;
1425 status = session->handleRx(buf, transactionId, appManager, chre);
1426 if (status < 0) {
1427 session->complete();
1428 }
1429 }
1430
1431 NanohubRsp rsp(buf, transactionId, chre);
1432 if (rsp.mCmd == NANOHUB_HAL_SYS_MGMT) {
1433 uint8_t cmd = buf.readU8();
1434
1435 if (cmd == NANOHUB_HAL_SYS_MGMT_REBOOT) {
1436 // if this is reboot notification, kill all sessions
1437 for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) {
1438 if (!isActive(pos)) {
1439 continue;
1440 }
1441 Session *session = pos->second;
1442 session->abort(-EINTR);
1443 }
1444 lk.unlock();
1445 // log the reboot event, if not handled
1446 if (status > 0) {
1447 ALOGW("Nanohub reboot status [UNSOLICITED]: %08" PRIX32, rsp.mStatus);
1448 status = 0;
1449 }
1450 reboot = true;
1451 rebootStatus = rsp.mStatus;
1452 }
1453 }
1454
1455 return status;
1456 }
1457
setup_and_add(int id,Session * session,const hub_message_t * appMsg,uint32_t transactionId,AppManager & appManager)1458 int SystemComm::SessionManager::setup_and_add(int id, Session *session, const hub_message_t *appMsg, uint32_t transactionId, AppManager &appManager)
1459 {
1460 std::lock_guard<std::mutex> _l(lock);
1461
1462 // scan sessions to release those that are already done
1463 for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) {
1464 continue;
1465 }
1466
1467 if (sessions_.count(id) == 0 && !session->isRunning()) {
1468 sessions_[id] = session;
1469 int ret = session->setup(appMsg, transactionId, appManager);
1470 if (ret < 0) {
1471 session->complete();
1472 }
1473 return ret;
1474 }
1475 return -EBUSY;
1476 }
1477
doHandleTx(const hub_message_t * appMsg,uint32_t transactionId)1478 int SystemComm::doHandleTx(const hub_message_t *appMsg, uint32_t transactionId)
1479 {
1480 int status = 0;
1481
1482 switch (appMsg->message_type) {
1483 case CONTEXT_HUB_LOAD_APP:
1484 if (!mKeySession.haveKeys()) {
1485 status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mKeySession, appMsg, transactionId, mAppManager);
1486 if (status < 0) {
1487 break;
1488 }
1489 mKeySession.wait();
1490 status = mKeySession.getStatus();
1491 if (status < 0) {
1492 break;
1493 }
1494 }
1495 status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg, transactionId, mAppManager);
1496 break;
1497 case CONTEXT_HUB_APPS_ENABLE:
1498 case CONTEXT_HUB_APPS_DISABLE:
1499 case CONTEXT_HUB_UNLOAD_APP:
1500 // all APP-modifying commands share session key, to ensure they can't happen at the same time
1501 status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg, transactionId, mAppManager);
1502 break;
1503
1504 case CONTEXT_HUB_QUERY_APPS:
1505 mAppManager.sendAppInfoToApp(transactionId);
1506 break;
1507
1508 case CONTEXT_HUB_QUERY_MEMORY:
1509 status = mSessions.setup_and_add(CONTEXT_HUB_QUERY_MEMORY, &mMemInfoSession, appMsg, transactionId, mAppManager);
1510 break;
1511
1512 case CONTEXT_HUB_START_APPS:
1513 status = mSessions.setup_and_add(CONTEXT_HUB_START_APPS, &mAppMgmtSession, appMsg, transactionId, mAppManager);
1514 break;
1515
1516 default:
1517 ALOGW("Unknown os message type %u\n", appMsg->message_type);
1518 return -EINVAL;
1519 }
1520
1521 return status;
1522 }
1523
1524 }; // namespace nanohub
1525
1526 }; // namespace android
1527