Run executables directly (#645)
- Apps can be launched directly from file paths (including Files app support) - Added executable detection to identify unsupported or invalid binaries before launch. - App startup is now streamlined through separate registered-app and direct-execution interfaces. - Existing app launch points were migrated to the updated startup APIs.
This commit is contained in:
committed by
GitHub
parent
643cbc3806
commit
a0b2ee7ebc
@@ -0,0 +1,60 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
/**
|
||||
* Deep-copies @a argv (@a argc <= 0 => NULL, matching "no parameters"). Caller passes the result
|
||||
* to app_scheduler_start(), which takes ownership regardless of outcome.
|
||||
* @return NULL if @a argc <= 0 (no parameters), or if allocation failed. For @a argc > 0,
|
||||
* these are the only cases that produce NULL, so a caller can tell them apart by its own
|
||||
* already-known @a argc: NULL back from a positive @a argc always means allocation failed.
|
||||
* All partial allocations are freed before returning NULL, so failure never leaks memory.
|
||||
*/
|
||||
inline char** app_arguments_copy(int argc, const char* const argv[]) {
|
||||
if (argc <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* copy = new (std::nothrow) char*[argc + 1];
|
||||
if (copy == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int copied = 0;
|
||||
for (; copied < argc; copied++) {
|
||||
size_t length = strlen(argv[copied]);
|
||||
copy[copied] = new (std::nothrow) char[length + 1];
|
||||
if (copy[copied] == nullptr) {
|
||||
break;
|
||||
}
|
||||
memcpy(copy[copied], argv[copied], length + 1);
|
||||
}
|
||||
|
||||
if (copied < argc) {
|
||||
for (int i = 0; i < copied; i++) {
|
||||
delete[] copy[i];
|
||||
}
|
||||
delete[] copy;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
copy[argc] = nullptr;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees a deep-copied argv previously built by app_arguments_copy(): each individually
|
||||
* heap-allocated string, then the array itself. Safe to call with count == 0 / values == nullptr
|
||||
* (no-op).
|
||||
*/
|
||||
inline void app_arguments_free(int count, char** values) {
|
||||
if (values == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
delete[] values[i];
|
||||
}
|
||||
delete[] values;
|
||||
}
|
||||
@@ -38,21 +38,22 @@ struct AppCompletionSignal {
|
||||
/** A registered/running app instance, as tracked internally by app-module. */
|
||||
struct AppInstanceRecord {
|
||||
uint32_t id;
|
||||
/** NULL for an instance started via app_execute() (app/execute.h; no manifest involved). */
|
||||
const AppManifest* manifest;
|
||||
AppInstanceState state;
|
||||
/** The FreeRTOS task currently executing AppLoaderApi::run() for this instance; NULL when not running. */
|
||||
TaskHandle_t task;
|
||||
|
||||
/** 0 for a top-level launch (app_manager_start()). Non-zero for a modal child launched via
|
||||
* app_manager_start_for_result() - the instance that receives this child's APP_EVENT_RESULT. */
|
||||
/** 0 for a top-level launch (app_start()). Non-zero for a modal child launched via
|
||||
* app_start_for_result() - the instance that receives this child's APP_EVENT_RESULT. */
|
||||
uint32_t parent_id = 0;
|
||||
|
||||
/** This instance's completion signal - see AppCompletionSignal. Set once by
|
||||
* app_scheduler_start(), never reassigned. */
|
||||
AppCompletionSignal* completion = nullptr;
|
||||
|
||||
/** This instance's fd table. Constructed by start_internal() before insertion into
|
||||
* AppLedger::instances, torn down (every open fd closed) when the instance's task exits. */
|
||||
/** This instance's fd table. Constructed by app_manager_start_internal() before insertion
|
||||
* into AppLedger::instances, torn down (every open fd closed) when the instance's task exits. */
|
||||
AppFdTable fd_table {};
|
||||
};
|
||||
|
||||
@@ -70,17 +71,3 @@ inline AppLedger& app_ledger() {
|
||||
static AppLedger ledger;
|
||||
return ledger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees a deep-copied argv previously built by app_manager_start_with_parameters()/app_manager_start_for_result():
|
||||
* each individually heap-allocated string, then the array itself. Safe to call with count == 0 values == nullptr (no-op).
|
||||
*/
|
||||
inline void app_ledger_free_arguments(int count, char** values) {
|
||||
if (values == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
delete[] values[i];
|
||||
}
|
||||
delete[] values;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#include <app/manager.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Shared core behind every app_start*() (app/manager.h) and app_execute*()
|
||||
* (app/execute.h) entry point: deep-copies @a argv, allocates an instance id, installs
|
||||
* @a bindings into the new instance's fd table before app_scheduler_start() is called, then
|
||||
* starts it. @a manifest may be NULL for a location-based start with no manifest at all.
|
||||
* @retval ERROR_INVALID_ARGUMENT @a binding_count is nonzero but @a bindings is NULL
|
||||
* @retval ERROR_NOT_FOUND no AppLoaderApi is registered for @a location.type
|
||||
* @retval ERROR_OUT_OF_RANGE a binding's producer_fd is out of range
|
||||
* @retval ERROR_RESOURCE a binding's event_group has no free bits left to claim
|
||||
* @retval ERROR_NONE on success
|
||||
*/
|
||||
error_t app_manager_start_internal(const struct AppManifest* manifest, struct AppLocation location, struct AppStackConfig stack, AppInstanceId parent_instance_id, int argc, const char* const argv[], const struct AppStreamBinding* bindings, size_t binding_count, AppInstanceId* out_app_instance_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user