1e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie/* 2e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Copyright (C) 2016 The Android Open Source Project 3e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 4e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Licensed under the Apache License, Version 2.0 (the "License"); 5e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * you may not use this file except in compliance with the License. 6e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * You may obtain a copy of the License at 7e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 8e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * http://www.apache.org/licenses/LICENSE-2.0 9e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 10e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Unless required by applicable law or agreed to in writing, software 11e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * distributed under the License is distributed on an "AS IS" BASIS, 12e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * See the License for the specific language governing permissions and 14e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * limitations under the License. 15e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 16e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 17e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/core/event_loop.h" 18e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 19e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/core/event.h" 20341292509cfde0f859d89bda4ca5d55fc9772e64Brian Duddie#include "chre/core/event_loop_manager.h" 21e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/core/nanoapp.h" 22977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie#include "chre/platform/context.h" 23e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/platform/log.h" 24f1694b5b8abc93de4e187a78c096977ad6cf4b56Brian Duddie#include "chre/util/conditional_lock_guard.h" 25f1694b5b8abc93de4e187a78c096977ad6cf4b56Brian Duddie#include "chre/util/lock_guard.h" 26d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro#include "chre/util/system/debug_dump.h" 27a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie#include "chre_api/chre/version.h" 28e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 29e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddienamespace chre { 30e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 3162f187d9d736346275492e916f6001576b68bb00Brian Duddienamespace { 3262f187d9d736346275492e916f6001576b68bb00Brian Duddie 3362f187d9d736346275492e916f6001576b68bb00Brian Duddie/** 3462f187d9d736346275492e916f6001576b68bb00Brian Duddie * Populates a chreNanoappInfo structure using info from the given Nanoapp 3562f187d9d736346275492e916f6001576b68bb00Brian Duddie * instance. 3662f187d9d736346275492e916f6001576b68bb00Brian Duddie * 3762f187d9d736346275492e916f6001576b68bb00Brian Duddie * @param app A potentially null pointer to the Nanoapp to read from 3862f187d9d736346275492e916f6001576b68bb00Brian Duddie * @param info The structure to populate - should not be null, but this function 3962f187d9d736346275492e916f6001576b68bb00Brian Duddie * will handle that input 4062f187d9d736346275492e916f6001576b68bb00Brian Duddie * 4162f187d9d736346275492e916f6001576b68bb00Brian Duddie * @return true if neither app nor info were null, and info was populated 4262f187d9d736346275492e916f6001576b68bb00Brian Duddie */ 4362f187d9d736346275492e916f6001576b68bb00Brian Duddiebool populateNanoappInfo(const Nanoapp *app, struct chreNanoappInfo *info) { 4462f187d9d736346275492e916f6001576b68bb00Brian Duddie bool success = false; 4562f187d9d736346275492e916f6001576b68bb00Brian Duddie 4662f187d9d736346275492e916f6001576b68bb00Brian Duddie if (app != nullptr && info != nullptr) { 4762f187d9d736346275492e916f6001576b68bb00Brian Duddie info->appId = app->getAppId(); 4862f187d9d736346275492e916f6001576b68bb00Brian Duddie info->version = app->getAppVersion(); 4962f187d9d736346275492e916f6001576b68bb00Brian Duddie info->instanceId = app->getInstanceId(); 5062f187d9d736346275492e916f6001576b68bb00Brian Duddie success = true; 5162f187d9d736346275492e916f6001576b68bb00Brian Duddie } 5262f187d9d736346275492e916f6001576b68bb00Brian Duddie 5362f187d9d736346275492e916f6001576b68bb00Brian Duddie return success; 5462f187d9d736346275492e916f6001576b68bb00Brian Duddie} 5562f187d9d736346275492e916f6001576b68bb00Brian Duddie 5662f187d9d736346275492e916f6001576b68bb00Brian Duddie} // anonymous namespace 5762f187d9d736346275492e916f6001576b68bb00Brian Duddie 58fbb213b072fec0a14f437ad55685c4d95eec829eAndrew RossignolEventLoop::EventLoop() 59fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol : mTimerPool(*this) {} 60fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol 61977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddiebool EventLoop::findNanoappInstanceIdByAppId(uint64_t appId, 622fce52a25d14fcdcba888f8ff7892dffe3f55abaBrian Duddie uint32_t *instanceId) const { 63977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie CHRE_ASSERT(instanceId != nullptr); 649526b7b52ed3e6cb198c649f582877acb27f1c56Andrew Rossignol ConditionalLockGuard<Mutex> lock(mNanoappsLock, !inEventLoopThread()); 65977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie 66977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie bool found = false; 675d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie for (const UniquePtr<Nanoapp>& app : mNanoapps) { 68977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie if (app->getAppId() == appId) { 69977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie *instanceId = app->getInstanceId(); 70977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie found = true; 71977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie break; 72977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie } 73977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie } 74977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie 75977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie return found; 76977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie} 77977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie 78a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddievoid EventLoop::forEachNanoapp(NanoappCallbackFunction *callback, void *data) { 799526b7b52ed3e6cb198c649f582877acb27f1c56Andrew Rossignol ConditionalLockGuard<Mutex> lock(mNanoappsLock, !inEventLoopThread()); 80a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 815d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie for (const UniquePtr<Nanoapp>& nanoapp : mNanoapps) { 82a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie callback(nanoapp.get(), data); 83a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie } 84a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie} 85a2f5add27054c406f36528cf8a5cbc6d4c79d246Brian Duddie 8609a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddievoid EventLoop::invokeMessageFreeFunction( 8709a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie uint64_t appId, chreMessageFreeFunction *freeFunction, void *message, 8809a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie size_t messageSize) { 8909a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie Nanoapp *nanoapp = lookupAppByAppId(appId); 9009a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie if (nanoapp == nullptr) { 9109a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie LOGE("Couldn't find app 0x%016" PRIx64 " for message free callback", appId); 9209a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie } else { 9309a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie auto prevCurrentApp = mCurrentApp; 9409a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie mCurrentApp = nanoapp; 9509a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie freeFunction(message, messageSize); 9609a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie mCurrentApp = prevCurrentApp; 9709a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie } 9809a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie} 9909a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie 100e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddievoid EventLoop::run() { 101e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie LOGI("EventLoop start"); 102e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 103e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie bool havePendingEvents = false; 104e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie while (mRunning) { 10599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Events are delivered in two stages: first they arrive in the inbound 10699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // event queue mEvents (potentially posted from another thread), then within 10799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // this context these events are distributed to smaller event queues 10899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // associated with each Nanoapp that should receive the event. Once the 10999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // event is delivered to all interested Nanoapps, its free callback is 11099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // invoked. 111e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie if (!havePendingEvents || !mEvents.empty()) { 11288f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol if (mEvents.size() > mMaxEventPoolUsage) { 11388f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol mMaxEventPoolUsage = mEvents.size(); 11488f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol } 11588f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol 11699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // mEvents.pop() will be a blocking call if mEvents.empty() 11799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie distributeEvent(mEvents.pop()); 118e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 119e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 12099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie havePendingEvents = deliverEvents(); 121ff1c1a2ab3ff2614bb6cea1f1d6f6e9c44a87464Arthur Ishiguro 122ff1c1a2ab3ff2614bb6cea1f1d6f6e9c44a87464Arthur Ishiguro mPowerControlManager.postEventLoopProcess(mEvents.size()); 123e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 124e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 12599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Deliver any events sitting in Nanoapps' own queues (we could drop them to 12699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // exit faster, but this is less code and should complete quickly under normal 12799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // conditions), then purge the main queue of events pending distribution. All 12899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // nanoapps should be prevented from sending events or messages at this point 12999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // via currentNanoappIsStopping() returning true. 13099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie flushNanoappEventQueues(); 1315d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie while (!mEvents.empty()) { 1325d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie freeEvent(mEvents.pop()); 1335d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie } 1345d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 13599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Unload all running nanoapps 1362de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol while (!mNanoapps.empty()) { 13799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie unloadNanoappAtIndex(mNanoapps.size() - 1); 1382de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol } 139e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 1402de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol LOGI("Exiting EventLoop"); 141e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} 142e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 1439d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddiebool EventLoop::startNanoapp(UniquePtr<Nanoapp>& nanoapp) { 1449d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie CHRE_ASSERT(!nanoapp.isNull()); 1452de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol bool success = false; 1465d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie auto *eventLoopManager = EventLoopManagerSingleton::get(); 14750d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol EventLoop& eventLoop = eventLoopManager->getEventLoop(); 1485d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie uint32_t existingInstanceId; 1495d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 1505d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie if (nanoapp.isNull()) { 1515d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie // no-op, invalid argument 15250d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol } else if (eventLoop.findNanoappInstanceIdByAppId(nanoapp->getAppId(), 15350d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol &existingInstanceId)) { 1545d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie LOGE("App with ID 0x%016" PRIx64 " already exists as instance ID 0x%" 1555d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie PRIx32, nanoapp->getAppId(), existingInstanceId); 1565d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie } else if (!mNanoapps.prepareForPush()) { 1572de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol LOGE("Failed to allocate space for new nanoapp"); 1582de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol } else { 1595d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie nanoapp->setInstanceId(eventLoopManager->getNextInstanceId()); 1606f7ee70aab8a27c9c6ec431dc12b71a2b2bb9babBrian Duddie LOGD("Instance ID %" PRIu32 " assigned to app ID 0x%016" PRIx64, 1616f7ee70aab8a27c9c6ec431dc12b71a2b2bb9babBrian Duddie nanoapp->getInstanceId(), nanoapp->getAppId()); 16282f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie 16382f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie Nanoapp *newNanoapp = nanoapp.get(); 16482f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie { 16582f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie LockGuard<Mutex> lock(mNanoappsLock); 16682f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie mNanoapps.push_back(std::move(nanoapp)); 16782f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // After this point, nanoapp is null as we've transferred ownership into 16882f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // mNanoapps.back() - use newNanoapp to reference it 16982f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie } 17082f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie 17182f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie mCurrentApp = newNanoapp; 17282f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie success = newNanoapp->start(); 1739d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie mCurrentApp = nullptr; 1749d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie if (!success) { 17582f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // TODO: to be fully safe, need to purge/flush any events and messages 17682f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // sent by the nanoapp here (but don't call nanoappEnd). For now, we just 17782f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // destroy the Nanoapp instance. 17882f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie LOGE("Nanoapp %" PRIu32 " failed to start", newNanoapp->getInstanceId()); 17982f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie 18082f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // Note that this lock protects against concurrent read and modification 18182f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // of mNanoapps, but we are assured that no new nanoapps were added since 18282f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie // we pushed the new nanoapp 1839d5b500a223ef73560f0dce38f50b809bde5dd0dBrian Duddie LockGuard<Mutex> lock(mNanoappsLock); 18482f7498d84fc3631b7631d32994318ad16f0b24dBrian Duddie mNanoapps.pop_back(); 18565d679851a2c062c26f685afb450f17bce177d29Brian Duddie } else { 18665d679851a2c062c26f685afb450f17bce177d29Brian Duddie notifyAppStatusChange(CHRE_EVENT_NANOAPP_STARTED, *newNanoapp); 1872de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol } 188e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 189e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 1902de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol return success; 191e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} 192e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 19399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddiebool EventLoop::unloadNanoapp(uint32_t instanceId, 19499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie bool allowSystemNanoappUnload) { 19599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie bool unloaded = false; 19699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 197e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie for (size_t i = 0; i < mNanoapps.size(); i++) { 19899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie if (instanceId == mNanoapps[i]->getInstanceId()) { 19999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie if (!allowSystemNanoappUnload && mNanoapps[i]->isSystemNanoapp()) { 20099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie LOGE("Refusing to unload system nanoapp"); 20199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } else { 20299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Make sure all messages sent by this nanoapp at least have their 20399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // associated free callback processing pending in the event queue (i.e. 20499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // there are no messages pending delivery to the host) 20599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie EventLoopManagerSingleton::get()->getHostCommsManager() 20699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie .flushMessagesSentByNanoapp(mNanoapps[i]->getAppId()); 20799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 20899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Distribute all inbound events we have at this time - here we're 20999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // interested in handling any message free callbacks generated by 21099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // flushMessagesSentByNanoapp() 21199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie flushInboundEventQueue(); 21299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 21399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Mark that this nanoapp is stopping early, so it can't send events or 21499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // messages during the nanoapp event queue flush 21599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie mStoppingNanoapp = mNanoapps[i].get(); 21699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 21799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Process any pending events, with the intent of ensuring that we free 21899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // all events generated by this nanoapp 21999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie flushNanoappEventQueues(); 22099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 22165d679851a2c062c26f685afb450f17bce177d29Brian Duddie // Post the unload event now (so we can reference the Nanoapp instance 22265d679851a2c062c26f685afb450f17bce177d29Brian Duddie // directly), but nanoapps won't get it until after the unload completes 22365d679851a2c062c26f685afb450f17bce177d29Brian Duddie notifyAppStatusChange(CHRE_EVENT_NANOAPP_STOPPED, *mStoppingNanoapp); 22465d679851a2c062c26f685afb450f17bce177d29Brian Duddie 22599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Finally, we are at a point where there should not be any pending 22699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // events or messages sent by the app that could potentially reference 22799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // the nanoapp's memory, so we are safe to unload it 22899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie unloadNanoappAtIndex(i); 22999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie mStoppingNanoapp = nullptr; 23099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 23199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // TODO: right now we assume that the nanoapp will clean up all of its 23299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // resource allocations in its nanoappEnd callback (memory, sensor 23399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // subscriptions, etc.), otherwise we're leaking resources. We should 23499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // perform resource cleanup automatically here to avoid these types of 23599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // potential leaks. 23699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 23799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie LOGD("Unloaded nanoapp with instanceId %" PRIu32, instanceId); 23899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie unloaded = true; 23999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 24099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie break; 241e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 242e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 243e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 24499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie return unloaded; 245e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} 246e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 247042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddiebool EventLoop::postEvent(uint16_t eventType, void *eventData, 2484927ee586656424c827920876673228fbdcf27c3Andrew Rossignol chreEventCompleteFunction *freeCallback, uint32_t senderInstanceId, 2494927ee586656424c827920876673228fbdcf27c3Andrew Rossignol uint32_t targetInstanceId) { 250042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie bool success = false; 2515d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 2525d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie if (mRunning) { 2535d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie Event *event = mEventPool.allocate(eventType, eventData, freeCallback, 2545d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie senderInstanceId, targetInstanceId); 2555d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie if (event != nullptr) { 2565d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie success = mEvents.push(event); 2575d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie } else { 2585d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie LOGE("Failed to allocate event"); 2595d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie } 2604927ee586656424c827920876673228fbdcf27c3Andrew Rossignol } 2615d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 262042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie return success; 263e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} 264e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 265e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddievoid EventLoop::stop() { 2664927ee586656424c827920876673228fbdcf27c3Andrew Rossignol postEvent(0, nullptr, nullptr, kSystemInstanceId, kSystemInstanceId); 2675d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie // Stop accepting new events and tell the main loop to finish 2686a8dd884cbc430594135c5d4801cea224f77d6e9Andrew Rossignol mRunning = false; 269e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} 270e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 2712fce52a25d14fcdcba888f8ff7892dffe3f55abaBrian DuddieNanoapp *EventLoop::findNanoappByInstanceId(uint32_t instanceId) const { 2729526b7b52ed3e6cb198c649f582877acb27f1c56Andrew Rossignol ConditionalLockGuard<Mutex> lock(mNanoappsLock, !inEventLoopThread()); 273f1694b5b8abc93de4e187a78c096977ad6cf4b56Brian Duddie return lookupAppByInstanceId(instanceId); 27430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol} 27530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol 27662f187d9d736346275492e916f6001576b68bb00Brian Duddiebool EventLoop::populateNanoappInfoForAppId( 27762f187d9d736346275492e916f6001576b68bb00Brian Duddie uint64_t appId, struct chreNanoappInfo *info) const { 2789526b7b52ed3e6cb198c649f582877acb27f1c56Andrew Rossignol ConditionalLockGuard<Mutex> lock(mNanoappsLock, !inEventLoopThread()); 27962f187d9d736346275492e916f6001576b68bb00Brian Duddie Nanoapp *app = lookupAppByAppId(appId); 28062f187d9d736346275492e916f6001576b68bb00Brian Duddie return populateNanoappInfo(app, info); 28162f187d9d736346275492e916f6001576b68bb00Brian Duddie} 28262f187d9d736346275492e916f6001576b68bb00Brian Duddie 28362f187d9d736346275492e916f6001576b68bb00Brian Duddiebool EventLoop::populateNanoappInfoForInstanceId( 28462f187d9d736346275492e916f6001576b68bb00Brian Duddie uint32_t instanceId, struct chreNanoappInfo *info) const { 2859526b7b52ed3e6cb198c649f582877acb27f1c56Andrew Rossignol ConditionalLockGuard<Mutex> lock(mNanoappsLock, !inEventLoopThread()); 28662f187d9d736346275492e916f6001576b68bb00Brian Duddie Nanoapp *app = lookupAppByInstanceId(instanceId); 28762f187d9d736346275492e916f6001576b68bb00Brian Duddie return populateNanoappInfo(app, info); 28862f187d9d736346275492e916f6001576b68bb00Brian Duddie} 28962f187d9d736346275492e916f6001576b68bb00Brian Duddie 2902fce52a25d14fcdcba888f8ff7892dffe3f55abaBrian Duddiebool EventLoop::currentNanoappIsStopping() const { 29199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie return (mCurrentApp == mStoppingNanoapp || !mRunning); 29299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie} 29399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 294d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishigurobool EventLoop::logStateToBuffer(char *buffer, size_t *bufferPos, 295d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro size_t bufferSize) const { 296d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro bool success = debugDumpPrint(buffer, bufferPos, bufferSize, "\nNanoapps:\n"); 297d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro for (const UniquePtr<Nanoapp>& app : mNanoapps) { 298d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro success &= app->logStateToBuffer(buffer, bufferPos, bufferSize); 299d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro } 30088f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol 30188f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol success &= debugDumpPrint(buffer, bufferPos, bufferSize, 30288f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol "\nEvent Loop:\n"); 30388f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol success &= debugDumpPrint(buffer, bufferPos, bufferSize, 30488f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol " Max event pool usage: %zu/%zu\n", 30588f21c7ca23d96f6ef568a06c98f3a5c4538140fAndrew Rossignol mMaxEventPoolUsage, kMaxEventCount); 306d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro return success; 307d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro} 308d0530f420d8bdaee755ec2834af407424de195e0Arthur Ishiguro 30999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddiebool EventLoop::deliverEvents() { 31099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie bool havePendingEvents = false; 31199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 31299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Do one loop of round-robin. We might want to have some kind of priority or 31399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // time sharing in the future, but this should be good enough for now. 31499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie for (const UniquePtr<Nanoapp>& app : mNanoapps) { 31599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie if (app->hasPendingEvent()) { 31699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie havePendingEvents |= deliverNextEvent(app); 31799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 3185d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie } 319529f5218422862fdbddc1500e6ae033e8867751eBrian Duddie 32099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie return havePendingEvents; 3215d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie} 3225d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 3235d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddiebool EventLoop::deliverNextEvent(const UniquePtr<Nanoapp>& app) { 3245d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie // TODO: cleaner way to set/clear this? RAII-style? 3255d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie mCurrentApp = app.get(); 3265d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie Event *event = app->processNextEvent(); 3275d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie mCurrentApp = nullptr; 3285d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 3295d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie if (event->isUnreferenced()) { 3305d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie freeEvent(event); 3315d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie } 3325d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 3335d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie return app->hasPendingEvent(); 3345d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie} 3355d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 33699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddievoid EventLoop::distributeEvent(Event *event) { 33799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie for (const UniquePtr<Nanoapp>& app : mNanoapps) { 33899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie if ((event->targetInstanceId == chre::kBroadcastInstanceId 33999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie && app->isRegisteredForBroadcastEvent(event->eventType)) 34099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie || event->targetInstanceId == app->getInstanceId()) { 34199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie app->postEvent(event); 34299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 34399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 34499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 34599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie if (event->isUnreferenced()) { 34699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // Events sent to the system instance ID are processed via the free callback 34799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // and are not expected to be delivered to any nanoapp, so no need to log a 34899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // warning in that case 34999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie if (event->senderInstanceId != kSystemInstanceId) { 35099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie LOGW("Dropping event 0x%" PRIx16, event->eventType); 35199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 35299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie freeEvent(event); 35399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 35499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie} 35599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 35699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddievoid EventLoop::flushInboundEventQueue() { 35799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie while (!mEvents.empty()) { 35899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie distributeEvent(mEvents.pop()); 35999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 36099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie} 36199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 36299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddievoid EventLoop::flushNanoappEventQueues() { 36399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie while (deliverEvents()); 36499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie} 36599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 36699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddievoid EventLoop::freeEvent(Event *event) { 36799f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie if (event->freeCallback != nullptr) { 36899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie // TODO: find a better way to set the context to the creator of the event 36999f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie mCurrentApp = lookupAppByInstanceId(event->senderInstanceId); 37099f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie event->freeCallback(event->eventType, event->eventData); 37199f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie mCurrentApp = nullptr; 37299f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie } 37399f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 37499f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie mEventPool.deallocate(event); 37599f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie} 37699f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddie 3772fce52a25d14fcdcba888f8ff7892dffe3f55abaBrian DuddieNanoapp *EventLoop::lookupAppByAppId(uint64_t appId) const { 37809a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie for (const UniquePtr<Nanoapp>& app : mNanoapps) { 37909a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie if (app->getAppId() == appId) { 38009a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie return app.get(); 38109a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie } 38209a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie } 38309a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie 38409a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie return nullptr; 38509a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie} 38609a4783208b5ba1e14d0f0102eb31e688caca28dBrian Duddie 3872fce52a25d14fcdcba888f8ff7892dffe3f55abaBrian DuddieNanoapp *EventLoop::lookupAppByInstanceId(uint32_t instanceId) const { 388042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie // The system instance ID always has nullptr as its Nanoapp pointer, so can 389042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie // skip iterating through the nanoapp list for that case 390042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie if (instanceId != kSystemInstanceId) { 3915d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie for (const UniquePtr<Nanoapp>& app : mNanoapps) { 392042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie if (app->getInstanceId() == instanceId) { 3932de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol return app.get(); 394042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie } 395e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 396e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 397e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 398e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie return nullptr; 399e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} 400e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 40165d679851a2c062c26f685afb450f17bce177d29Brian Duddievoid EventLoop::notifyAppStatusChange(uint16_t eventType, 40265d679851a2c062c26f685afb450f17bce177d29Brian Duddie const Nanoapp& nanoapp) { 40365d679851a2c062c26f685afb450f17bce177d29Brian Duddie auto *info = memoryAlloc<chreNanoappInfo>(); 40465d679851a2c062c26f685afb450f17bce177d29Brian Duddie if (info == nullptr) { 40565d679851a2c062c26f685afb450f17bce177d29Brian Duddie LOGE("Couldn't alloc app status change event"); 40665d679851a2c062c26f685afb450f17bce177d29Brian Duddie } else { 40765d679851a2c062c26f685afb450f17bce177d29Brian Duddie info->appId = nanoapp.getAppId(); 40865d679851a2c062c26f685afb450f17bce177d29Brian Duddie info->version = nanoapp.getAppVersion(); 40965d679851a2c062c26f685afb450f17bce177d29Brian Duddie info->instanceId = nanoapp.getInstanceId(); 41065d679851a2c062c26f685afb450f17bce177d29Brian Duddie 41150d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol if (!postEvent(eventType, info, freeEventDataCallback)) { 41265d679851a2c062c26f685afb450f17bce177d29Brian Duddie LOGE("Couldn't post app status change event"); 41365d679851a2c062c26f685afb450f17bce177d29Brian Duddie memoryFree(info); 41465d679851a2c062c26f685afb450f17bce177d29Brian Duddie } 41565d679851a2c062c26f685afb450f17bce177d29Brian Duddie } 41665d679851a2c062c26f685afb450f17bce177d29Brian Duddie} 41765d679851a2c062c26f685afb450f17bce177d29Brian Duddie 41899f01ac9bd6e351538cb8922ef15d9e838e7339aBrian Duddievoid EventLoop::unloadNanoappAtIndex(size_t index) { 4195d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie const UniquePtr<Nanoapp>& nanoapp = mNanoapps[index]; 420e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 4215d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie // Let the app know it's going away 4225d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie mCurrentApp = nanoapp.get(); 4235d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie nanoapp->end(); 4245d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie mCurrentApp = nullptr; 4255d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie 4265d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie // Destroy the Nanoapp instance 4275d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie { 4285d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie LockGuard<Mutex> lock(mNanoappsLock); 4295d9b2d68940f7dac47bf2fbad6f6069ed3b2faaaBrian Duddie mNanoapps.erase(index); 430e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie } 431e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} 432e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 4336851c47f6eecf75c66f7df0b1331b0e392201e14Andrew Rossignol} // namespace chre 434