| 74 | } |
| 75 | |
| 76 | void LoaderService::onStopTopAppMessage(const std::string& id) { |
| 77 | auto lock = mutex.asScopedLock(); |
| 78 | if (!lock.lock(LOADER_TIMEOUT)) { |
| 79 | LOGGER.error(LOG_MESSAGE_MUTEX_LOCK_FAILED); |
| 80 | return; |
| 81 | } |
| 82 | |
| 83 | size_t original_stack_size = appStack.size(); |
| 84 | |
| 85 | if (original_stack_size == 0) { |
| 86 | LOGGER.error("Stop app: no app running"); |
| 87 | return; |
| 88 | } |
| 89 | |
| 90 | // Stop current app |
| 91 | auto app_to_stop = appStack[appStack.size() - 1]; |
| 92 | |
| 93 | if (app_to_stop->getManifest().appId != id) { |
| 94 | LOGGER.error("Stop app: id mismatch (wanted {} but found {} on top of stack)", id, app_to_stop->getManifest().appId); |
| 95 | return; |
| 96 | } |
| 97 | |
| 98 | if (original_stack_size == 1 && app_to_stop->getManifest().appName != "Boot") { |
| 99 | LOGGER.error("Stop app: can't stop root app"); |
| 100 | return; |
| 101 | } |
| 102 | |
| 103 | bool result_set = false; |
| 104 | app::Result result; |
| 105 | std::unique_ptr<Bundle> result_bundle; |
| 106 | if (app_to_stop->getApp()->moveResult(result, result_bundle)) { |
| 107 | result_set = true; |
| 108 | } |
| 109 | |
| 110 | auto app_to_stop_launch_id = app_to_stop->getLaunchId(); |
| 111 | |
| 112 | transitionAppToState(app_to_stop, app::State::Hiding); |
| 113 | transitionAppToState(app_to_stop, app::State::Destroyed); |
| 114 | |
| 115 | appStack.pop_back(); |
| 116 | |
| 117 | // We only expect the app to be referenced within the current scope |
| 118 | if (app_to_stop.use_count() > 1) { |
| 119 | LOGGER.warn("Memory leak: Stopped {}, but use count is {}", app_to_stop->getManifest().appId, app_to_stop.use_count() - 1); |
| 120 | } |
| 121 | |
| 122 | // Refcount is expected to be 2: 1 within app_to_stop and 1 within the current scope |
| 123 | if (app_to_stop->getApp().use_count() > 2) { |
| 124 | LOGGER.warn("Memory leak: Stopped {}, but use count is {}", app_to_stop->getManifest().appId, app_to_stop->getApp().use_count() - 2); |
| 125 | } |
| 126 | |
| 127 | #ifdef ESP_PLATFORM |
| 128 | LOGGER.info("Free heap: {}", heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); |
| 129 | #endif |
| 130 | |
| 131 | std::shared_ptr<app::AppInstance> instance_to_resume; |
| 132 | // If there's a previous app, resume it |
| 133 | if (!appStack.empty()) { |
nothing calls this directly
no test coverage detected