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