1/* 2 * Copyright (C) 2017 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#include <cinttypes> 18 19#include "chre_api/chre.h" 20#include "chre/core/event_loop.h" 21#include "chre/core/event_loop_manager.h" 22#include "chre/platform/assert.h" 23#include "chre/platform/log.h" 24#include "chre/platform/static_nanoapp_init.h" 25#include "chre/util/nanoapp/app_id.h" 26#include "chre/util/time.h" 27 28/** 29 * @file 30 * A nanoapp exclusively for testing, which unloads the spammer nanoapp after a 31 * short delay. Must only be compiled as a static/internal nanoapp. 32 */ 33 34namespace chre { 35namespace { 36 37constexpr uint32_t kAppVersion = 99; 38 39void handleUnload(uint16_t /* eventType */, void * /* data */) { 40 EventLoop& eventLoop = EventLoopManagerSingleton::get()->getEventLoop(); 41 uint32_t instanceId; 42 43 LOGD("About to unload spammer nanoapp"); 44 if (!eventLoop.findNanoappInstanceIdByAppId(kSpammerAppId, &instanceId)) { 45 LOGE("Couldn't unload nanoapp: not found"); 46 } else if (!eventLoop.unloadNanoapp(instanceId, true)) { 47 LOGE("Failed to unload nanoapp"); 48 } 49} 50 51bool nanoappStart() { 52 LOGI("Unload tester started as instance %" PRIu32, chreGetInstanceId()); 53 54 constexpr uint64_t kTimerDuration = Seconds(2).toRawNanoseconds(); 55 uint32_t timerHandle = chreTimerSet(kTimerDuration, 56 nullptr, true /* oneShot */); 57 CHRE_ASSERT_LOG(timerHandle != CHRE_TIMER_INVALID, "Couldn't start timer!"); 58 59 bool eventSent = chreSendEvent(CHRE_EVENT_FIRST_USER_VALUE, nullptr, nullptr, 60 chreGetInstanceId()); 61 CHRE_ASSERT_LOG(eventSent, "Couldn't send event to self!"); 62 63 struct chreNanoappInfo info; 64 bool gotInfo = chreGetNanoappInfoByInstanceId(chreGetInstanceId(), &info); 65 CHRE_ASSERT(gotInfo); 66 CHRE_ASSERT(info.appId == chreGetAppId()); 67 CHRE_ASSERT(info.appId == kUnloadTesterAppId); 68 CHRE_ASSERT(info.version == kAppVersion); 69 CHRE_ASSERT(info.instanceId == chreGetInstanceId()); 70 71 chreConfigureNanoappInfoEvents(true); 72 return true; 73} 74 75void nanoappHandleEvent(uint32_t senderInstanceId, 76 uint16_t eventType, 77 const void *eventData) { 78 if (eventType == CHRE_EVENT_FIRST_USER_VALUE 79 && senderInstanceId == chreGetInstanceId()) { 80 struct chreNanoappInfo info; 81 if (!chreGetNanoappInfoByAppId(kSpammerAppId, &info)) { 82 LOGW("Couldn't get spammer's app info - not running?"); 83 } 84 } else if (eventType == CHRE_EVENT_TIMER) { 85 // We can't do the unload from the context of another nanoapp's handle 86 // event callback, so get into the system context 87 if (!EventLoopManagerSingleton::get()->deferCallback( 88 SystemCallbackType::HandleUnloadNanoapp, nullptr, handleUnload)) { 89 LOGE("Couldn't defer callback"); 90 } 91 } else if (eventType == CHRE_EVENT_NANOAPP_STARTED 92 || eventType == CHRE_EVENT_NANOAPP_STOPPED) { 93 const auto *info = static_cast<const chreNanoappInfo *>(eventData); 94 if (info->appId == kSpammerAppId) { 95 LOGD("Received %s event for spammer instance %" PRIu32, 96 (eventType == CHRE_EVENT_NANOAPP_STARTED) ? "start" : "stop", 97 info->instanceId); 98 } 99 } 100} 101 102void nanoappEnd() {} 103 104} // anonymous namespace 105} // namespace chre 106 107CHRE_STATIC_NANOAPP_INIT(UnloadTester, chre::kUnloadTesterAppId, kAppVersion); 108