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 <cassert>
20 #include <cerrno>
21 #include <cinttypes>
22 
23 #include <endian.h>
24 
25 #include <vector>
26 
27 #include <utils/Log.h>
28 
29 #include <endian.h>
30 
31 #include <hardware/context_hub.h>
32 #include "nanohub_perdevice.h"
33 #include "system_comms.h"
34 #include "nanohubhal.h"
35 
36 namespace android {
37 
38 namespace nanohub {
39 
readAppName(MessageBuf & buf,hub_app_name_t & name)40 static void readAppName(MessageBuf &buf, hub_app_name_t &name)
41 {
42     name.id = buf.readU64();
43 }
44 
writeAppName(MessageBuf & buf,const hub_app_name_t & name)45 static void writeAppName(MessageBuf &buf, const hub_app_name_t &name)
46 {
47     buf.writeU64(name.id);
48 }
49 
readNanohubAppInfo(MessageBuf & buf,NanohubAppInfo & info)50 static void readNanohubAppInfo(MessageBuf &buf, NanohubAppInfo &info)
51 {
52     size_t pos = buf.getPos();
53     readAppName(buf, info.name);
54     info.version = buf.readU32();
55     info.flashUse = buf.readU32();
56     info.ramUse = buf.readU32();
57     if ((buf.getPos() - pos) != sizeof(info)) {
58         ALOGE("%s: failed to read object", __func__);
59     }
60 }
61 
readNanohubMemInfo(MessageBuf & buf,NanohubMemInfo & mi)62 static void readNanohubMemInfo(MessageBuf &buf,  NanohubMemInfo &mi)
63 {
64     size_t pos = buf.getPos();
65     mi.flashSz = buf.readU32();
66     mi.blSz = buf.readU32();
67     mi.osSz = buf.readU32();
68     mi.sharedSz = buf.readU32();
69     mi.eeSz = buf.readU32();
70     mi.ramSz = buf.readU32();
71 
72     mi.blUse = buf.readU32();
73     mi.osUse = buf.readU32();
74     mi.sharedUse = buf.readU32();
75     mi.eeUse = buf.readU32();
76     mi.ramUse = buf.readU32();
77     if ((buf.getPos() - pos) != sizeof(mi)) {
78         ALOGE("%s: failed to read object", __func__);
79     }
80 }
81 
NanohubRsp(MessageBuf & buf,bool no_status)82 NanohubRsp::NanohubRsp(MessageBuf &buf, bool no_status)
83 {
84     // all responses start with command
85     // most of them have 4-byte status (result code)
86     buf.reset();
87     cmd = buf.readU8();
88     if (!buf.getSize()) {
89         status = -EINVAL;
90     } else if (no_status) {
91         status = 0;
92     } else {
93         status = buf.readU32();
94     }
95 }
96 
sendToSystem(const void * data,size_t len)97 int SystemComm::sendToSystem(const void *data, size_t len)
98 {
99     if (NanoHub::messageTracingEnabled()) {
100         dumpBuffer("HAL -> SYS", getSystem()->mHostIfAppName, 0, data, len);
101     }
102     return NanoHub::sendToDevice(&getSystem()->mHostIfAppName, data, len);
103 }
104 
setup(const hub_message_t *)105 int SystemComm::AppInfoSession::setup(const hub_message_t *)
106 {
107     std::lock_guard<std::mutex> _l(mLock);
108     int suggestedSize = mAppInfo.size() ? mAppInfo.size() : 20;
109 
110     mAppInfo.clear();
111     mAppInfo.reserve(suggestedSize);
112     setState(SESSION_USER);
113 
114     return requestNext();
115 }
116 
deviceAppNameToHost(const hub_app_name_t src)117 inline hub_app_name_t deviceAppNameToHost(const hub_app_name_t src)
118 {
119     hub_app_name_t res = { .id = le64toh(src.id) };
120     return res;
121 }
122 
hostAppNameToDevice(const hub_app_name_t src)123 inline hub_app_name_t hostAppNameToDevice(const hub_app_name_t src)
124 {
125     hub_app_name_t res = { .id = htole64(src.id) };
126     return res;
127 }
128 
handleRx(MessageBuf & buf)129 int SystemComm::AppInfoSession::handleRx(MessageBuf &buf)
130 {
131     std::lock_guard<std::mutex> _l(mLock);
132 
133     NanohubRsp rsp(buf, true);
134     if (rsp.cmd != NANOHUB_QUERY_APPS) {
135         return 1;
136     }
137     size_t len = buf.getRoom();
138     if (len != sizeof(NanohubAppInfo) && len) {
139         ALOGE("%s: Invalid data size; have %zu, need %zu", __func__,
140               len, sizeof(NanohubAppInfo));
141         return -EINVAL;
142     }
143     if (getState() != SESSION_USER) {
144         ALOGE("%s: Invalid state; have %d, need %d", __func__, getState(), SESSION_USER);
145         return -EINVAL;
146     }
147     if (len) {
148         NanohubAppInfo info;
149         readNanohubAppInfo(buf, info);
150         hub_app_info appInfo;
151         appInfo.num_mem_ranges = 0;
152         if (info.flashUse != NANOHUB_MEM_SZ_UNKNOWN) {
153             mem_range_t &range = appInfo.mem_usage[appInfo.num_mem_ranges++];
154             range.type = HUB_MEM_TYPE_MAIN;
155             range.total_bytes = info.flashUse;
156         }
157         if (info.ramUse != NANOHUB_MEM_SZ_UNKNOWN) {
158             mem_range_t &range = appInfo.mem_usage[appInfo.num_mem_ranges++];
159             range.type = HUB_MEM_TYPE_RAM;
160             range.total_bytes = info.ramUse;
161         }
162 
163         appInfo.app_name = info.name;
164         appInfo.version = info.version;
165 
166         mAppInfo.push_back(appInfo);
167         return requestNext();
168     } else {
169         sendToApp(CONTEXT_HUB_QUERY_APPS,
170                         static_cast<const void *>(mAppInfo.data()),
171                         mAppInfo.size() * sizeof(mAppInfo[0]));
172         complete();
173     }
174 
175     return 0;
176 }
177 
requestNext()178 int SystemComm::AppInfoSession::requestNext()
179 {
180     char data[MAX_RX_PACKET];
181     MessageBuf buf(data, sizeof(data));
182     buf.writeU8(NANOHUB_QUERY_APPS);
183     buf.writeU32(mAppInfo.size());
184     return sendToSystem(buf.getData(), buf.getPos());
185 }
186 
setup(const hub_message_t *)187 int SystemComm::MemInfoSession::setup(const hub_message_t *)
188 {
189     std::lock_guard<std::mutex> _l(mLock);
190     char data[MAX_RX_PACKET];
191     MessageBuf buf(data, sizeof(data));
192     buf.writeU8(NANOHUB_QUERY_MEMINFO);
193 
194     setState(SESSION_USER);
195     return sendToSystem(buf.getData(), buf.getPos());
196 }
197 
handleRx(MessageBuf & buf)198 int SystemComm::MemInfoSession::handleRx(MessageBuf &buf)
199 {
200     std::lock_guard<std::mutex> _l(mLock);
201     NanohubRsp rsp(buf, true);
202 
203     if (rsp.cmd != NANOHUB_QUERY_MEMINFO)
204         return 1;
205 
206     size_t len = buf.getRoom();
207 
208     if (len != sizeof(NanohubMemInfo)) {
209         ALOGE("%s: Invalid data size: %zu", __func__, len);
210         return -EINVAL;
211     }
212     if (getState() != SESSION_USER) {
213         ALOGE("%s: Invalid state; have %d, need %d", __func__, getState(), SESSION_USER);
214         return -EINVAL;
215     }
216 
217     NanohubMemInfo mi;
218     readNanohubMemInfo(buf, mi);
219     std::vector<mem_range_t> ranges;
220     ranges.reserve(4);
221 
222     //if each is valid, copy to output area
223     if (mi.sharedSz != NANOHUB_MEM_SZ_UNKNOWN &&
224         mi.sharedUse != NANOHUB_MEM_SZ_UNKNOWN)
225         ranges.push_back({
226             .type = HUB_MEM_TYPE_MAIN,
227             .total_bytes = mi.sharedSz,
228             .free_bytes = mi.sharedSz - mi.sharedUse,
229         });
230 
231     if (mi.osSz != NANOHUB_MEM_SZ_UNKNOWN &&
232         mi.osUse != NANOHUB_MEM_SZ_UNKNOWN)
233         ranges.push_back({
234             .type = HUB_MEM_TYPE_OS,
235             .total_bytes = mi.osSz,
236             .free_bytes = mi.osSz - mi.osUse,
237         });
238 
239     if (mi.eeSz != NANOHUB_MEM_SZ_UNKNOWN &&
240         mi.eeUse != NANOHUB_MEM_SZ_UNKNOWN)
241         ranges.push_back({
242             .type = HUB_MEM_TYPE_EEDATA,
243             .total_bytes = mi.eeSz,
244             .free_bytes = mi.eeSz - mi.eeUse,
245         });
246 
247     if (mi.ramSz != NANOHUB_MEM_SZ_UNKNOWN &&
248         mi.ramUse != NANOHUB_MEM_SZ_UNKNOWN)
249         ranges.push_back({
250             .type = HUB_MEM_TYPE_RAM,
251             .total_bytes = mi.ramSz,
252             .free_bytes = mi.ramSz - mi.ramUse,
253         });
254 
255     //send it out
256     sendToApp(CONTEXT_HUB_QUERY_MEMORY,
257               static_cast<const void *>(ranges.data()),
258               ranges.size() * sizeof(ranges[0]));
259 
260     complete();
261 
262     return 0;
263 }
264 
setup(const hub_message_t * appMsg)265 int SystemComm::AppMgmtSession::setup(const hub_message_t *appMsg)
266 {
267     std::lock_guard<std::mutex> _l(mLock);
268 
269     char data[MAX_RX_PACKET];
270     MessageBuf buf(data, sizeof(data));
271     const uint8_t *msgData = static_cast<const uint8_t*>(appMsg->message);
272 
273     mCmd = appMsg->message_type;
274     mLen = appMsg->message_len;
275     mPos = 0;
276 
277     switch (mCmd) {
278     case  CONTEXT_HUB_APPS_ENABLE:
279         return setupMgmt(appMsg, NANOHUB_EXT_APPS_ON);
280     case  CONTEXT_HUB_APPS_DISABLE:
281         return setupMgmt(appMsg, NANOHUB_EXT_APPS_OFF);
282     case  CONTEXT_HUB_UNLOAD_APP:
283         return setupMgmt(appMsg, NANOHUB_EXT_APP_DELETE);
284     case  CONTEXT_HUB_LOAD_APP:
285     {
286         mData.clear();
287         mData = std::vector<uint8_t>(msgData, msgData + mLen);
288         const load_app_request_t *appReq = static_cast<const load_app_request_t*>(appMsg->message);
289         if (appReq == nullptr || mLen <= sizeof(*appReq)) {
290             ALOGE("%s: Invalid app header: too short\n", __func__);
291             return -EINVAL;
292         }
293         mAppName = appReq->app_binary.app_id;
294         setState(TRANSFER);
295 
296         buf.writeU8(NANOHUB_START_UPLOAD);
297         buf.writeU8(0);
298         buf.writeU32(mLen);
299         return sendToSystem(buf.getData(), buf.getPos());
300     }
301 
302     case  CONTEXT_HUB_OS_REBOOT:
303         setState(REBOOT);
304         buf.writeU8(NANOHUB_REBOOT);
305         return sendToSystem(buf.getData(), buf.getPos());
306     }
307 
308     return -EINVAL;
309 }
310 
setupMgmt(const hub_message_t * appMsg,uint32_t cmd)311 int SystemComm::AppMgmtSession::setupMgmt(const hub_message_t *appMsg, uint32_t cmd)
312 {
313     const hub_app_name_t &appName = *static_cast<const hub_app_name_t*>(appMsg->message);
314     if (appMsg->message_len != sizeof(appName)) {
315         return -EINVAL;
316     }
317 
318     char data[MAX_RX_PACKET];
319     MessageBuf buf(data, sizeof(data));
320     buf.writeU8(cmd);
321     writeAppName(buf, appName);
322     setState(MGMT);
323 
324     return sendToSystem(buf.getData(), buf.getPos());
325 }
326 
handleRx(MessageBuf & buf)327 int SystemComm::AppMgmtSession::handleRx(MessageBuf &buf)
328 {
329     int ret = 0;
330     std::lock_guard<std::mutex> _l(mLock);
331     NanohubRsp rsp(buf);
332 
333     switch (getState()) {
334     case TRANSFER:
335         ret = handleTransfer(rsp);
336         break;
337     case FINISH:
338         ret = handleFinish(rsp);
339         break;
340     case RUN:
341         ret = handleRun(rsp);
342         break;
343     case RUN_FAILED:
344         ret = handleRunFailed(rsp);
345         break;
346     case REBOOT:
347         ret = handleReboot(rsp);
348         break;
349     case MGMT:
350         ret = handleMgmt(rsp);
351         break;
352     }
353 
354     return ret;
355 }
356 
handleTransfer(NanohubRsp & rsp)357 int SystemComm::AppMgmtSession::handleTransfer(NanohubRsp &rsp)
358 {
359     if (rsp.cmd != NANOHUB_CONT_UPLOAD && rsp.cmd != NANOHUB_START_UPLOAD)
360         return 1;
361 
362     char data[MAX_RX_PACKET];
363     MessageBuf buf(data, sizeof(data));
364 
365     static_assert(NANOHUB_UPLOAD_CHUNK_SZ_MAX <= (MAX_RX_PACKET-5),
366                   "Invalid chunk size");
367 
368     if (mPos < mLen) {
369         uint32_t chunkSize = mLen - mPos;
370 
371         if (chunkSize > NANOHUB_UPLOAD_CHUNK_SZ_MAX) {
372             chunkSize = NANOHUB_UPLOAD_CHUNK_SZ_MAX;
373         }
374 
375         buf.writeU8(NANOHUB_CONT_UPLOAD);
376         buf.writeU32(mPos);
377         buf.writeRaw(&mData[mPos], chunkSize);
378         mPos += chunkSize;
379     } else {
380         buf.writeU8(NANOHUB_FINISH_UPLOAD);
381         setState(FINISH);
382     }
383 
384     return sendToSystem(buf.getData(), buf.getPos());
385 }
386 
handleFinish(NanohubRsp & rsp)387 int SystemComm::AppMgmtSession::handleFinish(NanohubRsp &rsp)
388 {
389     if (rsp.cmd != NANOHUB_FINISH_UPLOAD)
390         return 1;
391 
392     int ret = 0;
393     const bool success = rsp.status != 0;
394     mData.clear();
395 
396     if (success) {
397         char data[MAX_RX_PACKET];
398         MessageBuf buf(data, sizeof(data));
399         buf.writeU8(NANOHUB_EXT_APPS_ON);
400         writeAppName(buf, mAppName);
401         setState(RUN);
402         ret = sendToSystem(buf.getData(), buf.getPos());
403     } else {
404         int32_t result = NANOHUB_APP_NOT_LOADED;
405 
406         sendToApp(mCmd, &result, sizeof(result));
407         complete();
408     }
409 
410     return ret;
411 }
412 
handleRun(NanohubRsp & rsp)413 int SystemComm::AppMgmtSession::handleRun(NanohubRsp &rsp)
414 {
415     if (rsp.cmd != NANOHUB_EXT_APPS_ON)
416         return 1;
417 
418     MgmtStatus sts = { .value = (uint32_t)rsp.status };
419 
420     // op counter returns number of nanoapps that were started as result of the command
421     // for successful start command it must be > 0
422     int32_t result = sts.value > 0 && sts.op > 0 && sts.op <= 0x7F ? 0 : -1;
423 
424     ALOGI("Nanohub NEW APP START: %08" PRIX32 "\n", rsp.status);
425     if (result != 0) {
426         // if nanoapp failed to start we have to unload it
427         char data[MAX_RX_PACKET];
428         MessageBuf buf(data, sizeof(data));
429         buf.writeU8(NANOHUB_EXT_APP_DELETE);
430         writeAppName(buf, mAppName);
431         if (sendToSystem(buf.getData(), buf.getPos()) == 0) {
432             setState(RUN_FAILED);
433             return 0;
434         }
435         ALOGE("%s: failed to send DELETE for failed app\n", __func__);
436     }
437 
438     // it is either success, and we report it, or
439     // it is a failure to load, and also failure to send erase command
440     sendToApp(mCmd, &result, sizeof(result));
441     complete();
442     return 0;
443 }
444 
handleRunFailed(NanohubRsp & rsp)445 int SystemComm::AppMgmtSession::handleRunFailed(NanohubRsp &rsp)
446 {
447     if (rsp.cmd != NANOHUB_EXT_APP_DELETE)
448         return 1;
449 
450     int32_t result = -1;
451 
452     ALOGI("%s: APP DELETE [because it failed]: %08" PRIX32 "\n", __func__, rsp.status);
453 
454     sendToApp(mCmd, &result, sizeof(result));
455     complete();
456 
457     return 0;
458 }
459 
460 /* reboot notification, when triggered by App request */
handleReboot(NanohubRsp & rsp)461 int SystemComm::AppMgmtSession::handleReboot(NanohubRsp &rsp)
462 {
463     if (rsp.cmd != NANOHUB_REBOOT)
464         return 1;
465     ALOGI("Nanohub reboot status [USER REQ]: %08" PRIX32 "\n", rsp.status);
466 
467     // reboot notification is sent by SessionManager
468     complete();
469 
470     return 0;
471 }
472 
handleMgmt(NanohubRsp & rsp)473 int SystemComm::AppMgmtSession::handleMgmt(NanohubRsp &rsp)
474 {
475     bool valid = false;
476 
477     int32_t result = rsp.status;
478 
479     // TODO: remove this when context hub service can handle non-zero success status
480     if (result > 0) {
481         // something happened; assume it worked
482         result = 0;
483     } else if (result == 0) {
484         // nothing happened; this is provably an error
485         result = -1;
486     }
487 
488     switch (rsp.cmd) {
489     case NANOHUB_EXT_APPS_OFF:
490         valid = mCmd == CONTEXT_HUB_APPS_DISABLE;
491         break;
492     case NANOHUB_EXT_APPS_ON:
493         valid = mCmd == CONTEXT_HUB_APPS_ENABLE;
494         break;
495     case NANOHUB_EXT_APP_DELETE:
496         valid = mCmd == CONTEXT_HUB_UNLOAD_APP;
497         break;
498     default:
499         return 1;
500     }
501 
502     ALOGI("Nanohub MGMT response: CMD=%02X; STATUS=%08" PRIX32, rsp.cmd, rsp.status);
503     if (!valid) {
504         ALOGE("Invalid response for this state: APP CMD=%02X", mCmd);
505         return -EINVAL;
506     }
507 
508     sendToApp(mCmd, &result, sizeof(result));
509     complete();
510 
511     return 0;
512 }
513 
setup(const hub_message_t *)514 int SystemComm::KeyInfoSession::setup(const hub_message_t *) {
515     std::lock_guard<std::mutex> _l(mLock);
516     mRsaKeyData.clear();
517     setState(SESSION_USER);
518     mStatus = -EBUSY;
519     return requestRsaKeys();
520 }
521 
handleRx(MessageBuf & buf)522 int SystemComm::KeyInfoSession::handleRx(MessageBuf &buf)
523 {
524     std::lock_guard<std::mutex> _l(mLock);
525     NanohubRsp rsp(buf, true);
526 
527     if (getState() != SESSION_USER) {
528         // invalid state
529         mStatus = -EFAULT;
530         return mStatus;
531     }
532 
533     if (buf.getRoom()) {
534         mRsaKeyData.insert(mRsaKeyData.end(),
535                            buf.getData() + buf.getPos(),
536                            buf.getData() + buf.getSize());
537         return requestRsaKeys();
538     } else {
539         mStatus = 0;
540         complete();
541         return 0;
542     }
543 }
544 
requestRsaKeys(void)545 int SystemComm::KeyInfoSession::requestRsaKeys(void)
546 {
547     char data[MAX_RX_PACKET];
548     MessageBuf buf(data, sizeof(data));
549 
550     buf.writeU8(NANOHUB_QUERY_APPS);
551     buf.writeU32(mRsaKeyData.size());
552 
553     return sendToSystem(buf.getData(), buf.getPos());
554 }
555 
doHandleRx(const nano_message * msg)556 int SystemComm::doHandleRx(const nano_message *msg)
557 {
558     //we only care for messages from HostIF
559     if (msg->hdr.appId != mHostIfAppName.id)
560         return 1;
561 
562     //they must all be at least 1 byte long
563     if (!msg->hdr.len) {
564         return -EINVAL;
565     }
566     MessageBuf buf(reinterpret_cast<const char*>(msg->data), msg->hdr.len);
567     if (NanoHub::messageTracingEnabled()) {
568         dumpBuffer("SYS -> HAL", mHostIfAppName, 0, buf.getData(), buf.getSize());
569     }
570     int status = mSessions.handleRx(buf);
571     if (status) {
572         // provide default handler for any system message, that is not properly handled
573         dumpBuffer(status > 0 ? "HAL (not handled)" : "HAL (error)",
574                    mHostIfAppName, 0, buf.getData(), buf.getSize(), status);
575         status = status > 0 ? 0 : status;
576     }
577 
578     return status;
579 }
580 
handleRx(MessageBuf & buf)581 int SystemComm::SessionManager::handleRx(MessageBuf &buf)
582 {
583     int status = 1;
584     std::unique_lock<std::mutex> lk(lock);
585 
586     // pass message to all active sessions, in arbitrary order
587     // 1st session that handles the message terminates the loop
588     for (auto pos = sessions_.begin(); pos != sessions_.end() && status > 0; next(pos)) {
589         if (!isActive(pos)) {
590             continue;
591         }
592         Session *session = pos->second;
593         status = session->handleRx(buf);
594         if (status < 0) {
595             session->complete();
596         }
597     }
598 
599     NanohubRsp rsp(buf);
600     if (rsp.cmd == NANOHUB_REBOOT) {
601         // if this is reboot notification, kill all sessions
602         for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) {
603             if (!isActive(pos)) {
604                 continue;
605             }
606             Session *session = pos->second;
607             session->abort(-EINTR);
608         }
609         lk.unlock();
610         // log the reboot event, if not handled
611         if (status > 0) {
612             ALOGW("Nanohub reboot status [UNSOLICITED]: %08" PRIX32, rsp.status);
613             status = 0;
614         }
615         // report to java apps
616         sendToApp(CONTEXT_HUB_OS_REBOOT, &rsp.status, sizeof(rsp.status));
617     }
618 
619     return status;
620 }
621 
setup_and_add(int id,Session * session,const hub_message_t * appMsg)622 int SystemComm::SessionManager::setup_and_add(int id, Session *session, const hub_message_t *appMsg)
623 {
624     std::lock_guard<std::mutex> _l(lock);
625 
626     // scan sessions to release those that are already done
627     for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) {
628         continue;
629     }
630 
631     if (sessions_.count(id) == 0 && !session->isRunning()) {
632         sessions_[id] = session;
633         int ret = session->setup(appMsg);
634         if (ret < 0) {
635             session->complete();
636         }
637         return ret;
638     }
639     return -EBUSY;
640 }
641 
doHandleTx(const hub_message_t * appMsg)642 int SystemComm::doHandleTx(const hub_message_t *appMsg)
643 {
644     int status = 0;
645 
646     switch (appMsg->message_type) {
647     case CONTEXT_HUB_LOAD_APP:
648         if (!mKeySession.haveKeys()) {
649             status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mKeySession, appMsg);
650             if (status < 0) {
651                 break;
652             }
653             mKeySession.wait();
654             status = mKeySession.getStatus();
655             if (status < 0) {
656                 break;
657             }
658         }
659         status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg);
660         break;
661     case CONTEXT_HUB_APPS_ENABLE:
662     case CONTEXT_HUB_APPS_DISABLE:
663     case CONTEXT_HUB_UNLOAD_APP:
664         // all APP-modifying commands share session key, to ensure they can't happen at the same time
665         status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg);
666         break;
667 
668     case CONTEXT_HUB_QUERY_APPS:
669         status = mSessions.setup_and_add(CONTEXT_HUB_QUERY_APPS, &mAppInfoSession, appMsg);
670         break;
671 
672     case CONTEXT_HUB_QUERY_MEMORY:
673         status = mSessions.setup_and_add(CONTEXT_HUB_QUERY_MEMORY, &mMemInfoSession, appMsg);
674         break;
675 
676     default:
677         ALOGW("Unknown os message type %u\n", appMsg->message_type);
678         return -EINVAL;
679     }
680 
681    return status;
682 }
683 
684 }; // namespace nanohub
685 
686 }; // namespace android
687