mirror of
https://gitee.com/openharmony/startup_appspawn
synced 2024-11-23 07:00:17 +00:00
Xwadd new msg to old property
Signed-off-by: zhongning5 <zhongning5@huawei.com>
This commit is contained in:
parent
a9b2f799eb
commit
49dc924cc1
8
BUILD.gn
8
BUILD.gn
@ -16,10 +16,12 @@ import("//build/ohos.gni")
|
||||
config("appspawn_config") {
|
||||
visibility = [ "./*" ]
|
||||
include_dirs = [
|
||||
"${appspawn_path}",
|
||||
"common",
|
||||
"standard",
|
||||
"adapter",
|
||||
"interfaces/innerkits/include",
|
||||
"interfaces/innerkits_new/include",
|
||||
"util/include",
|
||||
"//third_party/json/include",
|
||||
]
|
||||
@ -61,6 +63,7 @@ if (!defined(ohos_lite)) {
|
||||
"ability_runtime:runtime",
|
||||
"access_token:libtoken_setproc",
|
||||
"ace_engine:ace_forward_compatibility",
|
||||
"cJSON:cjson",
|
||||
"c_utils:utils",
|
||||
"common_event_service:cesfwk_innerkits",
|
||||
"config_policy:configpolicy_util",
|
||||
@ -132,6 +135,7 @@ if (!defined(ohos_lite)) {
|
||||
"${appspawn_path}/adapter/appspawn_sandbox.cpp",
|
||||
"${appspawn_path}/common/appspawn_server.c",
|
||||
"${appspawn_path}/interfaces/innerkits/src/appspawn_mount_permission.cpp",
|
||||
"${appspawn_path}/standard/appspawn_msgmgr.c",
|
||||
"${appspawn_path}/standard/appspawn_process.c",
|
||||
"${appspawn_path}/standard/appspawn_service.c",
|
||||
"${appspawn_path}/util/src/env_utils.cpp",
|
||||
@ -148,10 +152,12 @@ if (!defined(ohos_lite)) {
|
||||
}
|
||||
configs = [ ":appspawn_config" ]
|
||||
ldflags = [ "-Wl,--dynamic-linker,/system/bin/linker64z" ]
|
||||
deps = []
|
||||
external_deps = [
|
||||
"ability_runtime:appkit_native",
|
||||
"access_token:libtoken_setproc",
|
||||
"access_token:libtokenid_sdk",
|
||||
"cJSON:cjson",
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"eventhandler:libeventhandler",
|
||||
@ -191,7 +197,7 @@ if (!defined(ohos_lite)) {
|
||||
|
||||
if (appspawn_report_event) {
|
||||
cflags += [ "-DREPORT_EVENT" ]
|
||||
deps = [ "adapter/sysevent:event_reporter" ]
|
||||
deps += [ "adapter/sysevent:event_reporter" ]
|
||||
}
|
||||
|
||||
subsystem_name = "${subsystem_name}"
|
||||
|
@ -37,7 +37,7 @@ const char* RENDERER_NAME = "renderer";
|
||||
#define NWEBSPAWN_SERVER_NAME "nwebspawn"
|
||||
using namespace OHOS::Security::AccessToken;
|
||||
|
||||
int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int SetAppAccessToken(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
int32_t ret = 0;
|
||||
@ -64,7 +64,7 @@ int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int SetSelinuxCon(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef WITH_SELINUX
|
||||
if (content->isNweb) {
|
||||
@ -100,7 +100,7 @@ int SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetUidGidFilter(struct AppSpawnContent_ *content)
|
||||
void SetUidGidFilter(struct AppSpawnContent *content)
|
||||
{
|
||||
#ifdef WITH_SECCOMP
|
||||
bool ret = false;
|
||||
@ -123,7 +123,7 @@ void SetUidGidFilter(struct AppSpawnContent_ *content)
|
||||
#endif
|
||||
}
|
||||
|
||||
int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int SetSeccompFilter(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef WITH_SECCOMP
|
||||
const char *appName = APP_NAME;
|
||||
|
@ -24,19 +24,19 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct AppSpawnContentExt_ AppSpawnContentExt;
|
||||
typedef struct AppInfo_ AppSpawnAppInfo;
|
||||
typedef struct AppSpawnContentExt AppSpawnContentExt;
|
||||
typedef struct AppInfo AppSpawnAppInfo;
|
||||
|
||||
int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int32_t SetAppSandboxProperty(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int SetAppAccessToken(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int SetSelinuxCon(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
void LoadExtendLib(AppSpawnContent *content);
|
||||
void LoadExtendLibNweb(AppSpawnContent *content);
|
||||
void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client);
|
||||
void RunChildProcessorNweb(AppSpawnContent *content, AppSpawnClient *client);
|
||||
void LoadAppSandboxConfig(AppSpawnContent *content);
|
||||
void SetUidGidFilter(struct AppSpawnContent_ *content);
|
||||
int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
void SetUidGidFilter(struct AppSpawnContent *content);
|
||||
int SetSeccompFilter(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
void HandleInternetPermission(const AppSpawnClient *client);
|
||||
|
||||
void DisallowInternet(void);
|
||||
|
@ -70,7 +70,7 @@ void LoadAppSandboxConfig(AppSpawnContent *content)
|
||||
content->sandboxNsFlags = SandboxUtils::GetSandboxNsFlags(content->isNweb);
|
||||
}
|
||||
|
||||
int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int32_t SetAppSandboxProperty(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client");
|
||||
AppSpawnClientExt *clientExt = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
|
@ -14,6 +14,8 @@
|
||||
ability_runtime_path = "//foundation/ability/ability_runtime"
|
||||
ability_runtime_kits_path = "${ability_runtime_path}/frameworks/kits"
|
||||
appspawn_path = "//base/startup/appspawn"
|
||||
appspawn_innerkits_path = "//base/startup/appspawn/interfaces/innerkits_new"
|
||||
startup_path = "//base/startup"
|
||||
subsystem_name = "startup"
|
||||
part_name = "appspawn"
|
||||
module_output_path = "${part_name}/appspawn_l2"
|
||||
|
12
bundle.json
12
bundle.json
@ -60,7 +60,8 @@
|
||||
"ui_lite",
|
||||
"code_signature",
|
||||
"bounds_checking_function",
|
||||
"zlib"
|
||||
"zlib",
|
||||
"cJSON"
|
||||
],
|
||||
"third_party": [
|
||||
"bounds_checking_function",
|
||||
@ -74,6 +75,15 @@
|
||||
"//base/startup/appspawn:appspawn_all"
|
||||
],
|
||||
"inner_kits": [
|
||||
{
|
||||
"header": {
|
||||
"header_base": "//base/startup/appspawn/interfaces/innerkits_new/include/",
|
||||
"header_files": [
|
||||
"appspawn.h"
|
||||
]
|
||||
},
|
||||
"name": "//base/startup/appspawn/interfaces/innerkits_new/client:appspawn_client"
|
||||
},
|
||||
{
|
||||
"header": {
|
||||
"header_base": "//base/startup/appspawn/interfaces/innerkits/include/",
|
||||
|
@ -44,7 +44,7 @@ long long DiffTime(struct timespec *startTime)
|
||||
return diff;
|
||||
}
|
||||
|
||||
static void NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result)
|
||||
static void NotifyResToParent(struct AppSpawnContent *content, AppSpawnClient *client, int result)
|
||||
{
|
||||
if (content->notifyResToParent != NULL) {
|
||||
content->notifyResToParent(content, client, result);
|
||||
@ -78,7 +78,7 @@ void exit(int code)
|
||||
}
|
||||
#endif
|
||||
|
||||
int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen)
|
||||
int DoStartApp(struct AppSpawnContent *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
APPSPAWN_LOGV("DoStartApp id %{public}d longProcNameLen %{public}u", client->id, longProcNameLen);
|
||||
@ -88,14 +88,12 @@ int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *l
|
||||
|
||||
if (content->setEnvInfo) {
|
||||
ret = content->setEnvInfo(content, client);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to setEnvInfo");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setEnvInfo");
|
||||
}
|
||||
|
||||
if (content->setAppSandbox) {
|
||||
ret = content->setAppSandbox(content, client);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to set app sandbox");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to set app sandbox");
|
||||
}
|
||||
|
||||
(void)umask(DEFAULT_UMASK);
|
||||
@ -107,38 +105,32 @@ int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *l
|
||||
|
||||
if (content->setXpmConfig) {
|
||||
ret = content->setXpmConfig(content, client);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to set setXpmConfig");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to set setXpmConfig");
|
||||
}
|
||||
|
||||
if (content->setProcessName) {
|
||||
ret = content->setProcessName(content, client, content->longProcName, content->longProcNameLen);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to set setProcessName");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to set setProcessName");
|
||||
}
|
||||
|
||||
if (content->setUidGid) {
|
||||
ret = content->setUidGid(content, client);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to setUidGid");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setUidGid");
|
||||
}
|
||||
|
||||
if (content->setFileDescriptors) {
|
||||
ret = content->setFileDescriptors(content, client);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to setFileDescriptors");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setFileDescriptors");
|
||||
}
|
||||
|
||||
if (content->setCapabilities) {
|
||||
ret = content->setCapabilities(content, client);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to setCapabilities");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setCapabilities");
|
||||
}
|
||||
|
||||
if (content->waitForDebugger) {
|
||||
ret = content->waitForDebugger(client);
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret);
|
||||
return ret, "Failed to waitForDebugger");
|
||||
APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to waitForDebugger");
|
||||
}
|
||||
|
||||
#ifdef SECURITY_COMPONENT_ENABLE
|
||||
@ -154,7 +146,7 @@ static int AppSpawnChild(void *arg)
|
||||
{
|
||||
APPSPAWN_CHECK(arg != NULL, return -1, "Invalid arg for appspawn child");
|
||||
AppSandboxArg *sandbox = (AppSandboxArg *)arg;
|
||||
struct AppSpawnContent_ *content = sandbox->content;
|
||||
struct AppSpawnContent *content = sandbox->content;
|
||||
AppSpawnClient *client = sandbox->client;
|
||||
int ret = -1;
|
||||
|
||||
|
@ -38,63 +38,63 @@ extern "C" {
|
||||
|
||||
#define APPSPAWN_CHECK_EXIT "AppSpawnCheckUnexpectedExitCall"
|
||||
|
||||
typedef struct AppSpawnClient_ {
|
||||
typedef struct AppSpawnClient {
|
||||
uint32_t id;
|
||||
uint32_t flags; // Save negotiated flags
|
||||
uint32_t cloneFlags; // for clone flags
|
||||
} AppSpawnClient;
|
||||
|
||||
#define MAX_SOCKEYT_NAME_LEN 128
|
||||
typedef struct AppSpawnContent_ {
|
||||
typedef struct AppSpawnContent {
|
||||
char *longProcName;
|
||||
uint32_t longProcNameLen;
|
||||
uint32_t sandboxNsFlags;
|
||||
bool isNweb;
|
||||
|
||||
// system
|
||||
void (*loadExtendLib)(struct AppSpawnContent_ *content);
|
||||
int (*initAppSpawn)(struct AppSpawnContent_ *content);
|
||||
void (*runAppSpawn)(struct AppSpawnContent_ *content, int argc, char *const argv[]);
|
||||
void (*setUidGidFilter)(struct AppSpawnContent_ *content);
|
||||
void (*loadExtendLib)(struct AppSpawnContent *content);
|
||||
int (*initAppSpawn)(struct AppSpawnContent *content);
|
||||
void (*runAppSpawn)(struct AppSpawnContent *content, int argc, char *const argv[]);
|
||||
void (*setUidGidFilter)(struct AppSpawnContent *content);
|
||||
|
||||
// for child
|
||||
void (*clearEnvironment)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
void (*initDebugParams)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setAppAccessToken)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setAppSandbox)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setKeepCapabilities)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setFileDescriptors)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setEnvInfo)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setProcessName)(struct AppSpawnContent_ *content, AppSpawnClient *client,
|
||||
void (*clearEnvironment)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
void (*initDebugParams)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setAppAccessToken)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setAppSandbox)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setKeepCapabilities)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setFileDescriptors)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setEnvInfo)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setProcessName)(struct AppSpawnContent *content, AppSpawnClient *client,
|
||||
char *longProcName, uint32_t longProcNameLen);
|
||||
int (*setUidGid)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setCapabilities)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setXpmConfig)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setUidGid)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setCapabilities)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setXpmConfig)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
|
||||
void (*notifyResToParent)(struct AppSpawnContent_ *content, AppSpawnClient *client, int result);
|
||||
void (*runChildProcessor)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
void (*notifyResToParent)(struct AppSpawnContent *content, AppSpawnClient *client, int result);
|
||||
void (*runChildProcessor)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
#ifndef ASAN_DETECTOR
|
||||
int (*setAsanEnabledEnv)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setAsanEnabledEnv)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
#endif
|
||||
// for pid namespace
|
||||
int (*enablePidNs)(struct AppSpawnContent_ *content);
|
||||
int (*enablePidNs)(struct AppSpawnContent *content);
|
||||
|
||||
// for cold start
|
||||
int (*coldStartApp)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*getWrapBundleNameValue)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*setSeccompFilter)(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int (*coldStartApp)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*getWrapBundleNameValue)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
int (*setSeccompFilter)(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
void (*handleInternetPermission)(const AppSpawnClient *client);
|
||||
int (*waitForDebugger)(AppSpawnClient *client);
|
||||
} AppSpawnContent;
|
||||
|
||||
typedef struct {
|
||||
struct AppSpawnContent_ *content;
|
||||
struct AppSpawnContent *content;
|
||||
AppSpawnClient *client;
|
||||
} AppSandboxArg;
|
||||
|
||||
AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int cold);
|
||||
int AppSpawnProcessMsg(AppSandboxArg *sandbox, pid_t *childPid);
|
||||
int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen);
|
||||
int DoStartApp(struct AppSpawnContent *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen);
|
||||
long long DiffTime(struct timespec *startTime);
|
||||
pid_t AppSpawnFork(int (*childFunc)(void *arg), void *args);
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
@ -80,13 +80,13 @@ typedef enum AppOperateType_ {
|
||||
#define APPSPAWN_COLDSTART_KEY "cold-start"
|
||||
#define NWEBSPAWN_COLDSTART_KEY "nweb-cold-start"
|
||||
|
||||
typedef struct ExtraInfo_ {
|
||||
typedef struct ExtraInfo {
|
||||
uint32_t totalLength;
|
||||
uint32_t savedLength;
|
||||
char* data;
|
||||
} ExtraInfo;
|
||||
|
||||
typedef struct AppParameter_ {
|
||||
typedef struct AppParameter {
|
||||
AppOperateType code;
|
||||
uint32_t flags;
|
||||
int32_t pid; // query render process exited status by render process pid
|
||||
|
@ -24,8 +24,7 @@ if (!defined(ohos_lite)) {
|
||||
sources = [
|
||||
"${appspawn_path}/modules/sandbox/appspawn_permission.c",
|
||||
"${appspawn_path}/util/src/appspawn_utils.c",
|
||||
"${appspawn_path}/util/src/json_utils.cpp",
|
||||
"../permission/appspawn_mount_permission.cpp",
|
||||
"../permission/appspawn_mount_permission.c",
|
||||
"appspawn_client.c",
|
||||
"appspawn_msg.c",
|
||||
]
|
||||
@ -35,6 +34,7 @@ if (!defined(ohos_lite)) {
|
||||
"../permission",
|
||||
"../module_engine/include",
|
||||
"${appspawn_path}",
|
||||
"${appspawn_path}/common",
|
||||
"${appspawn_path}/modules/sandbox",
|
||||
"${appspawn_path}/util/include",
|
||||
]
|
||||
@ -52,8 +52,8 @@ if (!defined(ohos_lite)) {
|
||||
public_configs = [ ":exported_header_files" ]
|
||||
version_script = "libappspawn_client.versionscript"
|
||||
|
||||
deps = [ "//third_party/cJSON:cjson" ]
|
||||
external_deps = [
|
||||
"cJSON:cjson",
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"hilog:libhilog",
|
||||
|
@ -253,6 +253,10 @@ int AppSpawnClientDestroy(AppSpawnClientHandle handle)
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
pthread_mutex_destroy(&reqMgr->mutex);
|
||||
if (reqMgr->socketId >= 0) {
|
||||
CloseClientSocket(reqMgr->socketId);
|
||||
reqMgr->socketId = -1;
|
||||
}
|
||||
free(reqMgr);
|
||||
return 0;
|
||||
}
|
||||
|
@ -274,6 +274,8 @@ static int CreateBaseMsg(AppSpawnReqMsgNode *reqNode, uint32_t msgType, const ch
|
||||
APPSPAWN_CHECK_ONLY_EXPER(msgType == MSG_APP_SPAWN || msgType == MSG_SPAWN_NATIVE_PROCESS, return 0);
|
||||
ret = SetFlagsTlv(reqNode, block, &reqNode->msgFlags, TLV_MSG_FLAGS, MAX_FLAGS_INDEX);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
|
||||
int maxCount = GetMaxPermissionIndex();
|
||||
APPSPAWN_CHECK(maxCount > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid max for permission %{public}s", processName);
|
||||
ret = SetFlagsTlv(reqNode, block, &reqNode->permissionFlags, TLV_PERMISSION, GetMaxPermissionIndex());
|
||||
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
|
||||
APPSPAWN_LOGV("CreateBaseMsg msgLen: %{public}u %{public}u", reqNode->msg->msgLen, block->currentIndex);
|
||||
|
@ -31,6 +31,9 @@
|
||||
AppSpawnReqMsgSetFlags;
|
||||
AppSpawnReqMsgAddStringInfo;
|
||||
AppSpawnTerminateMsgCreate;
|
||||
GetPermissionIndex;
|
||||
GetMaxPermissionIndex;
|
||||
GetPermissionByIndex;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
@ -32,6 +32,8 @@ extern "C" {
|
||||
* 如果调用AppSpawnClientSendMsg后,消息句柄不需要处理
|
||||
* 否则需要调用 AppSpawnReqMsgFree 释放句柄
|
||||
*
|
||||
* 所有字符串输入的接口,只能接受合法的字符串,输入null、""、和大于合法长度的字符串都返回错误
|
||||
*
|
||||
*/
|
||||
typedef void *AppSpawnReqMsgHandle;
|
||||
|
||||
@ -41,6 +43,7 @@ typedef void *AppSpawnReqMsgHandle;
|
||||
*/
|
||||
typedef void *AppSpawnClientHandle;
|
||||
|
||||
#define INVALID_PERMISSION_INDEX (-1)
|
||||
#define INVALID_REQ_HANDLE NULL
|
||||
#define NWEBSPAWN_SERVER_NAME "nwebspawn"
|
||||
#define APPSPAWN_SERVER_NAME "appspawn"
|
||||
@ -239,6 +242,30 @@ int AppSpawnReqMsgAddExtInfo(AppSpawnReqMsgHandle reqHandle, const char *name, c
|
||||
* @return if succeed return 0,else return other value
|
||||
*/
|
||||
int AppSpawnReqMsgAddStringInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const char *value);
|
||||
|
||||
/**
|
||||
* @brief Get the permission index by permission name
|
||||
*
|
||||
* @param permission permission name
|
||||
* @return int32_t permission index, if not exit, return INVALID_PERMISSION_INDEX
|
||||
*/
|
||||
int32_t GetPermissionIndex(const char *permission);
|
||||
|
||||
/**
|
||||
* @brief Get the max permission Index
|
||||
*
|
||||
* @return int32_t max permission Index
|
||||
*/
|
||||
int32_t GetMaxPermissionIndex(void);
|
||||
|
||||
/**
|
||||
* @brief Get the permission name by index
|
||||
*
|
||||
* @param index permission index
|
||||
* @return const char* permission name
|
||||
*/
|
||||
const char *GetPermissionByIndex(int32_t index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -33,8 +33,8 @@ extern "C" {
|
||||
|
||||
typedef struct TagAppSpawnMgr AppSpawnMgr;
|
||||
typedef struct TagAppSpawningCtx AppSpawningCtx;
|
||||
typedef struct TagAppSpawnContent AppSpawnContent;
|
||||
typedef struct TagAppSpawnClient AppSpawnClient;
|
||||
typedef struct AppSpawnContent AppSpawnContent;
|
||||
typedef struct AppSpawnClient AppSpawnClient;
|
||||
typedef struct TagAppSpawnedProcess AppSpawnedProcess;
|
||||
|
||||
typedef enum {
|
||||
|
241
interfaces/innerkits_new/permission/appspawn_mount_permission.cpp → interfaces/innerkits_new/permission/appspawn_mount_permission.c
Normal file → Executable file
241
interfaces/innerkits_new/permission/appspawn_mount_permission.cpp → interfaces/innerkits_new/permission/appspawn_mount_permission.c
Normal file → Executable file
@ -1,128 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "appspawn_mount_permission.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "appspawn_sandbox.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "json_utils.h"
|
||||
|
||||
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int32_t g_maxPermissionIndex = -1;
|
||||
static SandboxSection g_permissionQueue;
|
||||
|
||||
static int PermissionNodeCompareProc(ListNode *node, ListNode *newNode)
|
||||
{
|
||||
SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxNode, node);
|
||||
SandboxPermissionNode *newPermissionNode = (SandboxPermissionNode *)ListEntry(newNode, SandboxNode, node);
|
||||
return strcmp(permissionNode->name, newPermissionNode->name);
|
||||
}
|
||||
|
||||
static int ParsePermissionConfig(const cJSON *permissionConfigs)
|
||||
{
|
||||
cJSON *config = nullptr;
|
||||
cJSON_ArrayForEach(config, permissionConfigs)
|
||||
{
|
||||
const char *name = config->string;
|
||||
APPSPAWN_LOGV("ParsePermissionConfig %{public}s", name);
|
||||
SandboxPermissionNode *node = CreateSandboxPermissionNode(name, 0, NULL);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1);
|
||||
// success, insert queue
|
||||
OH_ListAddWithOrder(&g_permissionQueue.front, &node->sandboxNode.node, PermissionNodeCompareProc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, AppSpawnSandbox *context)
|
||||
{
|
||||
cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, "permission");
|
||||
APPSPAWN_CHECK(configs != nullptr && cJSON_IsArray(configs), return 0, "No permission in json");
|
||||
|
||||
int ret = 0;
|
||||
uint32_t configSize = cJSON_GetArraySize(configs);
|
||||
for (uint32_t i = 0; i < configSize; i++) {
|
||||
cJSON *json = cJSON_GetArrayItem(configs, i);
|
||||
ret = ParsePermissionConfig(json);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int LoadPermissionConfig(void)
|
||||
{
|
||||
int ret = ParseSandboxConfig("etc/sandbox", "/appdata-sandbox.json", ParseAppSandboxConfig, nullptr);
|
||||
if (ret == APPSPAWN_SANDBOX_NONE) {
|
||||
APPSPAWN_LOGW("No sandbox config");
|
||||
ret = 0;
|
||||
}
|
||||
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
|
||||
g_maxPermissionIndex = PermissionRenumber(&g_permissionQueue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t GetPermissionIndex(const char *permission)
|
||||
{
|
||||
return GetPermissionIndexInQueue(&g_permissionQueue, permission);
|
||||
}
|
||||
|
||||
int32_t GetMaxPermissionIndex(void)
|
||||
{
|
||||
return g_maxPermissionIndex;
|
||||
}
|
||||
|
||||
const SandboxPermissionNode *GetPermissionNode(const char *permission)
|
||||
{
|
||||
return GetPermissionNodeInQueue(&g_permissionQueue, permission);
|
||||
}
|
||||
|
||||
const SandboxPermissionNode *GetPermissionNodeByIndex(int32_t index)
|
||||
{
|
||||
if (g_maxPermissionIndex <= index) {
|
||||
return nullptr;
|
||||
}
|
||||
return GetPermissionNodeInQueueByIndex(&g_permissionQueue, index);
|
||||
}
|
||||
|
||||
static void LoadPermission(void)
|
||||
{
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
if (g_maxPermissionIndex == -1) {
|
||||
OH_ListInit(&g_permissionQueue.front);
|
||||
g_permissionQueue.type = SANDBOX_TAG_PERMISSION_QUEUE;
|
||||
LoadPermissionConfig();
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
}
|
||||
|
||||
static void DeletePermissions(void)
|
||||
{
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
OH_ListRemoveAll(&g_permissionQueue.front, NULL);
|
||||
g_maxPermissionIndex = -1;
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
}
|
||||
|
||||
__attribute__((constructor)) static void LoadPermissionModule(void)
|
||||
{
|
||||
LoadPermission();
|
||||
}
|
||||
|
||||
__attribute__((destructor)) static void DeletePermissionModule(void)
|
||||
{
|
||||
DeletePermissions();
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "appspawn_mount_permission.h"
|
||||
#include "appspawn_msg.h"
|
||||
#include "appspawn_permission.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "cJSON.h"
|
||||
#include "securec.h"
|
||||
|
||||
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int32_t g_maxPermissionIndex = -1;
|
||||
static SandboxQueue g_permissionQueue = {0};
|
||||
|
||||
static int ParsePermissionConfig(const cJSON *permissionConfigs)
|
||||
{
|
||||
cJSON *config = NULL;
|
||||
cJSON_ArrayForEach(config, permissionConfigs)
|
||||
{
|
||||
const char *name = config->string;
|
||||
APPSPAWN_LOGV("ParsePermissionConfig %{public}s", name);
|
||||
int ret = AddSandboxPermissionNode(name, &g_permissionQueue);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, ParseJsonContext *context)
|
||||
{
|
||||
cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, "permission");
|
||||
APPSPAWN_CHECK(configs != NULL && cJSON_IsArray(configs), return 0, "No permission in json");
|
||||
|
||||
int ret = 0;
|
||||
uint32_t configSize = cJSON_GetArraySize(configs);
|
||||
for (uint32_t i = 0; i < configSize; i++) {
|
||||
cJSON *json = cJSON_GetArrayItem(configs, i);
|
||||
ret = ParsePermissionConfig(json);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int LoadPermissionConfig(void)
|
||||
{
|
||||
int ret = ParseJsonConfig("etc/sandbox", APP_SANDBOX_FILE_NAME, ParseAppSandboxConfig, NULL);
|
||||
if (ret == APPSPAWN_SANDBOX_NONE) {
|
||||
APPSPAWN_LOGW("No sandbox config");
|
||||
ret = 0;
|
||||
}
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Load sandbox fail");
|
||||
g_maxPermissionIndex = PermissionRenumber(&g_permissionQueue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t GetPermissionIndex(const char *permission)
|
||||
{
|
||||
APPSPAWN_CHECK_ONLY_EXPER(permission != NULL && g_maxPermissionIndex > 0, return INVALID_PERMISSION_INDEX);
|
||||
return GetPermissionIndexInQueue(&g_permissionQueue, permission);
|
||||
}
|
||||
|
||||
int32_t GetMaxPermissionIndex(void)
|
||||
{
|
||||
return g_maxPermissionIndex;
|
||||
}
|
||||
|
||||
const char *GetPermissionByIndex(int32_t index)
|
||||
{
|
||||
if (g_maxPermissionIndex <= index) {
|
||||
return NULL;
|
||||
}
|
||||
const SandboxPermissionNode *node = GetPermissionNodeInQueueByIndex(&g_permissionQueue, index);
|
||||
return node == NULL ? NULL : node->name;
|
||||
}
|
||||
|
||||
static void LoadPermission(void)
|
||||
{
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
if (g_maxPermissionIndex == -1) {
|
||||
OH_ListInit(&g_permissionQueue.front);
|
||||
LoadPermissionConfig();
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
}
|
||||
|
||||
static void DeletePermissions(void)
|
||||
{
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
OH_ListRemoveAll(&g_permissionQueue.front, NULL);
|
||||
g_maxPermissionIndex = -1;
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
}
|
||||
|
||||
__attribute__((constructor)) static void LoadPermissionModule(void)
|
||||
{
|
||||
LoadPermission();
|
||||
}
|
||||
|
||||
__attribute__((destructor)) static void DeletePermissionModule(void)
|
||||
{
|
||||
DeletePermissions();
|
||||
}
|
@ -13,22 +13,38 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APPSPAWN_MOUNT_PERMISSION_H
|
||||
#define APPSPAWN_MOUNT_PERMISSION_H
|
||||
#ifndef APPSPAWN_CLIENT_MOUNT_PERMISSION_H
|
||||
#define APPSPAWN_CLIENT_MOUNT_PERMISSION_H
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
typedef struct TagPermissionNode PermissionNode;
|
||||
int32_t GetPermissionIndex(const char *permission);
|
||||
int32_t GetMaxPermissionIndex(void);
|
||||
const PermissionNode *GetPermissionNode(const char *permission);
|
||||
const PermissionNode *GetPermissionNodeByIndex(int32_t index);
|
||||
|
||||
typedef struct TagSandboxSection {
|
||||
struct ListNode front;
|
||||
uint32_t type;
|
||||
} SandboxQueue;
|
||||
|
||||
typedef struct TagParseJsonContext {
|
||||
uint32_t type;
|
||||
} ParseJsonContext;
|
||||
|
||||
typedef struct {
|
||||
struct ListNode node;
|
||||
} SandboxMountNode;
|
||||
|
||||
typedef struct TagPermissionNode {
|
||||
SandboxMountNode sandboxNode;
|
||||
uint32_t permissionIndex;
|
||||
char name[0];
|
||||
} SandboxPermissionNode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // APPSPAWN_MOUNT_PERMISSION_H
|
||||
#endif // APPSPAWN_CLIENT_MOUNT_PERMISSION_H
|
||||
|
@ -80,14 +80,14 @@ static int SetCapability(unsigned int capsCnt, const unsigned int *caps)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client,
|
||||
static int SetProcessName(struct AppSpawnContent *content, AppSpawnClient *client,
|
||||
char *longProcName, uint32_t longProcNameLen)
|
||||
{
|
||||
AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client;
|
||||
return prctl(PR_SET_NAME, appProperty->message.bundleName);
|
||||
}
|
||||
|
||||
static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int SetKeepCapabilities(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
APPSPAWN_LOGE("SetKeepCapabilities");
|
||||
#ifdef __LINUX__
|
||||
@ -99,7 +99,7 @@ static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int SetUidGid(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client;
|
||||
APPSPAWN_LOGE("SetUidGid %d %d", appProperty->message.uID, appProperty->message.gID);
|
||||
@ -128,7 +128,7 @@ static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int SetCapabilities(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client;
|
||||
APPSPAWN_LOGE("SetCapabilities appProperty->message.capsCnt %d", appProperty->message.capsCnt);
|
||||
|
90
modules/sandbox/appspawn_permission.c
Executable file
90
modules/sandbox/appspawn_permission.c
Executable file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "appspawn_permission.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "appspawn_msg.h"
|
||||
#include "securec.h"
|
||||
#include "interfaces/innerkits_new/permission/appspawn_mount_permission.h"
|
||||
|
||||
static int PermissionNodeCompareIndex(ListNode *node, void *data)
|
||||
{
|
||||
SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
|
||||
return permissionNode->permissionIndex - *(int32_t *)data;
|
||||
}
|
||||
|
||||
static int PermissionNodeCompareName(ListNode *node, void *data)
|
||||
{
|
||||
SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
|
||||
return strcmp(permissionNode->name, (char *)data);
|
||||
}
|
||||
|
||||
static int PermissionNodeCompareProc(ListNode *node, ListNode *newNode)
|
||||
{
|
||||
SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
|
||||
SandboxPermissionNode *newPermissionNode = (SandboxPermissionNode *)ListEntry(newNode, SandboxMountNode, node);
|
||||
return strcmp(permissionNode->name, newPermissionNode->name);
|
||||
}
|
||||
|
||||
int AddSandboxPermissionNode(const char *name, SandboxQueue *queue)
|
||||
{
|
||||
size_t len = APPSPAWN_ALIGN(strlen(name) + 1) + sizeof(SandboxPermissionNode);
|
||||
SandboxPermissionNode *node = (SandboxPermissionNode *)calloc(1, len);
|
||||
APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create permission node");
|
||||
OH_ListInit(&node->sandboxNode.node);
|
||||
node->permissionIndex = 0;
|
||||
int ret = strcpy_s(node->name, len, name);
|
||||
APPSPAWN_CHECK(ret == 0, free(node);
|
||||
return APPSPAWN_SYSTEM_ERROR, "Failed to copy name");
|
||||
OH_ListAddWithOrder(&queue->front, &node->sandboxNode.node, PermissionNodeCompareProc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t PermissionRenumber(SandboxQueue *queue)
|
||||
{
|
||||
ListNode *node = queue->front.next;
|
||||
int index = -1;
|
||||
while (node != &queue->front) {
|
||||
SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
|
||||
permissionNode->permissionIndex = ++index;
|
||||
APPSPAWN_LOGV("Permission index %{public}d name %{public}s",
|
||||
permissionNode->permissionIndex, permissionNode->name);
|
||||
node = node->next;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
const SandboxPermissionNode *GetPermissionNodeInQueue(SandboxQueue *queue, const char *permission)
|
||||
{
|
||||
if (queue == NULL || permission == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ListNode *node = OH_ListFind(&queue->front, (void *)permission, PermissionNodeCompareName);
|
||||
return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
|
||||
}
|
||||
|
||||
const SandboxPermissionNode *GetPermissionNodeInQueueByIndex(SandboxQueue *queue, int32_t index)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ListNode *node = OH_ListFind(&queue->front, (void *)&index, PermissionNodeCompareIndex);
|
||||
return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node);
|
||||
}
|
||||
|
||||
int32_t GetPermissionIndexInQueue(SandboxQueue *queue, const char *permission)
|
||||
{
|
||||
const SandboxPermissionNode *permissionNode = GetPermissionNodeInQueue(queue, permission);
|
||||
return permissionNode == NULL ? INVALID_PERMISSION_INDEX : permissionNode->permissionIndex;
|
||||
}
|
42
modules/sandbox/appspawn_permission.h
Executable file
42
modules/sandbox/appspawn_permission.h
Executable file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APPSPAWN_SANDBOX_PERMISSION_H
|
||||
#define APPSPAWN_SANDBOX_PERMISSION_H
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define APP_SANDBOX_FILE_NAME "/appdata-sandbox.json"
|
||||
typedef struct TagSandboxSection SandboxQueue;
|
||||
typedef struct TagPermissionNode SandboxPermissionNode;
|
||||
|
||||
int32_t AddSandboxPermissionNode(const char *name, SandboxQueue *queue);
|
||||
int32_t GetPermissionIndexInQueue(SandboxQueue *queue, const char *permission);
|
||||
const SandboxPermissionNode *GetPermissionNodeInQueue(SandboxQueue *queue, const char *permission);
|
||||
const SandboxPermissionNode *GetPermissionNodeInQueueByIndex(SandboxQueue *queue, int32_t index);
|
||||
const SandboxPermissionNode *GetPermissionNode(const char *permission);
|
||||
int32_t PermissionRenumber(SandboxQueue *queue);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // APPSPAWN_SANDBOX_PERMISSION_H
|
@ -29,9 +29,9 @@ if (!defined(ohos_lite)) {
|
||||
]
|
||||
configs = []
|
||||
cflags = []
|
||||
deps = [ "//third_party/cJSON:cjson" ]
|
||||
external_deps = [
|
||||
"bounds_checking_function:libsec_shared",
|
||||
"cJSON:cjson",
|
||||
"hilog:libhilog",
|
||||
"zlib:shared_libz",
|
||||
]
|
||||
@ -54,9 +54,10 @@ if (!defined(ohos_lite)) {
|
||||
]
|
||||
configs = []
|
||||
cflags = []
|
||||
deps = [ "//third_party/cJSON:cjson" ]
|
||||
|
||||
external_deps = [
|
||||
"bounds_checking_function:libsec_shared",
|
||||
"cJSON:cjson",
|
||||
"hilog:libhilog",
|
||||
"zlib:shared_libz",
|
||||
]
|
||||
|
409
standard/appspawn_msgmgr.c
Executable file
409
standard/appspawn_msgmgr.c
Executable file
@ -0,0 +1,409 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "interfaces/innerkits/include/appspawn_msg.h"
|
||||
#include "interfaces/innerkits_new/include/appspawn.h"
|
||||
#include "interfaces/innerkits_new/module_engine/include/appspawn_msg.h"
|
||||
#include "appspawn_service.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define INVALID_OFFSET 0xffffffff
|
||||
|
||||
void *GetAppSpawnMsgInfo(const AppSpawnMsgNode *message, int type)
|
||||
{
|
||||
APPSPAWN_CHECK(type < TLV_MAX, return NULL, "Invalid tlv type %{public}u", type);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL, return NULL);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset[type] != INVALID_OFFSET, return NULL);
|
||||
return (void *)(message->buffer + message->tlvOffset[type] + sizeof(AppSpawnTlv));
|
||||
}
|
||||
|
||||
void *GetAppSpawnMsgExtInfo(const AppSpawnMsgNode *message, const char *name, uint32_t *len)
|
||||
{
|
||||
APPSPAWN_CHECK(name != NULL, return NULL, "Invalid name ");
|
||||
APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL, return NULL);
|
||||
|
||||
APPSPAWN_LOGV("GetAppSpawnMsgExtInfo tlvCount %{public}d name %{public}s", message->tlvCount, name);
|
||||
for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) {
|
||||
if (message->tlvOffset[index] == INVALID_OFFSET) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *data = message->buffer + message->tlvOffset[index];
|
||||
if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) {
|
||||
continue;
|
||||
}
|
||||
AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data;
|
||||
if (strcmp(tlv->tlvName, name) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (len != NULL) {
|
||||
*len = tlv->dataLen;
|
||||
}
|
||||
return data + sizeof(AppSpawnTlvExt);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CheckAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index)
|
||||
{
|
||||
AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, type);
|
||||
APPSPAWN_CHECK(msgFlags != NULL,
|
||||
return 0, "No tlv %{public}u in msg %{public}s", type, message->msgHeader.processName);
|
||||
uint32_t blockIndex = index / 32; // 32 max bit in int
|
||||
uint32_t bitIndex = index % 32; // 32 max bit in int
|
||||
APPSPAWN_CHECK(blockIndex < msgFlags->count, return 0,
|
||||
"Invalid index %{public}d max: %{public}d", index, msgFlags->count);
|
||||
return CHECK_FLAGS_BY_INDEX(msgFlags->flags[blockIndex], bitIndex);
|
||||
}
|
||||
|
||||
static AppSpawnMsgNode *CreateAppSpawnMsg(void)
|
||||
{
|
||||
AppSpawnMsgNode *message = (AppSpawnMsgNode *)calloc(1, sizeof(AppSpawnMsgNode));
|
||||
APPSPAWN_CHECK(message != NULL, return NULL, "Failed to create message");
|
||||
message->buffer = NULL;
|
||||
message->tlvOffset = NULL;
|
||||
(void)memset_s(&message->msgHeader, sizeof(message->msgHeader), 0, sizeof(message->msgHeader));
|
||||
return message;
|
||||
}
|
||||
|
||||
void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode)
|
||||
{
|
||||
if (msgNode == NULL) {
|
||||
return;
|
||||
}
|
||||
if (msgNode->buffer) {
|
||||
free(msgNode->buffer);
|
||||
msgNode->buffer = NULL;
|
||||
}
|
||||
if (msgNode->tlvOffset) {
|
||||
free(msgNode->tlvOffset);
|
||||
msgNode->tlvOffset = NULL;
|
||||
}
|
||||
free(msgNode);
|
||||
}
|
||||
|
||||
static inline int CheckRecvMsg(const AppSpawnMsg *msg)
|
||||
{
|
||||
APPSPAWN_CHECK(msg != NULL, return -1, "Invalid msg");
|
||||
APPSPAWN_CHECK(msg->magic == APPSPAWN_MSG_MAGIC, return -1, "Invalid magic 0x%{public}x", msg->magic);
|
||||
APPSPAWN_CHECK(msg->msgLen < MAX_MSG_TOTAL_LENGTH, return -1, "Message too long %{public}u", msg->msgLen);
|
||||
APPSPAWN_CHECK(msg->msgLen >= sizeof(AppSpawnMsg), return -1, "Message too long %{public}u", msg->msgLen);
|
||||
APPSPAWN_CHECK(msg->tlvCount < MAX_TLV_COUNT, return -1, "Message too long %{public}u", msg->tlvCount);
|
||||
APPSPAWN_CHECK(msg->tlvCount < (msg->msgLen / sizeof(AppSpawnTlv)),
|
||||
return -1, "Message too long %{public}u", msg->tlvCount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AppSpawnMsgRebuild(AppSpawnMsgNode *message, const AppSpawnMsg *msg)
|
||||
{
|
||||
APPSPAWN_CHECK_ONLY_EXPER(CheckRecvMsg(&message->msgHeader) == 0, return APPSPAWN_MSG_INVALID);
|
||||
if (msg->msgLen == sizeof(message->msgHeader)) { // only has msg header
|
||||
return 0;
|
||||
}
|
||||
if (message->buffer == NULL) {
|
||||
message->buffer = calloc(1, msg->msgLen - sizeof(message->msgHeader));
|
||||
APPSPAWN_CHECK(message->buffer != NULL, return -1, "Failed to alloc memory for recv message");
|
||||
}
|
||||
if (message->tlvOffset == NULL) {
|
||||
uint32_t totalCount = msg->tlvCount + TLV_MAX;
|
||||
message->tlvOffset = malloc(totalCount * sizeof(uint32_t));
|
||||
APPSPAWN_CHECK(message->tlvOffset != NULL, return -1, "Failed to alloc memory for recv message");
|
||||
for (uint32_t i = 0; i < totalCount; i++) {
|
||||
message->tlvOffset[i] = INVALID_OFFSET;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CheckAppSpawnMsg(const AppSpawnMsgNode *message)
|
||||
{
|
||||
APPSPAWN_CHECK(strlen(message->msgHeader.processName) > 0,
|
||||
return APPSPAWN_MSG_INVALID, "Invalid property processName %{public}s", message->msgHeader.processName);
|
||||
APPSPAWN_CHECK(message->tlvOffset != NULL,
|
||||
return APPSPAWN_MSG_INVALID, "Invalid property tlv offset for %{public}s", message->msgHeader.processName);
|
||||
APPSPAWN_CHECK(message->buffer != NULL,
|
||||
return APPSPAWN_MSG_INVALID, "Invalid property buffer for %{public}s", message->msgHeader.processName);
|
||||
|
||||
if (message->tlvOffset[TLV_BUNDLE_INFO] == INVALID_OFFSET ||
|
||||
message->tlvOffset[TLV_MSG_FLAGS] == INVALID_OFFSET ||
|
||||
message->tlvOffset[TLV_ACCESS_TOKEN_INFO] == INVALID_OFFSET ||
|
||||
message->tlvOffset[TLV_DAC_INFO] == INVALID_OFFSET) {
|
||||
APPSPAWN_LOGE("No must tlv: %{public}u %{public}u %{public}u", message->tlvOffset[TLV_BUNDLE_INFO],
|
||||
message->tlvOffset[TLV_MSG_FLAGS], message->tlvOffset[TLV_DAC_INFO]);
|
||||
return APPSPAWN_MSG_INVALID;
|
||||
}
|
||||
AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(message, TLV_BUNDLE_INFO);
|
||||
if (bundleInfo != NULL) {
|
||||
if (strstr(bundleInfo->bundleName, "\\") != NULL || strstr(bundleInfo->bundleName, "/") != NULL) {
|
||||
APPSPAWN_LOGE("Invalid bundle name %{public}s", bundleInfo->bundleName);
|
||||
return APPSPAWN_MSG_INVALID;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CheckExtTlvInfo(const AppSpawnTlv *tlv, uint32_t remainLen)
|
||||
{
|
||||
AppSpawnTlvExt *tlvExt = (AppSpawnTlvExt *)(tlv);
|
||||
APPSPAWN_LOGV("Recv type [%{public}s %{public}u] real len: %{public}u",
|
||||
tlvExt->tlvName, tlvExt->tlvLen, tlvExt->dataLen);
|
||||
if (tlvExt->dataLen > tlvExt->tlvLen - sizeof(AppSpawnTlvExt)) {
|
||||
APPSPAWN_LOGE("Invalid tlv [%{public}s %{public}u] real len: %{public}u %{public}u",
|
||||
tlvExt->tlvName, tlvExt->tlvLen, tlvExt->dataLen, sizeof(AppSpawnTlvExt));
|
||||
return APPSPAWN_MSG_INVALID;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CheckMsgTlv(const AppSpawnTlv *tlv, uint32_t remainLen)
|
||||
{
|
||||
uint32_t tlvLen = 0;
|
||||
switch (tlv->tlvType) {
|
||||
case TLV_MSG_FLAGS:
|
||||
tlvLen = ((AppSpawnMsgFlags *)(tlv + 1))->count * sizeof(uint32_t);
|
||||
break;
|
||||
case TLV_ACCESS_TOKEN_INFO:
|
||||
tlvLen = sizeof(AppSpawnMsgAccessToken);
|
||||
break;
|
||||
case TLV_DAC_INFO:
|
||||
tlvLen = sizeof(AppSpawnMsgDacInfo);
|
||||
break;
|
||||
case TLV_BUNDLE_INFO:
|
||||
APPSPAWN_CHECK((tlv->tlvLen - sizeof(AppSpawnTlv)) <= (sizeof(AppSpawnMsgBundleInfo) + APP_LEN_BUNDLE_NAME),
|
||||
return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen);
|
||||
break;
|
||||
case TLV_OWNER_INFO:
|
||||
APPSPAWN_CHECK((tlv->tlvLen - sizeof(AppSpawnTlv)) <= APP_OWNER_ID_LEN,
|
||||
return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen);
|
||||
break;
|
||||
case TLV_DOMAIN_INFO:
|
||||
APPSPAWN_CHECK((tlv->tlvLen - sizeof(AppSpawnTlv)) <= (APP_APL_MAX_LEN + sizeof(AppSpawnMsgDomainInfo)),
|
||||
return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen);
|
||||
break;
|
||||
case TLV_MAX:
|
||||
return CheckExtTlvInfo(tlv, remainLen);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
APPSPAWN_CHECK(tlvLen <= tlv->tlvLen,
|
||||
return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DecodeAppSpawnMsg(AppSpawnMsgNode *message)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t tlvCount = 0;
|
||||
uint32_t bufferLen = message->msgHeader.msgLen - sizeof(AppSpawnMsg);
|
||||
uint32_t currLen = 0;
|
||||
while (currLen < bufferLen) {
|
||||
AppSpawnTlv *tlv = (AppSpawnTlv *)(message->buffer + currLen);
|
||||
APPSPAWN_CHECK(tlv->tlvLen <= (bufferLen - currLen), break,
|
||||
"Invalid tlv [%{public}d %{public}d] curr: %{public}u",
|
||||
tlv->tlvType, tlv->tlvLen, currLen + sizeof(AppSpawnMsg));
|
||||
|
||||
APPSPAWN_LOGV("DecodeAppSpawnMsg tlv %{public}u %{public}u start: %{public}u ",
|
||||
tlv->tlvType, tlv->tlvLen, currLen + sizeof(AppSpawnMsg)); // show in msg offset
|
||||
ret = CheckMsgTlv(tlv, bufferLen - currLen);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
|
||||
|
||||
if (tlv->tlvType < TLV_MAX) { // normal
|
||||
message->tlvOffset[tlv->tlvType] = currLen;
|
||||
currLen += tlv->tlvLen;
|
||||
} else {
|
||||
APPSPAWN_CHECK(tlvCount < message->msgHeader.tlvCount, break,
|
||||
"Invalid tlv number tlv %{public}d tlvCount: %{public}d", tlv->tlvType, tlvCount);
|
||||
message->tlvOffset[TLV_MAX + tlvCount] = currLen;
|
||||
tlvCount++;
|
||||
currLen += tlv->tlvLen;
|
||||
}
|
||||
}
|
||||
APPSPAWN_CHECK_ONLY_EXPER(currLen >= bufferLen, return APPSPAWN_MSG_INVALID);
|
||||
// save real ext tlv count
|
||||
message->tlvCount = tlvCount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen,
|
||||
AppSpawnMsgNode **outMsg, uint32_t *msgRecvLen, uint32_t *reminder)
|
||||
{
|
||||
*reminder = 0;
|
||||
AppSpawnMsgNode *message = *outMsg;
|
||||
if (message == NULL) {
|
||||
message = CreateAppSpawnMsg();
|
||||
APPSPAWN_CHECK(message != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create message");
|
||||
*outMsg = message;
|
||||
}
|
||||
|
||||
uint32_t reminderLen = bufferLen;
|
||||
const uint8_t *reminderBuffer = buffer;
|
||||
if (*msgRecvLen < sizeof(AppSpawnMsg)) { // recv partial message
|
||||
if ((bufferLen + *msgRecvLen) >= sizeof(AppSpawnMsg)) {
|
||||
int ret = memcpy_s(((uint8_t *)&message->msgHeader) + *msgRecvLen,
|
||||
sizeof(message->msgHeader) - *msgRecvLen,
|
||||
buffer, sizeof(message->msgHeader) - *msgRecvLen);
|
||||
APPSPAWN_CHECK(ret == EOK, return -1, "Failed to copy recv buffer");
|
||||
|
||||
ret = AppSpawnMsgRebuild(message, &message->msgHeader);
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc buffer for receive msg");
|
||||
reminderLen = bufferLen - (sizeof(message->msgHeader) - *msgRecvLen);
|
||||
reminderBuffer = buffer + sizeof(message->msgHeader) - *msgRecvLen;
|
||||
*msgRecvLen = sizeof(message->msgHeader);
|
||||
} else {
|
||||
int ret = memcpy_s(((uint8_t *)&message->msgHeader) + *msgRecvLen,
|
||||
sizeof(message->msgHeader) - *msgRecvLen, buffer, bufferLen);
|
||||
APPSPAWN_CHECK(ret == EOK, return -1, "Failed to copy recv buffer");
|
||||
*msgRecvLen += bufferLen;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// do not copy msg header
|
||||
uint32_t realCopy = (reminderLen + *msgRecvLen) > message->msgHeader.msgLen ?
|
||||
message->msgHeader.msgLen - *msgRecvLen : reminderLen;
|
||||
if (message->buffer == NULL) { // only has msg header
|
||||
return 0;
|
||||
}
|
||||
APPSPAWN_LOGV("HandleRecvBuffer msgRecvLen: %{public}u reminderLen %{public}u realCopy %{public}u",
|
||||
*msgRecvLen, reminderLen, realCopy);
|
||||
int ret = memcpy_s(message->buffer + *msgRecvLen - sizeof(message->msgHeader),
|
||||
message->msgHeader.msgLen - *msgRecvLen, reminderBuffer, realCopy);
|
||||
APPSPAWN_CHECK(ret == EOK, return -1, "Failed to copy recv buffer");
|
||||
*msgRecvLen += realCopy;
|
||||
if (realCopy < reminderLen) {
|
||||
*reminder = reminderLen - realCopy;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_t GetPidFromTerminationMsg(AppSpawnMsgNode *message)
|
||||
{
|
||||
pid_t *pid = (pid_t *)GetAppSpawnMsgInfo(message, TLV_RENDER_TERMINATION_INFO);
|
||||
if (pid != NULL) {
|
||||
return *pid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ChangeAppSpawnMsgExt2Property(AppSpawnMsgNode *message, AppSpawnClientExt *appProperty)
|
||||
{
|
||||
static const char *extInfoNames[] = { "HspList", "Overlay", "DataGroup", "AppEnv"};
|
||||
static const char *extraNames[] = { "|HspList|", "|Overlay|", "|DataGroup|", "|AppEnv|"};
|
||||
char *data[sizeof(extInfoNames) / sizeof(extInfoNames[0])] = {};
|
||||
|
||||
AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppSpawnMsgInfo(message, TLV_DAC_INFO);
|
||||
if (dacInfo != NULL) {
|
||||
appProperty->property.uid = dacInfo->uid;
|
||||
appProperty->property.gid = dacInfo->gid;
|
||||
appProperty->property.gidCount = dacInfo->gidCount;
|
||||
for (uint32_t i = 0; i < dacInfo->gidCount; i++) {
|
||||
appProperty->property.gidTable[i] = dacInfo->gidTable[i];
|
||||
}
|
||||
}
|
||||
|
||||
ExtraInfo *extraInfo = &appProperty->property.extraInfo;
|
||||
uint32_t totalLength = 0;
|
||||
uint32_t currLen = 0;
|
||||
uint32_t nameCount = sizeof(extInfoNames) / sizeof(extInfoNames[0]);
|
||||
for (uint32_t i = 0; i < nameCount; i++) {
|
||||
currLen = 0;
|
||||
data[i] = (char *)GetAppSpawnMsgExtInfo(message, extInfoNames[i], &currLen);
|
||||
if (data[i]) {
|
||||
totalLength += currLen + strlen(extraNames[i]) * 2 + 1; // 2 format |type1|...|type1|type2|...|type2|
|
||||
}
|
||||
}
|
||||
if (totalLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extraInfo->data = (char *)calloc(1, totalLength);
|
||||
APPSPAWN_CHECK(extraInfo->data != NULL, return -1, "Failed to alloc mem for extra");
|
||||
currLen = 0;
|
||||
for (uint32_t i = 0; i < nameCount; i++) {
|
||||
if (data[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
int len = snprintf_s(extraInfo->data + currLen, totalLength - currLen, totalLength - currLen - 1,
|
||||
"%s%s%s", extraNames[i], data[i], extraNames[i]);
|
||||
if (len <= 0) {
|
||||
free(extraInfo->data);
|
||||
extraInfo->data = NULL;
|
||||
return 0;
|
||||
}
|
||||
currLen += len;
|
||||
}
|
||||
extraInfo->totalLength = currLen;
|
||||
extraInfo->savedLength = currLen;
|
||||
APPSPAWN_LOGV("extraInfo %{public}s", extraInfo->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ChangeAppSpawnMsg2Property(AppSpawnMsgNode *message, AppSpawnClientExt *appProperty)
|
||||
{
|
||||
APPSPAWN_CHECK_ONLY_EXPER(message != NULL && appProperty != NULL, return -1);
|
||||
int ret = 0;
|
||||
do {
|
||||
appProperty->property.code = (AppOperateType)message->msgHeader.msgType;
|
||||
ret = strcpy_s(appProperty->property.processName, APP_LEN_PROC_NAME, message->msgHeader.processName);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to copy processName");
|
||||
ret = DecodeAppSpawnMsg(message);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to decode message");
|
||||
AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, TLV_MSG_FLAGS);
|
||||
appProperty->property.flags = msgFlags ? *(uint32_t *)msgFlags->flags : 0;
|
||||
|
||||
msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, TLV_PERMISSION);
|
||||
appProperty->property.mountPermissionFlags = msgFlags ? *(uint32_t *)msgFlags->flags : 0;
|
||||
|
||||
AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(message, TLV_BUNDLE_INFO);
|
||||
if (bundleInfo != NULL) {
|
||||
ret = strcpy_s(appProperty->property.bundleName, APP_LEN_BUNDLE_NAME, bundleInfo->bundleName);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to copy bundle name");
|
||||
appProperty->property.bundleIndex = (int32_t)bundleInfo->bundleIndex;
|
||||
}
|
||||
AppSpawnMsgDomainInfo *domainInfo = (AppSpawnMsgDomainInfo *)GetAppSpawnMsgInfo(message, TLV_DOMAIN_INFO);
|
||||
if (domainInfo != NULL) {
|
||||
ret = strcpy_s(appProperty->property.apl, sizeof(appProperty->property.apl), domainInfo->apl);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to copy apl");
|
||||
appProperty->property.hapFlags = domainInfo->hapFlags;
|
||||
}
|
||||
AppSpawnMsgOwnerId *owner = (AppSpawnMsgOwnerId *)GetAppSpawnMsgInfo(message, TLV_OWNER_INFO);
|
||||
if (owner != NULL) {
|
||||
ret = strcpy_s(appProperty->property.ownerId, sizeof(appProperty->property.ownerId), owner->ownerId);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to copy ownerId");
|
||||
}
|
||||
AppSpawnMsgAccessToken *token = (AppSpawnMsgAccessToken *)GetAppSpawnMsgInfo(message, TLV_ACCESS_TOKEN_INFO);
|
||||
appProperty->property.accessTokenIdEx = token ? token->accessTokenIdEx : 0;
|
||||
|
||||
AppSpawnMsgInternetInfo *info = (AppSpawnMsgInternetInfo *)GetAppSpawnMsgInfo(message, TLV_INTERNET_INFO);
|
||||
if (info != NULL) {
|
||||
appProperty->property.allowInternet = info->allowInternet;
|
||||
appProperty->property.setAllowInternet = info->setAllowInternet;
|
||||
}
|
||||
char *renderCmd = (char *)GetAppSpawnMsgExtInfo(message, MSG_EXT_NAME_RENDER_CMD, NULL);
|
||||
if (renderCmd != NULL) {
|
||||
ret = strcpy_s(appProperty->property.renderCmd, sizeof(appProperty->property.renderCmd), renderCmd);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to copy renderCmd");
|
||||
}
|
||||
ret = ChangeAppSpawnMsgExt2Property(message, appProperty);
|
||||
} while (0);
|
||||
DeleteAppSpawnMsg(message);
|
||||
return ret;
|
||||
}
|
@ -50,7 +50,7 @@
|
||||
|
||||
// ide-asan
|
||||
#ifndef ASAN_DETECTOR
|
||||
static int SetAsanEnabledEnv(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int SetAsanEnabledEnv(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
|
||||
if (appProperty->code == SPAWN_NATIVE_PROCESS) {
|
||||
@ -82,7 +82,7 @@ static int SetAsanEnabledEnv(struct AppSpawnContent_ *content, AppSpawnClient *c
|
||||
}
|
||||
#endif
|
||||
|
||||
static void SetGwpAsanEnabled(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static void SetGwpAsanEnabled(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
|
||||
char debugValue[10] = {0};
|
||||
@ -98,7 +98,7 @@ static void SetGwpAsanEnabled(struct AppSpawnContent_ *content, AppSpawnClient *
|
||||
}
|
||||
}
|
||||
|
||||
static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client,
|
||||
static int SetProcessName(struct AppSpawnContent *content, AppSpawnClient *client,
|
||||
char *longProcName, uint32_t longProcNameLen)
|
||||
{
|
||||
AppSpawnClientExt *appPropertyExt = (AppSpawnClientExt *)client;
|
||||
@ -134,7 +134,7 @@ static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *clie
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int SetKeepCapabilities(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
|
||||
// set keep capabilities when user not root.
|
||||
@ -145,7 +145,7 @@ static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int SetCapabilities(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
// init cap
|
||||
struct __user_cap_header_struct cap_header;
|
||||
@ -186,7 +186,7 @@ static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *cli
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void InitDebugParams(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static void InitDebugParams(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifndef APPSPAWN_TEST
|
||||
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
|
||||
@ -230,7 +230,7 @@ static void ClearEnvironment(AppSpawnContent *content, AppSpawnClient *client)
|
||||
return;
|
||||
}
|
||||
|
||||
int SetXpmConfig(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int SetXpmConfig(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef CODE_SIGNATURE_ENABLE
|
||||
// nwebspawn no permission set xpm config
|
||||
@ -256,7 +256,7 @@ int SetXpmConfig(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int SetUidGid(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef GRAPHIC_PERMISSION_CHECK
|
||||
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
|
||||
@ -298,7 +298,7 @@ static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int32_t SetFileDescriptors(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifndef APPSPAWN_TEST
|
||||
// close stdin stdout stderr
|
||||
@ -417,7 +417,7 @@ static void Free(char **argv, ExtraInfo *extraInfo)
|
||||
|
||||
#ifdef ASAN_DETECTOR
|
||||
#define WRAP_VALUE_MAX_LENGTH 96
|
||||
static int GetWrapBundleNameValue(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int GetWrapBundleNameValue(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
|
||||
char wrapBundleNameKey[WRAP_VALUE_MAX_LENGTH] = {0};
|
||||
@ -465,7 +465,7 @@ static int EncodeAppClient(AppSpawnClient *client, char *param, int32_t originLe
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static int ColdStartApp(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppParameter *appProperty = &((AppSpawnClientExt *)client)->property;
|
||||
APPSPAWN_LOGI("ColdStartApp::appName %{public}s", appProperty->processName);
|
||||
@ -489,12 +489,9 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client
|
||||
#endif
|
||||
ret = strcpy_s(argv[0], APP_LEN_PROC_NAME, appSpawnPath);
|
||||
APPSPAWN_CHECK(ret >= 0, break, "Invalid strcpy");
|
||||
ret = -1;
|
||||
if (content->isNweb) {
|
||||
argv[START_INDEX] = strdup(NWEBSPAWN_COLDSTART_KEY);
|
||||
} else {
|
||||
argv[START_INDEX] = strdup(APPSPAWN_COLDSTART_KEY);
|
||||
}
|
||||
(content->isNweb) ? (argv[START_INDEX] = strdup(NWEBSPAWN_COLDSTART_KEY)) :
|
||||
(argv[START_INDEX] = strdup(APPSPAWN_COLDSTART_KEY));
|
||||
|
||||
APPSPAWN_CHECK(argv[START_INDEX] != NULL, break, "Invalid strdup");
|
||||
argv[FD_INDEX] = strdup(buffer);
|
||||
APPSPAWN_CHECK(argv[FD_INDEX] != NULL, break, "Invalid strdup");
|
||||
@ -515,9 +512,7 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client
|
||||
#else
|
||||
ret = -1;
|
||||
#endif
|
||||
if (ret) {
|
||||
APPSPAWN_LOGE("Failed to execv, errno = %{public}d", errno);
|
||||
}
|
||||
APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to execv, errno = %{public}d", errno)
|
||||
}
|
||||
argv[0] = NULL;
|
||||
Free(argv, &appProperty->extraInfo);
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "appspawn_service.h"
|
||||
#include "appspawn_adapter.h"
|
||||
#include "appspawn_server.h"
|
||||
#include "appspawn_msg.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
@ -50,7 +49,6 @@
|
||||
#define USER_ID_SIZE 4
|
||||
|
||||
static AppSpawnContentExt *g_appSpawnContent = NULL;
|
||||
static const uint32_t EXTRAINFO_TOTAL_LENGTH_MAX = 32 * 1024;
|
||||
|
||||
static int AppInfoHashNodeCompare(const HashNode *node1, const HashNode *node2)
|
||||
{
|
||||
@ -140,6 +138,11 @@ static void OnClose(const TaskHandle taskHandle)
|
||||
APPSPAWN_CHECK(client != NULL, return, "Invalid client");
|
||||
APPSPAWN_LOGI("OnClose %{public}d processName = %{public}s",
|
||||
client->client.id, client->property.processName);
|
||||
if (client->receiverCtx.incompleteMsg) {
|
||||
DeleteAppSpawnMsg(client->receiverCtx.incompleteMsg);
|
||||
client->receiverCtx.incompleteMsg = NULL;
|
||||
client->receiverCtx.msgRecvLen = 0;
|
||||
}
|
||||
if (client->property.extraInfo.data != NULL) {
|
||||
free(client->property.extraInfo.data);
|
||||
client->property.extraInfo.totalLength = 0;
|
||||
@ -161,14 +164,15 @@ static void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle
|
||||
}
|
||||
}
|
||||
|
||||
static int SendResponse(AppSpawnClientExt *client, const char *buff, size_t buffSize)
|
||||
static int SendResponse(AppSpawnClientExt *client, int result, pid_t pid)
|
||||
{
|
||||
uint32_t bufferSize = buffSize;
|
||||
uint32_t bufferSize = sizeof(AppSpawnResponseMsg);
|
||||
BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize);
|
||||
char *buffer = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize);
|
||||
int ret = memcpy_s(buffer, bufferSize, buff, buffSize);
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
|
||||
return LE_Send(LE_GetDefaultLoop(), client->stream, handle, buffSize);
|
||||
AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize);
|
||||
APPSPAWN_CHECK(buffer != NULL, return -1, "Failed to get buffer");
|
||||
buffer->result.result = result;
|
||||
buffer->result.pid = pid;
|
||||
return LE_Send(LE_GetDefaultLoop(), client->stream, handle, bufferSize);
|
||||
}
|
||||
|
||||
#ifndef APPSPAWN_TEST
|
||||
@ -436,41 +440,6 @@ static void CheckColdAppEnabled(AppSpawnClientExt *appProperty)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ReceiveRequestDataToExtraInfo(const TaskHandle taskHandle, AppSpawnClientExt *client,
|
||||
const uint8_t *buffer, uint32_t buffLen)
|
||||
{
|
||||
if (client->property.extraInfo.totalLength) {
|
||||
ExtraInfo *extraInfo = &client->property.extraInfo;
|
||||
if (extraInfo->savedLength == 0) {
|
||||
extraInfo->data = (char *)malloc(extraInfo->totalLength);
|
||||
APPSPAWN_CHECK(extraInfo->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: malloc extraInfo failed %{public}u", extraInfo->totalLength);
|
||||
}
|
||||
|
||||
uint32_t saved = extraInfo->savedLength;
|
||||
uint32_t total = extraInfo->totalLength;
|
||||
char *data = extraInfo->data;
|
||||
|
||||
APPSPAWN_LOGI("Receiving extraInfo: (%{public}u saved + %{public}u incoming) / %{public}u total",
|
||||
saved, buffLen, total);
|
||||
|
||||
APPSPAWN_CHECK((total - saved) >= buffLen, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: too many data for extraInfo %{public}u ", buffLen);
|
||||
|
||||
int ret = memcpy_s(data + saved, buffLen, buffer, buffLen);
|
||||
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: memcpy extraInfo failed");
|
||||
|
||||
extraInfo->savedLength += buffLen;
|
||||
if (extraInfo->savedLength < extraInfo->totalLength) {
|
||||
return false;
|
||||
}
|
||||
extraInfo->data[extraInfo->totalLength - 1] = 0;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int CheckRequestMsgValid(AppSpawnClientExt *client)
|
||||
{
|
||||
if (client->property.extraInfo.totalLength >= EXTRAINFO_TOTAL_LENGTH_MAX) {
|
||||
@ -487,44 +456,6 @@ static int CheckRequestMsgValid(AppSpawnClientExt *client)
|
||||
return -1;
|
||||
}
|
||||
|
||||
APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *client,
|
||||
const uint8_t *buffer, uint32_t buffLen)
|
||||
{
|
||||
APPSPAWN_CHECK(buffer != NULL && buffLen > 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: Invalid buff, bufferLen:%{public}d", buffLen);
|
||||
|
||||
// 1. receive AppParamter
|
||||
if (client->property.extraInfo.totalLength == 0) {
|
||||
APPSPAWN_CHECK(buffLen >= sizeof(client->property), LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: Invalid buffLen %{public}u", buffLen);
|
||||
|
||||
int ret = memcpy_s(&client->property, sizeof(client->property), buffer, sizeof(client->property));
|
||||
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: memcpy failed %{public}d:%{public}u", ret, buffLen);
|
||||
|
||||
// reset extraInfo
|
||||
client->property.extraInfo.savedLength = 0;
|
||||
client->property.extraInfo.data = NULL;
|
||||
|
||||
// update buffer
|
||||
buffer += sizeof(client->property);
|
||||
buffLen -= sizeof(client->property);
|
||||
ret = CheckRequestMsgValid(client);
|
||||
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "Invalid request msg");
|
||||
}
|
||||
|
||||
// 2. check whether extraInfo exist
|
||||
if (client->property.extraInfo.totalLength == 0) { // no extraInfo
|
||||
APPSPAWN_LOGV("ReceiveRequestData: no extraInfo");
|
||||
return true;
|
||||
} else if (buffLen == 0) {
|
||||
APPSPAWN_LOGV("ReceiveRequestData: waiting for extraInfo");
|
||||
return false;
|
||||
}
|
||||
return ReceiveRequestDataToExtraInfo(taskHandle, client, buffer, buffLen);
|
||||
}
|
||||
|
||||
static int HandleMessage(AppSpawnClientExt *appProperty)
|
||||
{
|
||||
// create pipe
|
||||
@ -558,35 +489,29 @@ static int HandleMessage(AppSpawnClientExt *appProperty)
|
||||
info->uid = appProperty->property.uid;
|
||||
ProcessAppAdd(g_appSpawnContent, info);
|
||||
}
|
||||
SendResponse(appProperty, (char *)&appProperty->pid, sizeof(appProperty->pid));
|
||||
SendResponse(appProperty, 0, appProperty->pid);
|
||||
} else {
|
||||
SendResponse(appProperty, (char *)&result, sizeof(result));
|
||||
SendResponse(appProperty, result, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
|
||||
static int ProcessRecvMsg(const TaskHandle taskHandle, AppSpawnClientExt *appProperty)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle);
|
||||
APPSPAWN_CHECK(appProperty != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return, "alloc client Failed");
|
||||
|
||||
if (!ReceiveRequestData(taskHandle, appProperty, buffer, buffLen)) {
|
||||
return;
|
||||
if (CheckRequestMsgValid(appProperty)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_appSpawnContent->content.isNweb) {
|
||||
// get render process termination status, only nwebspawn need this logic.
|
||||
if (appProperty->property.code == GET_RENDER_TERMINATION_STATUS) {
|
||||
int ret = GetProcessTerminationStatus(&appProperty->client);
|
||||
RemoveAppInfo(appProperty->property.pid);
|
||||
SendResponse(appProperty, (char *)&ret, sizeof(ret));
|
||||
return;
|
||||
SendResponse(appProperty, ret, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
APPSPAWN_CHECK(appProperty->property.gidCount <= APP_MAX_GIDS && strlen(appProperty->property.processName) > 0,
|
||||
LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return, "Invalid property %{public}u", appProperty->property.gidCount);
|
||||
return -1, "Invalid property %{public}u", appProperty->property.gidCount);
|
||||
|
||||
// special handle bundle name medialibrary and scanner
|
||||
HandleSpecial(appProperty);
|
||||
@ -596,9 +521,48 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer,
|
||||
}
|
||||
appProperty->pid = 0;
|
||||
CheckColdAppEnabled(appProperty);
|
||||
int ret = HandleMessage(appProperty);
|
||||
if (ret != 0) {
|
||||
LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return HandleMessage(appProperty);
|
||||
}
|
||||
|
||||
static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle);
|
||||
APPSPAWN_CHECK(appProperty != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return, "alloc client Failed");
|
||||
APPSPAWN_CHECK(buffLen < MAX_MSG_TOTAL_LENGTH, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return, "Message too long %{public}u", buffLen);
|
||||
|
||||
uint32_t reminder = 0;
|
||||
uint32_t currLen = 0;
|
||||
AppSpawnMsgNode *message = appProperty->receiverCtx.incompleteMsg; // incomplete msg
|
||||
appProperty->receiverCtx.incompleteMsg = NULL;
|
||||
int ret = 0;
|
||||
do {
|
||||
ret = GetAppSpawnMsgFromBuffer(buffer + currLen, buffLen - currLen,
|
||||
&message, &appProperty->receiverCtx.msgRecvLen, &reminder);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break);
|
||||
|
||||
if (appProperty->receiverCtx.msgRecvLen != message->msgHeader.msgLen) { // recv complete msg
|
||||
appProperty->receiverCtx.incompleteMsg = message;
|
||||
message = NULL;
|
||||
break;
|
||||
}
|
||||
appProperty->receiverCtx.msgRecvLen = 0;
|
||||
// change msg to app property and free message
|
||||
ret = ChangeAppSpawnMsg2Property(message, appProperty);
|
||||
message = NULL;
|
||||
if (ret == 0) {
|
||||
ret = ProcessRecvMsg(taskHandle, appProperty);
|
||||
}
|
||||
if (ret != 0) {
|
||||
LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
break;
|
||||
}
|
||||
currLen += buffLen - reminder;
|
||||
} while (reminder > 0);
|
||||
|
||||
if (message) {
|
||||
DeleteAppSpawnMsg(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,6 +598,8 @@ APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskH
|
||||
client->property.extraInfo.totalLength = 0;
|
||||
client->property.extraInfo.savedLength = 0;
|
||||
client->property.extraInfo.data = NULL;
|
||||
client->receiverCtx.msgRecvLen = 0;
|
||||
client->receiverCtx.incompleteMsg = NULL;
|
||||
APPSPAWN_LOGI("OnConnection client fd %{public}d Id %{public}d", LE_GetSocketFd(stream), client->client.id);
|
||||
return stream;
|
||||
}
|
||||
@ -645,7 +611,7 @@ static int OnConnection(const LoopHandle loopHandle, const TaskHandle server)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result)
|
||||
static void NotifyResToParent(struct AppSpawnContent *content, AppSpawnClient *client, int result)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
|
||||
int fd = appProperty->fd[1];
|
||||
|
@ -18,7 +18,9 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include "appspawn_msg.h"
|
||||
#include "interfaces/innerkits/include/appspawn_msg.h"
|
||||
#include "interfaces/innerkits_new/include/appspawn.h"
|
||||
#include "interfaces/innerkits_new/module_engine/include/appspawn_msg.h"
|
||||
#include "appspawn_server.h"
|
||||
#include "init_hashmap.h"
|
||||
#include "loop_event.h"
|
||||
@ -47,15 +49,30 @@ extern bool may_init_gwp_asan(bool forceInit);
|
||||
#define EXTRA_INFO_INDEX 5
|
||||
#define NULL_INDEX 6
|
||||
#define PARAM_BUFFER_LEN 128
|
||||
|
||||
typedef struct TagAppSpawnMsgNode {
|
||||
AppSpawnMsg msgHeader;
|
||||
uint32_t tlvCount;
|
||||
uint32_t *tlvOffset;
|
||||
uint8_t *buffer;
|
||||
} AppSpawnMsgNode;
|
||||
|
||||
typedef struct TagAppSpawnMsgReceiverCtx {
|
||||
uint32_t nextMsgId;
|
||||
uint32_t msgRecvLen;
|
||||
AppSpawnMsgNode *incompleteMsg;
|
||||
} AppSpawnMsgReceiverCtx;
|
||||
|
||||
typedef struct {
|
||||
AppSpawnClient client;
|
||||
TaskHandle stream;
|
||||
int32_t fd[2]; // 2 fd count
|
||||
AppSpawnMsgReceiverCtx receiverCtx;
|
||||
AppParameter property;
|
||||
pid_t pid;
|
||||
} AppSpawnClientExt;
|
||||
|
||||
typedef struct AppInfo_ {
|
||||
typedef struct AppInfo {
|
||||
HashNode node;
|
||||
pid_t pid;
|
||||
AppOperateType code;
|
||||
@ -63,7 +80,7 @@ typedef struct AppInfo_ {
|
||||
char name[0];
|
||||
} AppInfo, AppSpawnAppInfo;
|
||||
|
||||
typedef struct AppSpawnContentExt_ {
|
||||
typedef struct AppSpawnContentExt {
|
||||
AppSpawnContent content;
|
||||
uint32_t flags;
|
||||
TaskHandle server;
|
||||
@ -95,6 +112,11 @@ do { \
|
||||
(clientExt)->property.setAllowInternet, (clientExt)->property.allowInternet); \
|
||||
} while (0)
|
||||
|
||||
int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen,
|
||||
AppSpawnMsgNode **outMsg, uint32_t *msgRecvLen, uint32_t *reminder);
|
||||
int ChangeAppSpawnMsg2Property(AppSpawnMsgNode *message, AppSpawnClientExt *appProperty);
|
||||
void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include "appspawn_adapter.h"
|
||||
#include "appspawn_msg.h"
|
||||
#include "appspawn_server.h"
|
||||
#include "appspawn_service.h"
|
||||
#include "securec.h"
|
||||
|
@ -24,7 +24,10 @@ group("moduletest") {
|
||||
group("unittest") {
|
||||
if (!defined(ohos_lite)) {
|
||||
testonly = true
|
||||
deps = [ "unittest:AppSpawn_ut" ]
|
||||
deps = [
|
||||
"unittest:AppSpawn_ut",
|
||||
"unittest/app_spawn_client_test:AppSpawn_client_ut",
|
||||
]
|
||||
deps += [ "unittest/hnp_test:HnpTest" ]
|
||||
} else {
|
||||
testonly = true
|
||||
|
@ -15,18 +15,45 @@ import("//base/startup/appspawn/appspawn.gni")
|
||||
import("//build/test.gni")
|
||||
|
||||
ohos_executable("AppSpawnTest") {
|
||||
sources = [ "${appspawn_path}/test/moduletest/appspawn_test_cmd.cpp" ]
|
||||
sources = [
|
||||
"${appspawn_path}/test/moduletest/appspawn_test_cmder.cpp",
|
||||
"${appspawn_path}/test/moduletest/appspawn_test_main.cpp",
|
||||
"${appspawn_path}/util/src/appspawn_utils.c",
|
||||
]
|
||||
|
||||
configs = [ "${appspawn_path}:appspawn_config" ]
|
||||
include_dirs = [
|
||||
"${appspawn_path}",
|
||||
"${appspawn_path}/common",
|
||||
"${appspawn_path}/standard",
|
||||
"${appspawn_path}/modules/modulemgr",
|
||||
"${appspawn_path}/modules/ace_adapter",
|
||||
"${appspawn_path}/modules/common",
|
||||
"${appspawn_path}/modules/sandbox",
|
||||
"${appspawn_path}/test/moduletest/threadpool",
|
||||
"${appspawn_innerkits_path}/include",
|
||||
"${appspawn_innerkits_path}/client",
|
||||
"${appspawn_innerkits_path}/permission",
|
||||
"${appspawn_innerkits_path}/module_engine/include",
|
||||
"${appspawn_path}/test/mock",
|
||||
"${appspawn_path}/test/unittest",
|
||||
"${appspawn_path}/util/include",
|
||||
]
|
||||
|
||||
deps = [ "${appspawn_path}/interfaces/innerkits:appspawn_socket_client" ]
|
||||
deps = [
|
||||
"${appspawn_innerkits_path}/client:appspawn_client",
|
||||
"${appspawn_path}/test/moduletest/threadpool:libappspawn_threadpool",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"cJSON:cjson",
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"hilog:libhilog",
|
||||
"init:libbegetutil",
|
||||
"zlib:libz",
|
||||
]
|
||||
subsystem_name = "${subsystem_name}"
|
||||
part_name = "${part_name}"
|
||||
}
|
||||
|
||||
ohos_moduletest("AppSpawnModuleTest") {
|
||||
@ -35,39 +62,49 @@ ohos_moduletest("AppSpawnModuleTest") {
|
||||
sources = [
|
||||
"${appspawn_path}/test/moduletest/appspawn_client_test.cpp",
|
||||
"${appspawn_path}/test/moduletest/appspawn_module_test.cpp",
|
||||
"${appspawn_path}/test/moduletest/appspawn_test_cmder.cpp",
|
||||
"${appspawn_path}/util/src/appspawn_utils.c",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
"//commonlibrary/c_utils/base/include",
|
||||
"//third_party/zlib/contrib/minizip",
|
||||
"//third_party/zlib",
|
||||
]
|
||||
|
||||
configs = [
|
||||
"${appspawn_path}:appspawn_config",
|
||||
"${ability_runtime_path}/services/appmgr:appmgr_config",
|
||||
"${appspawn_path}",
|
||||
"${appspawn_path}/common",
|
||||
"${appspawn_path}/standard",
|
||||
"${appspawn_path}/modules/modulemgr",
|
||||
"${appspawn_path}/modules/ace_adapter",
|
||||
"${appspawn_path}/modules/common",
|
||||
"${appspawn_path}/modules/sandbox",
|
||||
"${appspawn_path}/test/moduletest/threadpool",
|
||||
"${appspawn_innerkits_path}/include",
|
||||
"${appspawn_innerkits_path}/client",
|
||||
"${appspawn_innerkits_path}/permission",
|
||||
"${appspawn_innerkits_path}/module_engine/include",
|
||||
"${appspawn_path}/test/mock",
|
||||
"${appspawn_path}/test/unittest",
|
||||
"${appspawn_path}/util/include",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"${ability_runtime_path}/services/appmgr:libappms",
|
||||
"${appspawn_path}/interfaces/innerkits:appspawn_socket_client",
|
||||
"${appspawn_innerkits_path}/client:appspawn_client",
|
||||
"//third_party/googletest:gtest_main",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"bundle_framework:appexecfwk_base",
|
||||
"cJSON:cjson",
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"hilog:libhilog",
|
||||
"init:libbegetutil",
|
||||
]
|
||||
subsystem_name = "${subsystem_name}"
|
||||
part_name = "${part_name}"
|
||||
}
|
||||
|
||||
group("moduletest") {
|
||||
testonly = true
|
||||
|
||||
deps = [ ":AppSpawnModuleTest" ]
|
||||
deps = [
|
||||
":AppSpawnModuleTest",
|
||||
":AppSpawnTest",
|
||||
]
|
||||
deps += [ "hnp_sample:hnpsample" ]
|
||||
if (appspawn_test_cmd) {
|
||||
deps += [ ":AppSpawnTest" ]
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@ -13,18 +13,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "appspawn_test_client.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "appspawn.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
using namespace testing;
|
||||
using namespace testing::ext;
|
||||
using namespace OHOS;
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppSpawn {
|
||||
|
||||
class AppSpawnClientTest : public testing::Test, public AppSpawnTestClient {
|
||||
class AppSpawnClientTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
@ -32,317 +31,68 @@ public:
|
||||
void TearDown() {}
|
||||
};
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_1, TestSize.Level0)
|
||||
static AppSpawnReqMsgHandle CreateMsg(AppSpawnClientHandle handle, const char *bundleName)
|
||||
{
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
AppSpawnReqMsgHandle reqHandle = 0;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, bundleName, &reqHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return 0, "Failed to create req %{public}s", bundleName);
|
||||
do {
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, bundleName);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to create req %{public}s", bundleName);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
request.code = SPAWN_NATIVE_PROCESS;
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
EXPECT_LT(ret, 0);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
AppDacInfo dacInfo = {};
|
||||
dacInfo.uid = 20010029; // 20010029 test data
|
||||
dacInfo.gid = 20010029; // 20010029 test data
|
||||
dacInfo.gidCount = 2; // 2 count
|
||||
dacInfo.gidTable[0] = 20010029; // 20010029 test data
|
||||
dacInfo.gidTable[1] = 20010029 + 1; // 20010029 test data
|
||||
(void)strcpy_s(dacInfo.userName, sizeof(dacInfo.userName), "test-app-name");
|
||||
ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to add dac %{public}s", APPSPAWN_SERVER_NAME);
|
||||
|
||||
AppSpawnReqMsgSetAppFlag(reqHandle, static_cast<AppFlagsIndex>(10)); // 10 test
|
||||
|
||||
ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, 12345678); // 12345678
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to add access token %{public}s", APPSPAWN_SERVER_NAME);
|
||||
|
||||
static const char *permissions[] = {
|
||||
"ohos.permission.READ_IMAGEVIDEO",
|
||||
"ohos.permission.FILE_CROSS_APP",
|
||||
"ohos.permission.ACTIVATE_THEME_PACKAGE",
|
||||
"ohos.permission.GET_WALLPAPER",
|
||||
};
|
||||
size_t count = sizeof(permissions) / sizeof(permissions[0]);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
ret = AppSpawnReqMsgAddPermission(reqHandle, permissions[i]);
|
||||
APPSPAWN_CHECK(ret == 0, break, "Failed to create req %{public}s", bundleName);
|
||||
}
|
||||
return reqHandle;
|
||||
} while (0);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
return INVALID_REQ_HANDLE;
|
||||
}
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_2, TestSize.Level0)
|
||||
static AppSpawnClientHandle CreateClient(const char *serviceName)
|
||||
{
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
|
||||
// more gid
|
||||
request.gidCount = APP_MAX_GIDS + 1;
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
EXPECT_NE(ret, 0);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
AppSpawnClientHandle clientHandle = NULL;
|
||||
int ret = AppSpawnClientInit(serviceName, &clientHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return nullptr, "Failed to create client %{public}s", serviceName);
|
||||
return clientHandle;
|
||||
}
|
||||
|
||||
// has hsp data,read json from etc
|
||||
static const std::string g_jsonStr = "{ "
|
||||
"\"bundles\": [{ "
|
||||
"\"name\":\"test_service\", "
|
||||
"\"path\":[\"/data/init_ut/test_service\"], "
|
||||
"\"importance\":-20, "
|
||||
"\"uid\":\"system\", "
|
||||
"\"writepid\":[\"/dev/test_service\"], "
|
||||
"\"console\":1, "
|
||||
"\"caps\":[\"TEST_ERR\"], "
|
||||
"\"gid\":[\"system\"], "
|
||||
"\"critical\":1 "
|
||||
"}], "
|
||||
"\"modules\": [{ "
|
||||
"\"name\":\"test_service\", "
|
||||
"\"path\":[\"/data/init_ut/test_service\"], "
|
||||
"\"importance\":-20, "
|
||||
"\"uid\":\"system\", "
|
||||
"\"writepid\":[\"/dev/test_service\"], "
|
||||
"\"console\":1, "
|
||||
"\"caps\":[\"TEST_ERR\"], "
|
||||
"\"gid\":[\"system\"], "
|
||||
"\"critical\":1 "
|
||||
"}], "
|
||||
" \"versions\": [{ "
|
||||
"\"name\":\"test_service\", "
|
||||
"\"path\":[\"/data/init_ut/test_service\"], "
|
||||
"\"importance\":-20, "
|
||||
"\"uid\":\"system\", "
|
||||
"\"writepid\":[\"/dev/test_service\"], "
|
||||
"\"console\":1, "
|
||||
"\"caps\":[\"TEST_ERR\"], "
|
||||
"\"gid\":[\"system\"], "
|
||||
"\"critical\":1 "
|
||||
"}] "
|
||||
"}";
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_3, TestSize.Level0)
|
||||
HWTEST(AppSpawnClientTest, AppSpawn_Client_test001, TestSize.Level0)
|
||||
{
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_3");
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
AppSpawnClientHandle clientHandle = CreateClient(APPSPAWN_SERVER_NAME);
|
||||
ASSERT_EQ(clientHandle != NULL, 1);
|
||||
AppSpawnReqMsgHandle reqHandle = CreateMsg(clientHandle, "ohos.samples.clock");
|
||||
ASSERT_EQ(reqHandle != INVALID_REQ_HANDLE, 1);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
|
||||
printf("AppSpawn_Client_AppSpawn_3 hsp %zu %s \n", g_jsonStr.size(), g_jsonStr.c_str());
|
||||
request.extraInfo.totalLength = g_jsonStr.size();
|
||||
std::vector<char *> data(sizeof(request) + g_jsonStr.size());
|
||||
memcpy_s(data.data(), sizeof(request), &request, sizeof(request));
|
||||
memcpy_s(data.data() + sizeof(request), g_jsonStr.size(), g_jsonStr.data(), g_jsonStr.size());
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
AppSpawnResult result = {};
|
||||
int ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
|
||||
if (ret == 0 && result.pid > 0) {
|
||||
kill(result.pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
}
|
||||
|
||||
// has env data,read json from etc
|
||||
static const std::string g_envJsonStr = "|AppEnv|{"
|
||||
"\"test.name1\": \"test.value1\","
|
||||
"\"test.name2\": \"test.value2\""
|
||||
"}|AppEnv|";
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_3_1, TestSize.Level0)
|
||||
{
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_3_1 start");
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
|
||||
printf("AppSpawn_Client_AppSpawn_3_1 env %zu %s \n", g_envJsonStr.size(), g_envJsonStr.c_str());
|
||||
request.extraInfo.totalLength = g_envJsonStr.size();
|
||||
std::vector<char *> data(sizeof(request) + g_envJsonStr.size());
|
||||
memcpy_s(data.data(), sizeof(request), &request, sizeof(request));
|
||||
memcpy_s(data.data() + sizeof(request), g_envJsonStr.size(), g_envJsonStr.data(), g_envJsonStr.size());
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_3_1 end");
|
||||
}
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_4, TestSize.Level0)
|
||||
{
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_4");
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
|
||||
// has hsp data,read json from etc
|
||||
const std::string jsonPath("/system/etc/sandbox/system-sandbox.json");
|
||||
std::ifstream jsonFileStream;
|
||||
jsonFileStream.open(jsonPath.c_str(), std::ios::in);
|
||||
EXPECT_EQ(jsonFileStream.is_open() == true, 1);
|
||||
std::vector<char> buf;
|
||||
char ch;
|
||||
while (jsonFileStream.get(ch)) {
|
||||
buf.insert(buf.end(), ch);
|
||||
}
|
||||
jsonFileStream.close();
|
||||
|
||||
printf("AppSpawn_Client_AppSpawn_4 hsp %zu \n", buf.size());
|
||||
request.extraInfo.totalLength = buf.size();
|
||||
std::vector<char *> data(sizeof(request) + buf.size());
|
||||
memcpy_s(data.data(), sizeof(request), &request, sizeof(request));
|
||||
memcpy_s(data.data() + sizeof(request), buf.size(), buf.data(), buf.size());
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
}
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_5, TestSize.Level0)
|
||||
{
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_5 start");
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
|
||||
// more hsp data,read json from etc
|
||||
const std::string jsonPath("/system/etc/sandbox/appdata-sandbox.json");
|
||||
std::ifstream jsonFileStream;
|
||||
jsonFileStream.open(jsonPath.c_str(), std::ios::in);
|
||||
EXPECT_EQ(jsonFileStream.is_open() == true, 1);
|
||||
std::vector<char> buf;
|
||||
char ch;
|
||||
while (jsonFileStream.get(ch)) {
|
||||
buf.insert(buf.end(), ch);
|
||||
}
|
||||
jsonFileStream.close();
|
||||
|
||||
request.extraInfo.totalLength = buf.size();
|
||||
std::vector<char *> data(sizeof(request) + buf.size());
|
||||
memcpy_s(data.data(), sizeof(request), &request, sizeof(request));
|
||||
memcpy_s(data.data() + sizeof(request), buf.size(), buf.data(), buf.size());
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_5 end");
|
||||
}
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_6, TestSize.Level0)
|
||||
{
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_6 start");
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
SetParameter("startup.appspawn.cold.boot", "1");
|
||||
SetParameter("persist.appspawn.client.timeout", "10");
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > /data/aaa.txt");
|
||||
request.flags = APP_COLD_BOOT;
|
||||
request.code = SPAWN_NATIVE_PROCESS;
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
EXPECT_LT(ret, 0);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_6 end");
|
||||
}
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_7, TestSize.Level0)
|
||||
{
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_7 start");
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
SetParameter("startup.appspawn.cold.boot", "1");
|
||||
SetParameter("persist.appspawn.client.timeout", "10");
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.2222222222222clock", "ls -l > /data/aaa.txt");
|
||||
request.flags = APP_COLD_BOOT | APP_NO_SANDBOX;
|
||||
request.code = SPAWN_NATIVE_PROCESS;
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
EXPECT_EQ(ret, 0);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_7 end");
|
||||
}
|
||||
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_NWebSpawn_1, TestSize.Level0)
|
||||
{
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/NWebSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
EXPECT_EQ(ret, 0);
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
ClientClose();
|
||||
}
|
||||
|
||||
HWTEST_F(AppSpawnClientTest, AppSpawn_Client_NWebSpawn_2, TestSize.Level0)
|
||||
{
|
||||
int ret = ClientCreateSocket("/dev/unix/socket/NWebSpawn");
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt");
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
EXPECT_EQ(ret, 0);
|
||||
pid_t pid = 0;
|
||||
ret = ClientRecvMsg(pid);
|
||||
EXPECT_EQ(ret, 0);
|
||||
printf("AppSpawn_Client_NWebSpawn_2 pid %d \n", pid);
|
||||
request.code = GET_RENDER_TERMINATION_STATUS;
|
||||
request.pid = pid;
|
||||
ret = ClientSendMsg(reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = ClientRecvMsg(pid);
|
||||
printf("AppSpawn_Client_NWebSpawn_2 result %d \n", ret);
|
||||
// close client
|
||||
ClientClose();
|
||||
AppSpawnClientDestroy(clientHandle);
|
||||
}
|
||||
} // namespace AppSpawn
|
||||
} // namespace OHOS
|
||||
} // namespace OHOS
|
||||
|
858
test/moduletest/appspawn_module_test.cpp
Normal file → Executable file
858
test/moduletest/appspawn_module_test.cpp
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef APPSPAWN_CLIENT_TEST_H
|
||||
#define APPSPAWN_CLIENT_TEST_H
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#include "client_socket.h"
|
||||
#include "appspawn_server.h"
|
||||
#include "parameter.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppSpawn {
|
||||
|
||||
class AppSpawnTestClient {
|
||||
public:
|
||||
AppSpawnTestClient() = default;
|
||||
~AppSpawnTestClient() = default;
|
||||
|
||||
int ClientCreateSocket(std::string path = "/dev/unix/socket/NWebSpawn")
|
||||
{
|
||||
// close old socket and create new
|
||||
if (clientSocket_ != nullptr) {
|
||||
clientSocket_->CloseClient();
|
||||
clientSocket_ = nullptr;
|
||||
}
|
||||
clientSocket_ = std::make_shared<ClientSocket>(path);
|
||||
APPSPAWN_CHECK(clientSocket_ != nullptr, return -1, "Failed to create client for path %s", path.c_str());
|
||||
int ret = clientSocket_->CreateClient();
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for path %ss", path.c_str());
|
||||
ret = clientSocket_->ConnectSocket();
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to connect to server %ss", path.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ClientClose()
|
||||
{
|
||||
if (clientSocket_ != nullptr) {
|
||||
clientSocket_->CloseClient();
|
||||
clientSocket_ = nullptr;
|
||||
}
|
||||
}
|
||||
int ClientSendMsg(const uint8_t *buf, int len)
|
||||
{
|
||||
int curr = 0;
|
||||
int real = 0;
|
||||
uint8_t *buffer = const_cast<uint8_t *>(buf);
|
||||
const int maxLen = 5 * 1024;
|
||||
while (curr < len) {
|
||||
if ((len - curr) > maxLen) {
|
||||
real = maxLen;
|
||||
} else {
|
||||
real = len - curr;
|
||||
}
|
||||
if (clientSocket_->WriteSocketMessage(static_cast<const void *>(buffer + curr), real) != real) {
|
||||
return -1;
|
||||
}
|
||||
curr += real;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ClientRecvMsg(pid_t &pid)
|
||||
{
|
||||
pid = -1;
|
||||
std::vector<uint8_t> data(sizeof(pid_t)); // 4 pid size
|
||||
if (clientSocket_->ReadSocketMessage(data.data(), data.size()) == sizeof(pid_t)) {
|
||||
int ret = *(reinterpret_cast<int *>(data.data()));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
pid = static_cast<pid_t>(ret);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ClientFillMsg(AppParameter *request, const std::string &processName, const std::string &cmd)
|
||||
{
|
||||
request->code = DEFAULT;
|
||||
request->flags = 0;
|
||||
request->uid = 20010033; // 20010033 test uid
|
||||
request->gid = 20010033; // 20010033 test gid
|
||||
request->gidCount = 0;
|
||||
request->accessTokenId = 0x200a509d; // 0x200a509d test token id
|
||||
request->accessTokenIdEx = 0x4832514205; // 0x4832514205 test token id
|
||||
request->allowInternet = 1;
|
||||
request->extraInfo.totalLength = 0;
|
||||
request->extraInfo.savedLength = 0;
|
||||
request->extraInfo.data = nullptr;
|
||||
int ret = strcpy_s(request->apl, sizeof(request->processName), processName.c_str());
|
||||
ret += strcpy_s(request->processName, sizeof(request->processName), processName.c_str());
|
||||
ret += strcpy_s(request->bundleName, sizeof(request->bundleName), processName.c_str());
|
||||
ret += strcpy_s(request->renderCmd, sizeof(request->renderCmd), cmd.c_str());
|
||||
ret += strcpy_s(request->ownerId, sizeof(request->ownerId), cmd.c_str());
|
||||
if (ret != 0) {
|
||||
printf("Failed to copy bundle name \n");
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<ClientSocket> clientSocket_ {};
|
||||
};
|
||||
|
||||
} // namespace AppSpawn
|
||||
} // namespace OHOS
|
||||
#endif // APPSPAWN_CLIENT_TEST_H
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "appspawn_test_client.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
OHOS::AppSpawn::AppSpawnTestClient g_testClient;
|
||||
|
||||
static int DoRun(const char *server, const AppParameter *request)
|
||||
{
|
||||
int ret = g_testClient.ClientCreateSocket(server);
|
||||
if (ret != 0) {
|
||||
printf("Failed to connect server \n");
|
||||
return 1;
|
||||
}
|
||||
ret = g_testClient.ClientSendMsg(reinterpret_cast<const uint8_t *>(request), sizeof(AppParameter));
|
||||
if (ret != 0) {
|
||||
printf("Failed to send msg to server \n");
|
||||
g_testClient.ClientClose();
|
||||
return 1;
|
||||
}
|
||||
pid_t pid = 0;
|
||||
ret = g_testClient.ClientRecvMsg(pid);
|
||||
if (ret != 0) {
|
||||
printf("Failed spawn new app result %d \n", ret);
|
||||
g_testClient.ClientClose();
|
||||
quick_exit(0);
|
||||
return 1;
|
||||
}
|
||||
if (pid > 0) {
|
||||
printf("Success spawn new app pid %d \n", pid);
|
||||
}
|
||||
int index = 0;
|
||||
while (index < 5) { // wait 5s
|
||||
sleep(1);
|
||||
index++;
|
||||
}
|
||||
if (pid > 0) {
|
||||
APPSPAWN_LOGI("Success spawn new app pid %{public}d \n", pid);
|
||||
kill(pid, SIGKILL);
|
||||
}
|
||||
// close client
|
||||
g_testClient.ClientClose();
|
||||
quick_exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *const argv[])
|
||||
{
|
||||
int coldStart = 0;
|
||||
int withSandbox = 0;
|
||||
const char *cmd = "ls -l /data > /data/test.log";
|
||||
const char *bundleName = "ohos.samples.test";
|
||||
const char *server = "/dev/unix/socket/AppSpawn";
|
||||
for (int32_t i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-c") == 0) {
|
||||
coldStart = 1;
|
||||
} else if (strcmp(argv[i], "-s") == 0) {
|
||||
withSandbox = 1;
|
||||
} else if (strcmp(argv[i], "--nwebspawn") == 0) {
|
||||
server = "/dev/unix/socket/NWebSpawn";
|
||||
} else if (strcmp(argv[i], "-b") == 0 && ((i + 1) < argc)) {
|
||||
i++;
|
||||
bundleName = argv[i];
|
||||
} else if (strcmp(argv[i], "-C") == 0 && ((i + 1) < argc)) {
|
||||
i++;
|
||||
cmd = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (coldStart) {
|
||||
SetParameter("startup.appspawn.cold.boot", "1");
|
||||
SetParameter("persist.appspawn.client.timeout", "10");
|
||||
}
|
||||
|
||||
AppParameter request = {};
|
||||
memset_s((void *)(&request), sizeof(request), 0, sizeof(request));
|
||||
g_testClient.ClientFillMsg(&request, bundleName, cmd);
|
||||
|
||||
request.flags = coldStart ? APP_COLD_BOOT : 0;
|
||||
request.flags |= !withSandbox ? APP_NO_SANDBOX : 0;
|
||||
request.code = SPAWN_NATIVE_PROCESS;
|
||||
return DoRun(server, &request);
|
||||
}
|
593
test/moduletest/appspawn_test_cmder.cpp
Executable file
593
test/moduletest/appspawn_test_cmder.cpp
Executable file
@ -0,0 +1,593 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "appspawn_test_cmder.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "appspawn.h"
|
||||
#include "appspawn_msg.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "command_lexer.h"
|
||||
#include "cJSON.h"
|
||||
#include "securec.h"
|
||||
#include "thread_manager.h"
|
||||
|
||||
#define MAX_THREAD 10
|
||||
#define MAX_SEND 200
|
||||
#define PTY_PATH_SIZE 128
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppSpawnModuleTest {
|
||||
static const std::string g_defaultAppInfo = "{ \
|
||||
\"msg-type\": 0, \
|
||||
\"msg-flags\": [1, 2 ], \
|
||||
\"process-name\" : \"com.example.myapplication\", \
|
||||
\"dac-info\" : { \
|
||||
\"uid\" : 20010043, \
|
||||
\"gid\" : 20010043,\
|
||||
\"gid-table\" : [],\
|
||||
\"user-name\" : \"\" \
|
||||
},\
|
||||
\"access-token\" : {\
|
||||
\"accessTokenIdEx\" : 537854093\
|
||||
},\
|
||||
\"permission\" : [\
|
||||
\"ohos.permission.READ_IMAGEVIDEO\",\
|
||||
\"ohos.permission.FILE_CROSS_APP\",\
|
||||
\"ohos.permission.ACTIVATE_THEME_PACKAGE\"\
|
||||
],\
|
||||
\"internet-permission\" : {\
|
||||
\"set-allow-internet\" : 0,\
|
||||
\"allow-internet\" : 0\
|
||||
},\
|
||||
\"bundle-info\" : {\
|
||||
\"bundle-index\" : 0,\
|
||||
\"bundle-name\" : \"com.example.myapplication\" \
|
||||
},\
|
||||
\"owner-id\" : \"\",\
|
||||
\"render-cmd\" : \"1234567890\",\
|
||||
\"domain-info\" : {\
|
||||
\"hap-flags\" : 0,\
|
||||
\"apl\" : \"system_core\"\
|
||||
},\
|
||||
\"ext-info\" : [\
|
||||
{\
|
||||
\"name\" : \"test\",\
|
||||
\"value\" : \"4444444444444444444\" \
|
||||
} \
|
||||
]\
|
||||
}";
|
||||
|
||||
static const char *APPSPAWN_TEST_USAGE = "usage: AppSpawnTest <options> \n"
|
||||
"options list:\n"
|
||||
" --help list available commands\n"
|
||||
" --file xx file path with app info\n"
|
||||
" --thread xx use multi-thread to send message\n"
|
||||
" --type xx send msg type \n"
|
||||
" --pid xx render terminate pid\n"
|
||||
" --mode nwebspawn send message to nwebspawn service\n";
|
||||
|
||||
int AppSpawnTestCommander::ProcessArgs(int argc, char *const argv[])
|
||||
{
|
||||
int sendMsg = 0;
|
||||
msgType_ = MAX_TYPE_INVALID;
|
||||
for (int32_t i = 0; i < argc; i++) {
|
||||
if (argv[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "--file") == 0 && ((i + 1) < argc)) { // test file
|
||||
i++;
|
||||
testFileName_ = argv[i];
|
||||
sendMsg = 1;
|
||||
} else if (strcmp(argv[i], "--thread") == 0 && ((i + 1) < argc)) { // use thread
|
||||
i++;
|
||||
threadCount_ = atoi(argv[i]);
|
||||
if (threadCount_ > MAX_THREAD) {
|
||||
threadCount_ = MAX_THREAD;
|
||||
}
|
||||
sendMsg = 1;
|
||||
} else if (strcmp(argv[i], "--mode") == 0 && ((i + 1) < argc)) {
|
||||
i++;
|
||||
appSpawn_ = strcmp(argv[i], "nwebspawn") == 0 ? 0 : 1;
|
||||
sendMsg = 1;
|
||||
} else if (strcmp(argv[i], "--type") == 0 && ((i + 1) < argc)) {
|
||||
i++;
|
||||
msgType_ = atoi(argv[i]);
|
||||
sendMsg = 1;
|
||||
} else if (strcmp(argv[i], "--pid") == 0 && ((i + 1) < argc)) {
|
||||
i++;
|
||||
msgType_ = MSG_GET_RENDER_TERMINATION_STATUS;
|
||||
terminatePid_ = atoi(argv[i]);
|
||||
sendMsg = 1;
|
||||
} else if (strcmp(argv[i], "--help") == 0) {
|
||||
printf("%s\n", APPSPAWN_TEST_USAGE);
|
||||
return 1;
|
||||
} else if (strcmp(argv[i], "--send") == 0 || strcmp(argv[i], "send") == 0) {
|
||||
sendMsg = 1;
|
||||
}
|
||||
}
|
||||
if (sendMsg == 0) {
|
||||
printf("%s\n", APPSPAWN_TEST_USAGE);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t AppSpawnTestCommander::GetUint32ArrayFromJson(const cJSON *json,
|
||||
const char *name, uint32_t dataArray[], uint32_t maxCount)
|
||||
{
|
||||
APPSPAWN_CHECK(json != NULL, return 0, "Invalid json");
|
||||
APPSPAWN_CHECK(name != NULL, return 0, "Invalid name");
|
||||
APPSPAWN_CHECK(dataArray != NULL, return 0, "Invalid dataArray");
|
||||
APPSPAWN_CHECK(cJSON_IsObject(json), return 0, "json is not object.");
|
||||
cJSON *array = cJSON_GetObjectItemCaseSensitive(json, name);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(array != NULL, return 0);
|
||||
APPSPAWN_CHECK(cJSON_IsArray(array), return 0, "json is not object.");
|
||||
|
||||
uint32_t count = 0;
|
||||
uint32_t arrayLen = cJSON_GetArraySize(array);
|
||||
for (int i = 0; i < arrayLen; i++) {
|
||||
cJSON *item = cJSON_GetArrayItem(array, i);
|
||||
uint32_t value = (uint32_t)cJSON_GetNumberValue(item);
|
||||
if (count < maxCount) {
|
||||
dataArray[count++] = value;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::AddBundleInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle)
|
||||
{
|
||||
cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "bundle-info");
|
||||
APPSPAWN_CHECK_ONLY_EXPER(config, return 0);
|
||||
|
||||
uint32_t bundleIndex = GetIntValueFromJsonObj(config, "bundle-index", 0);
|
||||
char *bundleName = GetStringFromJsonObj(config, "bundle-name");
|
||||
int ret = AppSpawnReqMsgSetBundleInfo(reqHandle, bundleIndex, bundleName);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add bundle info req %{public}s", bundleName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::GetDacInfoFromJson(const cJSON *appInfoConfig, AppDacInfo &info)
|
||||
{
|
||||
cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "dac-info");
|
||||
APPSPAWN_CHECK_ONLY_EXPER(config, return 0);
|
||||
|
||||
info.uid = GetIntValueFromJsonObj(config, "uid", 0);
|
||||
info.gid = GetIntValueFromJsonObj(config, "gid", 0);
|
||||
info.gidCount = GetUint32ArrayFromJson(config, "gid-table", info.gidTable, APP_MAX_GIDS);
|
||||
char *userName = GetStringFromJsonObj(config, "user-name");
|
||||
if (userName != nullptr) {
|
||||
return strcpy_s(info.userName, sizeof(info.userName), userName);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::GetInternetPermissionInfoFromJson(
|
||||
const cJSON *appInfoConfig, AppSpawnMsgInternetInfo &info)
|
||||
{
|
||||
cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "internet-permission");
|
||||
APPSPAWN_CHECK_ONLY_EXPER(config, return 0);
|
||||
|
||||
info.setAllowInternet = GetIntValueFromJsonObj(config, "set-allow-internet", 0);
|
||||
info.allowInternet = GetIntValueFromJsonObj(config, "allow-internet", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::GetAccessTokenFromJson(const cJSON *appInfoConfig, AppSpawnMsgAccessToken &info)
|
||||
{
|
||||
cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "access-token");
|
||||
APPSPAWN_CHECK_ONLY_EXPER(config, return 0);
|
||||
|
||||
info.accessTokenIdEx = GetIntValueFromJsonObj(config, "accessTokenIdEx", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::AddDomainInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle)
|
||||
{
|
||||
cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "domain-info");
|
||||
APPSPAWN_CHECK_ONLY_EXPER(config, return 0);
|
||||
|
||||
uint32_t hapFlags = GetIntValueFromJsonObj(config, "hap-flags", 0);
|
||||
char *apl = GetStringFromJsonObj(config, "apl");
|
||||
int ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, hapFlags, apl);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to domain info");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::AddExtTlv(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle)
|
||||
{
|
||||
cJSON *configs = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "ext-info");
|
||||
APPSPAWN_CHECK_ONLY_EXPER(configs, return 0);
|
||||
|
||||
int ret = 0;
|
||||
uint32_t count = cJSON_GetArraySize(configs);
|
||||
for (unsigned int j = 0; j < count; j++) {
|
||||
cJSON *config = cJSON_GetArrayItem(configs, j);
|
||||
|
||||
char *name = GetStringFromJsonObj(config, "name");
|
||||
char *value = GetStringFromJsonObj(config, "value");
|
||||
APPSPAWN_LOGV("ext-info %{public}s %{public}s", name, value);
|
||||
ret = AppSpawnReqMsgAddStringInfo(reqHandle, name, value);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add ext name %{public}s", name);
|
||||
}
|
||||
|
||||
// 添加一个二进制的扩展元素
|
||||
AppDacInfo dacInfo{};
|
||||
dacInfo.uid = 101; // 101 test data
|
||||
dacInfo.gid = 101; // 101 test data
|
||||
dacInfo.gidTable[0] = 101; // 101 test data
|
||||
dacInfo.gidCount = 1;
|
||||
(void)strcpy_s(dacInfo.userName, sizeof(dacInfo.userName), processName_.c_str());
|
||||
ret = AppSpawnReqMsgAddExtInfo(reqHandle, "app-dac-info", reinterpret_cast<uint8_t *>(&dacInfo), sizeof(dacInfo));
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add ext name app-info");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::BuildMsgFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle)
|
||||
{
|
||||
int ret = AddBundleInfoFromJson(appInfoConfig, reqHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add dac %{public}s", processName_.c_str());
|
||||
|
||||
ret = AddDomainInfoFromJson(appInfoConfig, reqHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add dac %{public}s", processName_.c_str());
|
||||
|
||||
AppDacInfo dacInfo = {};
|
||||
ret = GetDacInfoFromJson(appInfoConfig, dacInfo);
|
||||
APPSPAWN_LOGE("*************, %d", dacInfo.gidCount);
|
||||
APPSPAWN_LOGE("*************, %d", dacInfo.uid);
|
||||
ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add dac %{public}s", processName_.c_str());
|
||||
|
||||
AppSpawnMsgAccessToken token = {};
|
||||
ret = GetAccessTokenFromJson(appInfoConfig, token);
|
||||
ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, token.accessTokenIdEx);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to add access token %{public}s", processName_.c_str());
|
||||
|
||||
cJSON *obj = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "permission");
|
||||
if (obj != nullptr && cJSON_IsArray(obj)) {
|
||||
int count = cJSON_GetArraySize(obj);
|
||||
for (int i = 0; i < count; i++) {
|
||||
char *value = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
|
||||
APPSPAWN_LOGV("permission %{public}s ", value);
|
||||
ret = AppSpawnReqMsgAddPermission(reqHandle, value);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to permission %{public}s", value);
|
||||
}
|
||||
}
|
||||
|
||||
AppSpawnMsgInternetInfo internetInfo = {};
|
||||
ret = GetInternetPermissionInfoFromJson(appInfoConfig, internetInfo);
|
||||
ret = AppSpawnReqMsgSetAppInternetPermissionInfo(reqHandle,
|
||||
internetInfo.allowInternet, internetInfo.setAllowInternet);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to internet info %{public}s", processName_.c_str());
|
||||
|
||||
std::string ownerId = GetStringFromJsonObj(appInfoConfig, "owner-id");
|
||||
if (!ownerId.empty()) {
|
||||
ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, ownerId.c_str());
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to ownerid %{public}s", processName_.c_str());
|
||||
}
|
||||
|
||||
std::string renderCmd = GetStringFromJsonObj(appInfoConfig, "render-cmd");
|
||||
if (!renderCmd.empty()) {
|
||||
ret = AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_RENDER_CMD, renderCmd.c_str());
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to add renderCmd %{public}s", renderCmd.c_str());
|
||||
}
|
||||
return AddExtTlv(appInfoConfig, reqHandle);
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::CreateOtherMsg(AppSpawnReqMsgHandle &reqHandle, pid_t pid)
|
||||
{
|
||||
if (msgType_ == MSG_GET_RENDER_TERMINATION_STATUS) {
|
||||
int ret = AppSpawnTerminateMsgCreate(pid, &reqHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to termination message req %{public}s", processName_.c_str());
|
||||
}
|
||||
if (msgType_ == MSG_DUMP) {
|
||||
int ret = AppSpawnReqMsgCreate(static_cast<AppSpawnMsgType>(msgType_), processName_.c_str(), &reqHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to dump req %{public}s", processName_.c_str());
|
||||
ret = AppSpawnReqMsgAddStringInfo(reqHandle, "pty-name", ptyName_.c_str());
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to add ptyName_ %{public}s", ptyName_.c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::CreateMsg(AppSpawnReqMsgHandle &reqHandle, const char *defaultConfig)
|
||||
{
|
||||
int ret = APPSPAWN_SYSTEM_ERROR;
|
||||
if (clientHandle_ == NULL) {
|
||||
const char *name = appSpawn_ ? APPSPAWN_SERVER_NAME : NWEBSPAWN_SERVER_NAME;
|
||||
ret = AppSpawnClientInit(name, &clientHandle_);
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to create client %{public}s", name);
|
||||
}
|
||||
reqHandle = INVALID_REQ_HANDLE;
|
||||
if (appInfoConfig_) {
|
||||
cJSON_Delete(appInfoConfig_);
|
||||
appInfoConfig_ = nullptr;
|
||||
}
|
||||
if (!testFileName_.empty()) {
|
||||
appInfoConfig_ = GetJsonObjFromFile(testFileName_.c_str());
|
||||
if (appInfoConfig_ == nullptr) {
|
||||
printf("Failed to load file %s, so use default info \n", testFileName_.c_str());
|
||||
}
|
||||
}
|
||||
if (appInfoConfig_ == nullptr) {
|
||||
appInfoConfig_ = cJSON_Parse(defaultConfig);
|
||||
}
|
||||
if (appInfoConfig_ == nullptr) {
|
||||
printf("Invalid app info \n");
|
||||
return APPSPAWN_SYSTEM_ERROR;
|
||||
}
|
||||
processName_ = GetStringFromJsonObj(appInfoConfig_, "process-name");
|
||||
if (processName_.empty()) {
|
||||
processName_ = "com.example.myapplication";
|
||||
}
|
||||
if (msgType_ == MAX_TYPE_INVALID) {
|
||||
msgType_ = GetIntValueFromJsonObj(appInfoConfig_, "msg-type", MSG_APP_SPAWN);
|
||||
}
|
||||
if (msgType_ == MSG_DUMP) {
|
||||
return CreateOtherMsg(reqHandle, 0);
|
||||
} else if (msgType_ == MSG_GET_RENDER_TERMINATION_STATUS) {
|
||||
pid_t pid = GetIntValueFromJsonObj(appInfoConfig_, "pid", 0);
|
||||
return CreateOtherMsg(reqHandle, pid);
|
||||
}
|
||||
ret = AppSpawnReqMsgCreate(static_cast<AppSpawnMsgType>(msgType_), processName_.c_str(), &reqHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return ret, "Failed to create req %{public}s", processName_.c_str());
|
||||
|
||||
uint32_t msgFlags[64] = {};
|
||||
uint32_t count = GetUint32ArrayFromJson(appInfoConfig_, "msg-flags", msgFlags, ARRAY_LENGTH(msgFlags));
|
||||
for (uint32_t j = 0; j < count; j++) {
|
||||
(void)AppSpawnReqMsgSetAppFlag(reqHandle, static_cast<AppFlagsIndex>(msgFlags[j]));
|
||||
}
|
||||
ret = BuildMsgFromJson(appInfoConfig_, reqHandle);
|
||||
APPSPAWN_CHECK(ret == 0, AppSpawnReqMsgFree(reqHandle);
|
||||
return ret, "Failed to build req %{public}s", processName_.c_str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::SendMsg()
|
||||
{
|
||||
const char *server = appSpawn_ ? APPSPAWN_SERVER_NAME : NWEBSPAWN_SERVER_NAME;
|
||||
printf("Send msg to server '%s' \n", server);
|
||||
AppSpawnReqMsgHandle reqHandle = INVALID_REQ_HANDLE;
|
||||
int ret = 0;
|
||||
if (msgType_ == MSG_DUMP) {
|
||||
while (!dumpFlags) {
|
||||
usleep(20000); // 20000
|
||||
}
|
||||
ret = CreateOtherMsg(reqHandle, 0);
|
||||
} else if (msgType_ == MSG_GET_RENDER_TERMINATION_STATUS) {
|
||||
ret = CreateOtherMsg(reqHandle, terminatePid_);
|
||||
} else {
|
||||
ret = CreateMsg(reqHandle, g_defaultAppInfo.c_str());
|
||||
}
|
||||
AppSpawnResult result = {ret, 0};
|
||||
if (ret == 0) {
|
||||
ret = AppSpawnClientSendMsg(clientHandle_, reqHandle, &result);
|
||||
}
|
||||
switch (msgType_) {
|
||||
case MSG_APP_SPAWN:
|
||||
if (result.result == 0) {
|
||||
printf("Spawn app %s success, pid %d \n", processName_.c_str(), result.pid);
|
||||
} else {
|
||||
printf("Spawn app %s fail, result 0x%x \n", processName_.c_str(), result.result);
|
||||
}
|
||||
break;
|
||||
case MSG_SPAWN_NATIVE_PROCESS:
|
||||
if (result.result == 0) {
|
||||
printf("Spawn native app %s success, pid %d \n", processName_.c_str(), result.pid);
|
||||
} else {
|
||||
printf("Spawn native app %s fail, result 0x%x \n", processName_.c_str(), result.result);
|
||||
}
|
||||
break;
|
||||
case MSG_GET_RENDER_TERMINATION_STATUS:
|
||||
printf("Terminate app %s success, pid %d status 0x%x \n", processName_.c_str(), result.pid, result.result);
|
||||
break;
|
||||
default:
|
||||
printf("Dump server %s result %d \n", server, ret);
|
||||
break;
|
||||
}
|
||||
msgType_ = MAX_TYPE_INVALID;
|
||||
terminatePid_ = 0;
|
||||
printf("Please input cmd: \n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::StartSendMsg()
|
||||
{
|
||||
int ret = 0;
|
||||
printf("Start send msg thread count %d file name %s \n", threadCount_, testFileName_.c_str());
|
||||
if (threadCount_ == 1) {
|
||||
SendMsg();
|
||||
} else {
|
||||
ThreadTaskHandle taskHandle = 0;
|
||||
ret = ThreadMgrAddTask(threadMgr_, &taskHandle);
|
||||
APPSPAWN_CHECK(ret == 0, return 0, "Failed to add task ");
|
||||
for (uint32_t index = 0; index < threadCount_; index++) {
|
||||
ThreadMgrAddExecutor(threadMgr_, taskHandle, TaskExecutorProc, reinterpret_cast<ThreadContext *>(this));
|
||||
}
|
||||
TaskSyncExecute(threadMgr_, taskHandle);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AppSpawnTestCommander::TaskExecutorProc(ThreadTaskHandle handle, const ThreadContext *context)
|
||||
{
|
||||
AppSpawnTestCommander *testCmder = AppSpawnTestCommander::ConvertTo(context);
|
||||
testCmder->SendMsg();
|
||||
}
|
||||
|
||||
void AppSpawnTestCommander::SendTaskFinish(ThreadTaskHandle handle, const ThreadContext *context)
|
||||
{
|
||||
APPSPAWN_LOGV("SendTaskFinish %{public}u \n", handle);
|
||||
}
|
||||
|
||||
static std::vector<std::string> g_args;
|
||||
static int HandleSplitString(const char *str, void *context)
|
||||
{
|
||||
APPSPAWN_LOGV("HandleSplitString %{public}s ", str);
|
||||
std::string value = str;
|
||||
g_args.push_back(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::ProcessInputCmd(std::string &cmd)
|
||||
{
|
||||
g_args.clear();
|
||||
int ret = StringSplit(cmd.c_str(), " ", nullptr, HandleSplitString);
|
||||
std::vector<char *> options;
|
||||
for (const auto &arg : g_args) {
|
||||
if (!arg.empty()) {
|
||||
options.push_back(const_cast<char *>(arg.c_str()));
|
||||
}
|
||||
}
|
||||
(void)ProcessArgs(options.size(), options.data());
|
||||
StartSendMsg();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AppSpawnTestCommander::InputThread(ThreadTaskHandle handle, const ThreadContext *context)
|
||||
{
|
||||
AppSpawnTestCommander *testCmder = AppSpawnTestCommander::ConvertTo(context);
|
||||
char buffer[1024] = {0}; // 1024 test buffer max len
|
||||
fd_set fds;
|
||||
printf("Please input cmd: \n");
|
||||
while (1) {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
int ret = select(STDIN_FILENO + 1, &fds, nullptr, nullptr, nullptr);
|
||||
if (ret <= 0) {
|
||||
if (testCmder->exit_) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ssize_t rlen = read(STDIN_FILENO, buffer, sizeof(buffer) - 1);
|
||||
if (rlen <= 1) {
|
||||
continue;
|
||||
}
|
||||
buffer[rlen - 1] = 0;
|
||||
printf("Recv command: '%s' \n", buffer);
|
||||
if (strncmp("quit", buffer, strlen("quit")) == 0) {
|
||||
testCmder->exit_ = 1;
|
||||
break;
|
||||
}
|
||||
if (strncmp("send", buffer, 4) == 0) { // 4 strlen("send")
|
||||
std::string cmd(buffer);
|
||||
testCmder->ProcessInputCmd(cmd);
|
||||
printf("Please input cmd: \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppSpawnTestCommander::DumpThread(ThreadTaskHandle handle, const ThreadContext *context)
|
||||
{
|
||||
AppSpawnTestCommander *testCmder = AppSpawnTestCommander::ConvertTo(context);
|
||||
printf("Start dump thread \n");
|
||||
char buffer[10240] = {0}; // 1024 test buffer max len
|
||||
fd_set fds;
|
||||
while (1) {
|
||||
testCmder->dumpFlags = 1;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(testCmder->ptyFd_, &fds);
|
||||
int ret = select(testCmder->ptyFd_ + 1, &fds, nullptr, nullptr, nullptr);
|
||||
if (ret <= 0) {
|
||||
if (testCmder->exit_) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!FD_ISSET(testCmder->ptyFd_, &fds)) {
|
||||
continue;
|
||||
}
|
||||
ssize_t rlen = read(testCmder->ptyFd_, buffer, sizeof(buffer) - 1);
|
||||
while (rlen > 0) {
|
||||
buffer[rlen] = '\0';
|
||||
printf("%s", buffer);
|
||||
fflush(stdout);
|
||||
rlen = read(testCmder->ptyFd_, buffer, sizeof(buffer) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::Run()
|
||||
{
|
||||
int ret = 0;
|
||||
const char *name = appSpawn_ ? APPSPAWN_SERVER_NAME : NWEBSPAWN_SERVER_NAME;
|
||||
if (clientHandle_ == NULL) {
|
||||
ret = AppSpawnClientInit(name, &clientHandle_);
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to create client %{public}s", name);
|
||||
}
|
||||
|
||||
InitPtyInterface();
|
||||
|
||||
ret = CreateThreadMgr(5, &threadMgr_); // 5 max thread
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to create thread manager");
|
||||
|
||||
ret = ThreadMgrAddTask(threadMgr_, &inputHandle_);
|
||||
APPSPAWN_CHECK(ret == 0, return 0, "Failed to add task for thread ");
|
||||
ThreadMgrAddExecutor(threadMgr_, inputHandle_, InputThread, this);
|
||||
TaskExecute(threadMgr_, inputHandle_, SendTaskFinish, this);
|
||||
|
||||
ret = ThreadMgrAddTask(threadMgr_, &dumpHandle_);
|
||||
APPSPAWN_CHECK(ret == 0, return 0, "Failed to add task for thread ");
|
||||
ThreadMgrAddExecutor(threadMgr_, dumpHandle_, DumpThread, this);
|
||||
TaskExecute(threadMgr_, dumpHandle_, SendTaskFinish, this);
|
||||
|
||||
StartSendMsg();
|
||||
|
||||
APPSPAWN_LOGV("Finish send msg \n");
|
||||
while (!exit_) {
|
||||
usleep(200000); // 200000 200ms
|
||||
}
|
||||
ThreadMgrCancelTask(threadMgr_, inputHandle_);
|
||||
ThreadMgrCancelTask(threadMgr_, dumpHandle_);
|
||||
DestroyThreadMgr(threadMgr_);
|
||||
threadMgr_ = nullptr;
|
||||
inputHandle_ = 0;
|
||||
dumpHandle_ = 0;
|
||||
AppSpawnClientDestroy(clientHandle_);
|
||||
clientHandle_ = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AppSpawnTestCommander::InitPtyInterface()
|
||||
{
|
||||
// open master pty and get slave pty
|
||||
int pfd = open("/dev/ptmx", O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
|
||||
APPSPAWN_CHECK(pfd >= 0, return -1, "Failed open pty err=%d", errno);
|
||||
APPSPAWN_CHECK(grantpt(pfd) >= 0, close(pfd); return -1, "Failed to call grantpt");
|
||||
APPSPAWN_CHECK(unlockpt(pfd) >= 0, close(pfd); return -1, "Failed to call unlockpt");
|
||||
char ptsbuffer[PTY_PATH_SIZE] = {0};
|
||||
int ret = ptsname_r(pfd, ptsbuffer, sizeof(ptsbuffer));
|
||||
APPSPAWN_CHECK(ret >= 0, close(pfd);
|
||||
return -1, "Failed to get pts name err=%d", errno);
|
||||
APPSPAWN_LOGI("ptsbuffer is %s", ptsbuffer);
|
||||
APPSPAWN_CHECK(chmod(ptsbuffer, S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == 0, close(pfd);
|
||||
return -1, "Failed to chmod %s, err=%d", ptsbuffer, errno);
|
||||
ptyFd_ = pfd;
|
||||
ptyName_ = std::string(ptsbuffer);
|
||||
return 0;
|
||||
}
|
||||
} // namespace AppSpawnModuleTest
|
||||
} // namespace OHOS
|
132
test/moduletest/appspawn_test_cmder.h
Executable file
132
test/moduletest/appspawn_test_cmder.h
Executable file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef APPSPAWN_TEST_CMD_H
|
||||
#define APPSPAWN_TEST_CMD_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "appspawn.h"
|
||||
#include "appspawn_msg.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "cJSON.h"
|
||||
#include "securec.h"
|
||||
#include "thread_manager.h"
|
||||
|
||||
typedef struct TagThreadContext {
|
||||
} ThreadContext;
|
||||
|
||||
__attribute__((always_inline)) inline char *GetStringFromJsonObj(const cJSON *json, const char *key)
|
||||
{
|
||||
APPSPAWN_CHECK_ONLY_EXPER(key != NULL && json != NULL, NULL);
|
||||
APPSPAWN_CHECK(cJSON_IsObject(json), return NULL, "json is not object %{public}s %s", key, cJSON_Print(json));
|
||||
cJSON *obj = cJSON_GetObjectItemCaseSensitive(json, key);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(obj != NULL, return NULL);
|
||||
APPSPAWN_CHECK(cJSON_IsString(obj), return NULL, "json is not string %{public}s %s", key, cJSON_Print(obj));
|
||||
return cJSON_GetStringValue(obj);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) inline bool GetBoolValueFromJsonObj(const cJSON *json, const char *key, bool def)
|
||||
{
|
||||
char *value = GetStringFromJsonObj(json, key);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(value != NULL, return def);
|
||||
|
||||
if (strcmp(value, "true") == 0 || strcmp(value, "ON") == 0 || strcmp(value, "True") == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) inline uint32_t GetIntValueFromJsonObj(const cJSON *json, const char *key, uint32_t def)
|
||||
{
|
||||
APPSPAWN_CHECK(json != NULL, return def, "Invalid json");
|
||||
APPSPAWN_CHECK(cJSON_IsObject(json), return def, "json is not object.");
|
||||
return cJSON_GetNumberValue(cJSON_GetObjectItemCaseSensitive(json, key));
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
namespace AppSpawnModuleTest {
|
||||
class AppSpawnTestCommander : public ThreadContext {
|
||||
public:
|
||||
AppSpawnTestCommander()
|
||||
{
|
||||
exit_ = 0;
|
||||
appSpawn_ = 1;
|
||||
dumpFlags = 0;
|
||||
msgType_ = 0;
|
||||
}
|
||||
~AppSpawnTestCommander()
|
||||
{
|
||||
if (ptyFd_ != -1) {
|
||||
(void)close(ptyFd_);
|
||||
ptyFd_ = -1;
|
||||
}
|
||||
if (appInfoConfig_) {
|
||||
cJSON_Delete(appInfoConfig_);
|
||||
appInfoConfig_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int ProcessArgs(int argc, char *const argv[]);
|
||||
int Run();
|
||||
|
||||
int CreateOtherMsg(AppSpawnReqMsgHandle &reqHandle, pid_t pid);
|
||||
int CreateMsg(AppSpawnReqMsgHandle &reqHandle, const char *defaultConfig);
|
||||
int StartSendMsg();
|
||||
int SendMsg();
|
||||
AppSpawnClientHandle GetClientHandle() { return clientHandle_; }
|
||||
private:
|
||||
std::vector<std::string> split(const std::string &str, const std::string &pattern);
|
||||
int InitPtyInterface();
|
||||
int ProcessInputCmd(std::string &cmd);
|
||||
int AddExtTlv(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle);
|
||||
int BuildMsgFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle);
|
||||
int AddBundleInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle);
|
||||
int GetDacInfoFromJson(const cJSON *appInfoConfig, AppDacInfo &info);
|
||||
int GetInternetPermissionInfoFromJson(const cJSON *appInfoConfig, AppSpawnMsgInternetInfo &info);
|
||||
int GetAccessTokenFromJson(const cJSON *appInfoConfig, AppSpawnMsgAccessToken &info);
|
||||
int AddDomainInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle);
|
||||
uint32_t GetUint32ArrayFromJson(const cJSON *json, const char *name, uint32_t dataArray[], uint32_t maxCount);
|
||||
static AppSpawnTestCommander *ConvertTo(const ThreadContext *context)
|
||||
{
|
||||
return const_cast<AppSpawnTestCommander *>(reinterpret_cast<const AppSpawnTestCommander *>(context));
|
||||
}
|
||||
static void TaskExecutorProc(ThreadTaskHandle handle, const ThreadContext *context);
|
||||
static void SendTaskFinish(ThreadTaskHandle handle, const ThreadContext *context);
|
||||
static void InputThread(ThreadTaskHandle handle, const ThreadContext *context);
|
||||
static void DumpThread(ThreadTaskHandle handle, const ThreadContext *context);
|
||||
|
||||
int ptyFd_{-1};
|
||||
uint32_t dumpFlags : 1;
|
||||
uint32_t exit_ : 1;
|
||||
uint32_t appSpawn_ : 1;
|
||||
uint32_t msgType_;
|
||||
pid_t terminatePid_;
|
||||
uint32_t threadCount_{1};
|
||||
std::string ptyName_{};
|
||||
std::string testFileName_{};
|
||||
std::string processName_{};
|
||||
cJSON *appInfoConfig_ { nullptr};
|
||||
AppSpawnClientHandle clientHandle_{nullptr};
|
||||
ThreadMgr threadMgr_{nullptr};
|
||||
ThreadTaskHandle inputHandle_{0};
|
||||
ThreadTaskHandle dumpHandle_{0};
|
||||
};
|
||||
} // namespace AppSpawnModuleTest
|
||||
} // namespace OHOS
|
||||
#endif // APPSPAWN_TEST_CMD_H
|
48
test/moduletest/appspawn_test_main.cpp
Executable file
48
test/moduletest/appspawn_test_main.cpp
Executable file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "appspawn.h"
|
||||
#include "appspawn_msg.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "appspawn_test_cmder.h"
|
||||
#include "command_lexer.h"
|
||||
#include "cJSON.h"
|
||||
#include "securec.h"
|
||||
#include "thread_manager.h"
|
||||
|
||||
int main(int argc, char *const argv[])
|
||||
{
|
||||
if (argc <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander;
|
||||
int ret = commander.ProcessArgs(argc, argv);
|
||||
if (ret == 0) {
|
||||
commander.Run();
|
||||
}
|
||||
return 0;
|
||||
}
|
37
test/moduletest/threadpool/BUILD.gn
Executable file
37
test/moduletest/threadpool/BUILD.gn
Executable file
@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//base/startup/appspawn/appspawn.gni")
|
||||
import("//build/ohos.gni")
|
||||
|
||||
config("appspawn_threadpool") {
|
||||
include_dirs = [ "." ]
|
||||
}
|
||||
|
||||
ohos_source_set("libappspawn_threadpool") {
|
||||
sources = [ "thread_manager.c" ]
|
||||
include_dirs = [
|
||||
".",
|
||||
"${appspawn_path}/util/include",
|
||||
"${appspawn_path}/common",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"c_utils:utils",
|
||||
"hilog:libhilog",
|
||||
"init:libbegetutil",
|
||||
]
|
||||
public_configs = [ ":appspawn_threadpool" ]
|
||||
subsystem_name = "${subsystem_name}"
|
||||
part_name = "${part_name}"
|
||||
}
|
544
test/moduletest/threadpool/thread_manager.c
Executable file
544
test/moduletest/threadpool/thread_manager.c
Executable file
@ -0,0 +1,544 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "thread_manager.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include "appspawn_utils.h"
|
||||
#include "list.h"
|
||||
|
||||
typedef struct {
|
||||
atomic_uint threadExit;
|
||||
uint32_t index;
|
||||
pthread_t threadId;
|
||||
} ThreadNode;
|
||||
|
||||
typedef struct {
|
||||
pthread_mutex_t mutex; // 保护执行队列
|
||||
pthread_cond_t cond; // 线程等待条件
|
||||
ListNode taskList; // 任务队列,任务还没有启动
|
||||
ListNode waitingTaskQueue; // 启动的任务,排队等待执行
|
||||
ListNode executingTaskQueue; // 正在执行
|
||||
ListNode executorQueue; // 执行节点,保存 TaskExecuteNode
|
||||
uint32_t executorCount;
|
||||
uint32_t maxThreadCount;
|
||||
uint32_t currTaskId;
|
||||
struct timespec lastAdjust;
|
||||
uint32_t validThreadCount;
|
||||
ThreadNode threadNode[1]; // 线程信息,控制线程的退出和结束
|
||||
} ThreadManager;
|
||||
|
||||
typedef struct {
|
||||
uint32_t taskId;
|
||||
ListNode node;
|
||||
ListNode executorList;
|
||||
uint32_t totalTask;
|
||||
atomic_uint taskFlags; // 表示任务是否被取消,各线程检查后决定任务线程是否结束
|
||||
atomic_uint finishTaskCount;
|
||||
const ThreadContext *context;
|
||||
TaskFinishProcessor finishProcess;
|
||||
pthread_mutex_t mutex; // 保护执行队列
|
||||
pthread_cond_t cond; // 同步执行时,等待确认
|
||||
} TaskNode;
|
||||
|
||||
typedef struct {
|
||||
ListNode node; // 保存sub task到对应的task,方便管理
|
||||
ListNode executeNode; // 等待处理的任务节点
|
||||
TaskNode *task;
|
||||
const ThreadContext *context;
|
||||
TaskExecutor executor;
|
||||
} TaskExecuteNode;
|
||||
|
||||
static ThreadManager *g_threadManager = NULL;
|
||||
|
||||
static void *ManagerThreadProc(void *args);
|
||||
static void *ThreadExecute(void *args);
|
||||
|
||||
static void SetCondAttr(pthread_cond_t *cond)
|
||||
{
|
||||
pthread_condattr_t attr;
|
||||
pthread_condattr_init(&attr);
|
||||
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||
pthread_cond_init(cond, &attr);
|
||||
pthread_condattr_destroy(&attr);
|
||||
}
|
||||
|
||||
static void ConvertToTimespec(int time, struct timespec *tm)
|
||||
{
|
||||
struct timespec start;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
uint64_t ns = time;
|
||||
ns *= APPSPAWN_MSEC_TO_NSEC;
|
||||
ns += start.tv_sec * APPSPAWN_SEC_TO_NSEC + start.tv_nsec;
|
||||
tm->tv_sec = ns / APPSPAWN_SEC_TO_NSEC;
|
||||
tm->tv_nsec = ns % APPSPAWN_SEC_TO_NSEC;
|
||||
}
|
||||
|
||||
static TaskExecuteNode *PopTaskExecutor(ThreadManager *mgr)
|
||||
{
|
||||
TaskExecuteNode *executor = NULL;
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
ListNode *node = mgr->executorQueue.next;
|
||||
if (node != &mgr->executorQueue) {
|
||||
OH_ListRemove(node);
|
||||
OH_ListInit(node);
|
||||
executor = ListEntry(node, TaskExecuteNode, executeNode);
|
||||
mgr->executorCount--;
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
return executor;
|
||||
}
|
||||
|
||||
static int AddExecutor(ThreadManager *mgr, const TaskNode *task)
|
||||
{
|
||||
ListNode *node = task->executorList.next;
|
||||
while (node != &task->executorList) {
|
||||
TaskExecuteNode *executor = ListEntry(node, TaskExecuteNode, node);
|
||||
APPSPAWN_LOGV("AddExecutor task: %{public}u executorCount: %{public}u executor: %{public}p %{public}u",
|
||||
task->taskId, mgr->executorCount, executor, executor->task->taskId);
|
||||
|
||||
// 插入尾部执行
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
OH_ListRemove(&executor->executeNode);
|
||||
OH_ListInit(&executor->executeNode);
|
||||
OH_ListAddTail(&mgr->executorQueue, &executor->executeNode);
|
||||
mgr->executorCount++;
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void RunExecutor(ThreadManager *mgr, ThreadNode *threadNode, uint32_t maxCount)
|
||||
{
|
||||
APPSPAWN_LOGV("RunExecutor in thread: %{public}d executorCount: %{public}u ",
|
||||
threadNode->index, mgr->executorCount);
|
||||
TaskExecuteNode *executor = PopTaskExecutor(mgr);
|
||||
uint32_t count = 0;
|
||||
while (executor != NULL && !threadNode->threadExit) {
|
||||
APPSPAWN_LOGV("RunExecutor task: %{public}u executor: %{public}p", executor->task->taskId, executor);
|
||||
atomic_fetch_add(&executor->task->finishTaskCount, 1);
|
||||
executor->executor(executor->task->taskId, executor->context);
|
||||
count++;
|
||||
if (count >= maxCount) {
|
||||
break;
|
||||
}
|
||||
executor = PopTaskExecutor(mgr);
|
||||
}
|
||||
APPSPAWN_LOGV("RunExecutor executorCount: %{public}u end", mgr->executorCount);
|
||||
}
|
||||
|
||||
static int TaskCompareTaskId(ListNode *node, void *data)
|
||||
{
|
||||
TaskNode *task = ListEntry(node, TaskNode, node);
|
||||
return task->taskId - *(uint32_t *)data;
|
||||
}
|
||||
|
||||
static TaskNode *GetTask(ThreadManager *mgr, ListNode *queue, uint32_t taskId)
|
||||
{
|
||||
ListNode *node = NULL;
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
node = OH_ListFind(queue, &taskId, TaskCompareTaskId);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
if (node == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return ListEntry(node, TaskNode, node);
|
||||
}
|
||||
|
||||
static void DeleteTask(TaskNode *task)
|
||||
{
|
||||
APPSPAWN_LOGV("DeleteTask task: %{public}u ", task->taskId);
|
||||
|
||||
if (!ListEmpty(task->node)) {
|
||||
return;
|
||||
}
|
||||
OH_ListRemoveAll(&task->executorList, NULL);
|
||||
pthread_cond_destroy(&task->cond);
|
||||
pthread_mutex_destroy(&task->mutex);
|
||||
free(task);
|
||||
}
|
||||
|
||||
static TaskNode *PopTask(ThreadManager *mgr, ListNode *queue)
|
||||
{
|
||||
TaskNode *task = NULL;
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
ListNode *node = queue->next;
|
||||
if (node != queue) {
|
||||
OH_ListRemove(node);
|
||||
OH_ListInit(node);
|
||||
task = ListEntry(node, TaskNode, node);
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
return task;
|
||||
}
|
||||
|
||||
static void PushTask(ThreadManager *mgr, TaskNode *task, ListNode *queue)
|
||||
{
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
OH_ListAddTail(queue, &task->node);
|
||||
pthread_cond_broadcast(&mgr->cond);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
}
|
||||
|
||||
static void SafeRemoveTask(ThreadManager *mgr, TaskNode *task)
|
||||
{
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
OH_ListRemove(&task->node);
|
||||
OH_ListInit(&task->node);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
|
||||
ListNode *node = task->executorList.next;
|
||||
while (node != &task->executorList) {
|
||||
OH_ListRemove(node);
|
||||
OH_ListInit(node);
|
||||
TaskExecuteNode *executor = ListEntry(node, TaskExecuteNode, node);
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
if (!ListEmpty(executor->executeNode)) {
|
||||
OH_ListRemove(&executor->executeNode);
|
||||
OH_ListInit(&executor->executeNode);
|
||||
mgr->executorCount--;
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
free(executor);
|
||||
|
||||
node = task->executorList.next;
|
||||
}
|
||||
}
|
||||
|
||||
static void ExecuteTask(ThreadManager *mgr)
|
||||
{
|
||||
TaskNode *task = PopTask(mgr, &mgr->waitingTaskQueue);
|
||||
if (task == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
APPSPAWN_LOGV("ExecuteTask task: %{public}u ", task->taskId);
|
||||
AddExecutor(mgr, task);
|
||||
PushTask(mgr, task, &mgr->executingTaskQueue);
|
||||
return;
|
||||
}
|
||||
|
||||
static void CheckTaskComplete(ThreadManager *mgr)
|
||||
{
|
||||
TaskNode *task = PopTask(mgr, &mgr->executingTaskQueue);
|
||||
if (task == NULL) {
|
||||
return;
|
||||
}
|
||||
if (task->totalTask <= atomic_load(&task->finishTaskCount)) {
|
||||
if (task->finishProcess != NULL) {
|
||||
task->finishProcess(task->taskId, task->context);
|
||||
DeleteTask(task);
|
||||
return;
|
||||
}
|
||||
pthread_mutex_lock(&task->mutex);
|
||||
pthread_cond_signal(&task->cond);
|
||||
pthread_mutex_unlock(&task->mutex);
|
||||
return;
|
||||
}
|
||||
PushTask(mgr, task, &mgr->executingTaskQueue);
|
||||
return;
|
||||
}
|
||||
|
||||
static void TaskQueueDestroyProc(ListNode *node)
|
||||
{
|
||||
OH_ListRemove(node);
|
||||
TaskNode *task = ListEntry(node, TaskNode, node);
|
||||
DeleteTask(task);
|
||||
}
|
||||
|
||||
int CreateThreadMgr(uint32_t maxThreadCount, ThreadMgr *instance)
|
||||
{
|
||||
if (g_threadManager != NULL) {
|
||||
*instance = (ThreadMgr)g_threadManager;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadManager *mgr = (ThreadManager *)malloc(sizeof(ThreadManager) + maxThreadCount * sizeof(ThreadNode));
|
||||
APPSPAWN_CHECK(mgr != NULL, return -1, "Failed to create thread manager");
|
||||
|
||||
mgr->executorCount = 0;
|
||||
mgr->currTaskId = 0;
|
||||
mgr->validThreadCount = 0;
|
||||
mgr->maxThreadCount = maxThreadCount;
|
||||
OH_ListInit(&mgr->taskList);
|
||||
OH_ListInit(&mgr->waitingTaskQueue);
|
||||
OH_ListInit(&mgr->executingTaskQueue);
|
||||
OH_ListInit(&mgr->executorQueue);
|
||||
pthread_mutex_init(&mgr->mutex, NULL);
|
||||
SetCondAttr(&mgr->cond);
|
||||
|
||||
for (uint32_t index = 0; index < maxThreadCount + 1; index++) {
|
||||
mgr->threadNode[index].index = index;
|
||||
mgr->threadNode[index].threadId = INVALID_THREAD_ID;
|
||||
atomic_init(&mgr->threadNode[index].threadExit, 0);
|
||||
}
|
||||
g_threadManager = mgr;
|
||||
int ret = pthread_create(&mgr->threadNode[0].threadId, NULL, ManagerThreadProc, (void *)&mgr->threadNode[0]);
|
||||
if (ret != 0) {
|
||||
APPSPAWN_LOGE("Failed to create thread for manager");
|
||||
g_threadManager = NULL;
|
||||
free(mgr);
|
||||
return -1;
|
||||
}
|
||||
*instance = (ThreadMgr)mgr;
|
||||
APPSPAWN_LOGV("Create thread manager success maxThreadCount: %{public}u", maxThreadCount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DestroyThreadMgr(ThreadMgr instance)
|
||||
{
|
||||
APPSPAWN_LOGV("DestroyThreadMgr");
|
||||
ThreadManager *mgr = (ThreadManager *)instance;
|
||||
APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager");
|
||||
|
||||
for (uint32_t index = 0; index < mgr->maxThreadCount + 1; index++) {
|
||||
if (mgr->threadNode[index].threadId != INVALID_THREAD_ID) {
|
||||
atomic_store(&mgr->threadNode[index].threadExit, 1);
|
||||
APPSPAWN_LOGV("DestroyThreadMgr index %{public}d %{public}d", index, mgr->threadNode[index].threadExit);
|
||||
}
|
||||
}
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
pthread_cond_broadcast(&mgr->cond);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
for (uint32_t index = 0; index < mgr->maxThreadCount + 1; index++) {
|
||||
if (mgr->threadNode[index].threadId != INVALID_THREAD_ID) {
|
||||
pthread_join(mgr->threadNode[index].threadId, NULL);
|
||||
APPSPAWN_LOGV("DestroyThreadMgr index %{public}d end", index);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
OH_ListRemoveAll(&mgr->taskList, TaskQueueDestroyProc);
|
||||
OH_ListRemoveAll(&mgr->waitingTaskQueue, TaskQueueDestroyProc);
|
||||
OH_ListRemoveAll(&mgr->executingTaskQueue, TaskQueueDestroyProc);
|
||||
OH_ListRemoveAll(&mgr->executorQueue, TaskQueueDestroyProc);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
|
||||
pthread_cond_destroy(&mgr->cond);
|
||||
pthread_mutex_destroy(&mgr->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ThreadMgrAddTask(ThreadMgr instance, ThreadTaskHandle *taskHandle)
|
||||
{
|
||||
ThreadManager *mgr = (ThreadManager *)instance;
|
||||
APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager");
|
||||
TaskNode *task = (TaskNode *)malloc(sizeof(TaskNode));
|
||||
APPSPAWN_CHECK(task != NULL, return -1, "Failed to create thread task");
|
||||
|
||||
task->context = NULL;
|
||||
task->finishProcess = NULL;
|
||||
task->totalTask = 0;
|
||||
atomic_init(&task->taskFlags, 0);
|
||||
atomic_init(&task->finishTaskCount, 0);
|
||||
OH_ListInit(&task->node);
|
||||
OH_ListInit(&task->executorList);
|
||||
pthread_mutex_init(&task->mutex, NULL);
|
||||
SetCondAttr(&task->cond);
|
||||
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
task->taskId = mgr->currTaskId++;
|
||||
OH_ListAddTail(&mgr->taskList, &task->node);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
*taskHandle = task->taskId;
|
||||
APPSPAWN_LOGV("Create thread task success task id: %{public}u", task->taskId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ThreadMgrAddExecutor(ThreadMgr instance,
|
||||
ThreadTaskHandle taskHandle, TaskExecutor executor, const ThreadContext *context)
|
||||
{
|
||||
ThreadManager *mgr = (ThreadManager *)instance;
|
||||
APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager");
|
||||
TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle);
|
||||
APPSPAWN_CHECK(task != NULL, return -1, "Invalid thread task %{public}u", taskHandle);
|
||||
|
||||
TaskExecuteNode *node = (TaskExecuteNode *)malloc(sizeof(TaskExecuteNode));
|
||||
APPSPAWN_CHECK(node != NULL, return -1, "Failed to create thread executor for task %{public}u", taskHandle);
|
||||
node->task = task;
|
||||
OH_ListInit(&node->node);
|
||||
OH_ListInit(&node->executeNode);
|
||||
node->context = context;
|
||||
node->executor = executor;
|
||||
task->totalTask++;
|
||||
OH_ListAddTail(&task->executorList, &node->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ThreadMgrCancelTask(ThreadMgr instance, ThreadTaskHandle taskHandle)
|
||||
{
|
||||
ThreadManager *mgr = (ThreadManager *)instance;
|
||||
APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager");
|
||||
TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle);
|
||||
if (task != NULL) {
|
||||
SafeRemoveTask(mgr, task);
|
||||
DeleteTask(task);
|
||||
return 0;
|
||||
}
|
||||
task = GetTask(mgr, &mgr->waitingTaskQueue, taskHandle);
|
||||
if (task != NULL) {
|
||||
SafeRemoveTask(mgr, task);
|
||||
DeleteTask(task);
|
||||
return 0;
|
||||
}
|
||||
task = GetTask(mgr, &mgr->executingTaskQueue, taskHandle);
|
||||
if (task != NULL) {
|
||||
SafeRemoveTask(mgr, task);
|
||||
DeleteTask(task);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TaskSyncExecute(ThreadMgr instance, ThreadTaskHandle taskHandle)
|
||||
{
|
||||
ThreadManager *mgr = (ThreadManager *)instance;
|
||||
APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager");
|
||||
TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle);
|
||||
APPSPAWN_CHECK(task != NULL, return -1, "Invalid thread task %{public}u", taskHandle);
|
||||
|
||||
pthread_mutex_lock(&task->mutex);
|
||||
OH_ListRemove(&task->node);
|
||||
OH_ListInit(&task->node);
|
||||
OH_ListAddTail(&mgr->waitingTaskQueue, &task->node);
|
||||
pthread_cond_broadcast(&mgr->cond);
|
||||
pthread_mutex_unlock(&task->mutex);
|
||||
APPSPAWN_LOGV("TaskSyncExecute task: %{public}u", task->taskId);
|
||||
struct timespec abstime;
|
||||
int ret = 0;
|
||||
do {
|
||||
ConvertToTimespec(60 * 1000, &abstime); // wait 60 * 1000 60s
|
||||
pthread_mutex_lock(&task->mutex);
|
||||
ret = pthread_cond_timedwait(&task->cond, &task->mutex, &abstime);
|
||||
pthread_mutex_unlock(&task->mutex);
|
||||
APPSPAWN_LOGV("TaskSyncExecute success task id: %{public}u ret: %{public}d", task->taskId, ret);
|
||||
} while (ret == ETIMEDOUT);
|
||||
|
||||
DeleteTask(task);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int TaskExecute(ThreadMgr instance,
|
||||
ThreadTaskHandle taskHandle, TaskFinishProcessor process, const ThreadContext *context)
|
||||
{
|
||||
ThreadManager *mgr = (ThreadManager *)instance;
|
||||
APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager");
|
||||
TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle);
|
||||
APPSPAWN_CHECK(task != NULL, return -1, "Invalid thread task %{public}u", taskHandle);
|
||||
|
||||
task->finishProcess = process;
|
||||
task->context = context;
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
OH_ListRemove(&task->node);
|
||||
OH_ListInit(&task->node);
|
||||
OH_ListAddTail(&mgr->waitingTaskQueue, &task->node);
|
||||
pthread_cond_broadcast(&mgr->cond);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
APPSPAWN_LOGV("TaskExecute task: %{public}u", task->taskId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CheckAndCreateNewThread(ThreadManager *mgr)
|
||||
{
|
||||
if (mgr->maxThreadCount <= mgr->validThreadCount) {
|
||||
return;
|
||||
}
|
||||
if (mgr->executorCount <= mgr->validThreadCount) {
|
||||
return;
|
||||
}
|
||||
APPSPAWN_LOGV("CheckAndCreateNewThread maxThreadCount: %{public}u validThreadCount: %{public}u %{public}u",
|
||||
mgr->maxThreadCount, mgr->validThreadCount, mgr->executorCount);
|
||||
|
||||
uint32_t totalThread = mgr->maxThreadCount;
|
||||
if (mgr->executorCount <= mgr->maxThreadCount) {
|
||||
totalThread = mgr->executorCount;
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < mgr->maxThreadCount + 1; index++) {
|
||||
if (mgr->threadNode[index].threadId != INVALID_THREAD_ID) {
|
||||
continue;
|
||||
}
|
||||
int ret = pthread_create(&mgr->threadNode[index].threadId,
|
||||
NULL, ThreadExecute, (void *)&(mgr->threadNode[index]));
|
||||
APPSPAWN_CHECK(ret == 0, return, "Failed to create thread for %{public}u", index);
|
||||
APPSPAWN_LOGV("Create thread success index: %{public}u", mgr->threadNode[index].index);
|
||||
mgr->validThreadCount++;
|
||||
if (mgr->validThreadCount >= totalThread) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void *ManagerThreadProc(void *args)
|
||||
{
|
||||
ThreadManager *mgr = g_threadManager;
|
||||
ThreadNode *threadNode = (ThreadNode *)args;
|
||||
struct timespec abstime;
|
||||
int ret = 0;
|
||||
while (!threadNode->threadExit) {
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
do {
|
||||
uint32_t timeout = 60 * 1000; // 60 * 1000 60s
|
||||
if (!ListEmpty(mgr->waitingTaskQueue)) {
|
||||
break;
|
||||
}
|
||||
if (!ListEmpty(mgr->executingTaskQueue)) {
|
||||
timeout = 500; // 500ms
|
||||
}
|
||||
ConvertToTimespec(timeout, &abstime);
|
||||
ret = pthread_cond_timedwait(&mgr->cond, &mgr->mutex, &abstime);
|
||||
if (!ListEmpty(mgr->executingTaskQueue) || ret == ETIMEDOUT) {
|
||||
break;
|
||||
}
|
||||
if (threadNode->threadExit) {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
|
||||
ExecuteTask(mgr);
|
||||
CheckAndCreateNewThread(mgr);
|
||||
|
||||
if (mgr->validThreadCount == 0) {
|
||||
RunExecutor(mgr, threadNode, 5); // 5 max thread
|
||||
}
|
||||
CheckTaskComplete(mgr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *ThreadExecute(void *args)
|
||||
{
|
||||
ThreadManager *mgr = g_threadManager;
|
||||
ThreadNode *threadNode = (ThreadNode *)args;
|
||||
struct timespec abstime;
|
||||
int ret = 0;
|
||||
while (!threadNode->threadExit) {
|
||||
pthread_mutex_lock(&mgr->mutex);
|
||||
while (ListEmpty(mgr->executorQueue) && !threadNode->threadExit) {
|
||||
ConvertToTimespec(60 * 1000, &abstime); // 60 * 1000 60s
|
||||
ret = pthread_cond_timedwait(&mgr->cond, &mgr->mutex, &abstime);
|
||||
}
|
||||
pthread_mutex_unlock(&mgr->mutex);
|
||||
APPSPAWN_LOGV("bbbb threadNode->threadExit %{public}d", threadNode->threadExit);
|
||||
RunExecutor(mgr, threadNode, 1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
47
test/moduletest/threadpool/thread_manager.h
Executable file
47
test/moduletest/threadpool/thread_manager.h
Executable file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APPSPAWN_MODULE_THREAD_MGR_H
|
||||
#define APPSPAWN_MODULE_THREAD_MGR_H
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define INVALID_THREAD_ID 0
|
||||
#define INVALID_TASK_HANDLE 0
|
||||
|
||||
typedef uint32_t ThreadTaskHandle;
|
||||
typedef void *ThreadMgr;
|
||||
typedef struct TagThreadContext ThreadContext;
|
||||
|
||||
typedef void (*TaskFinishProcessor)(ThreadTaskHandle handle, const ThreadContext *context);
|
||||
typedef void (*TaskExecutor)(ThreadTaskHandle handle, const ThreadContext *context);
|
||||
|
||||
int CreateThreadMgr(uint32_t maxThreadCount, ThreadMgr *mgr);
|
||||
int DestroyThreadMgr(ThreadMgr instance);
|
||||
int ThreadMgrAddTask(ThreadMgr mgr, ThreadTaskHandle *taskHandle);
|
||||
int ThreadMgrAddExecutor(ThreadMgr mgr,
|
||||
ThreadTaskHandle taskHandle, TaskExecutor executor, const ThreadContext *context);
|
||||
int ThreadMgrCancelTask(ThreadMgr mgr, ThreadTaskHandle taskHandle);
|
||||
int TaskSyncExecute(ThreadMgr mgr, ThreadTaskHandle taskHandle); // 同步执行
|
||||
int TaskExecute(ThreadMgr mgr, ThreadTaskHandle taskHandle, TaskFinishProcessor process, const ThreadContext *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // APPSPAWN_MODULE_THREAD_MGR_H
|
@ -36,13 +36,16 @@ config("utest_config") {
|
||||
}
|
||||
|
||||
include_dirs = [
|
||||
"${appspawn_path}",
|
||||
"${appspawn_path}/test/unittest",
|
||||
"${appspawn_path}/test/mock/include",
|
||||
"${appspawn_path}/common",
|
||||
"${appspawn_path}/standard",
|
||||
"${appspawn_path}/adapter",
|
||||
"${appspawn_path}/adapter/sysevent",
|
||||
"${appspawn_path}/modules/sandbox",
|
||||
"${appspawn_path}/interfaces/innerkits/include",
|
||||
"${appspawn_path}/interfaces/innerkits_new/include",
|
||||
"${appspawn_path}/util/include",
|
||||
"//commonlibrary/c_utils/base/include",
|
||||
"ability_runtime_kits_path/appkit/native/app/include",
|
||||
@ -98,6 +101,7 @@ if (!defined(ohos_lite)) {
|
||||
"${appspawn_path}/interfaces/innerkits/client/appspawn_socket.cpp",
|
||||
"${appspawn_path}/interfaces/innerkits/client/client_socket.cpp",
|
||||
"${appspawn_path}/interfaces/innerkits/src/appspawn_mount_permission.cpp",
|
||||
"${appspawn_path}/standard/appspawn_msgmgr.c",
|
||||
"${appspawn_path}/standard/appspawn_process.c",
|
||||
"${appspawn_path}/standard/appspawn_service.c",
|
||||
"${appspawn_path}/util/src/command_lexer.cpp",
|
||||
@ -128,6 +132,7 @@ if (!defined(ohos_lite)) {
|
||||
"ace_engine:ace_forward_compatibility",
|
||||
"bundle_framework:appexecfwk_base",
|
||||
"bundle_framework:appexecfwk_core",
|
||||
"cJSON:cjson",
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"eventhandler:libeventhandler",
|
||||
|
75
test/unittest/app_spawn_client_test/BUILD.gn
Executable file
75
test/unittest/app_spawn_client_test/BUILD.gn
Executable file
@ -0,0 +1,75 @@
|
||||
# Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//base/startup/appspawn/appspawn.gni")
|
||||
import("//build/test.gni")
|
||||
|
||||
ohos_unittest("AppSpawn_client_ut") {
|
||||
module_out_path = "${module_output_path}"
|
||||
deps = []
|
||||
defines = [
|
||||
"clone=CloneStub",
|
||||
"bind=BindStub",
|
||||
"listen=ListenStub",
|
||||
"lchown=LchownStub",
|
||||
"lchmod=LchmodStub",
|
||||
"getsockopt=GetsockoptStub",
|
||||
"setgroups=SetgroupsStub",
|
||||
"setresuid=SetresuidStub",
|
||||
"setresgid=SetresgidStub",
|
||||
"capset=CapsetStub",
|
||||
"dlopen=DlopenStub",
|
||||
"dlsym=DlsymStub",
|
||||
"dlclose=DlcloseStub",
|
||||
"waitpid=WaitpidStub",
|
||||
"HapContext=HapContextStub",
|
||||
"APPSPAWN_TEST",
|
||||
"OHOS_DEBUG",
|
||||
"GRAPHIC_PERMISSION_CHECK",
|
||||
]
|
||||
include_dirs = [
|
||||
"${appspawn_path}",
|
||||
"${appspawn_path}/test/unittest",
|
||||
"${appspawn_path}/common",
|
||||
"${appspawn_path}/standard",
|
||||
"${appspawn_path}/adapter",
|
||||
"${appspawn_path}/adapter/sysevent",
|
||||
"${appspawn_path}/modules/sandbox",
|
||||
"${appspawn_path}/interfaces/innerkits_new/include",
|
||||
"${appspawn_path}/interfaces/innerkits_new/client",
|
||||
"${appspawn_path}/interfaces/innerkits_new/permission",
|
||||
"${appspawn_path}/util/include",
|
||||
"${appspawn_path}/interfaces/innerkits_new/module_engine/include",
|
||||
"//third_party/json/include",
|
||||
]
|
||||
sources = [
|
||||
"${appspawn_path}/interfaces/innerkits_new/client/appspawn_client.c",
|
||||
"${appspawn_path}/interfaces/innerkits_new/client/appspawn_msg.c",
|
||||
"${appspawn_path}/interfaces/innerkits_new/permission/appspawn_mount_permission.c",
|
||||
"${appspawn_path}/modules/sandbox/appspawn_permission.c",
|
||||
"${appspawn_path}/util/src/appspawn_utils.c",
|
||||
]
|
||||
|
||||
sources += [ "${appspawn_path}/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp" ]
|
||||
|
||||
deps += [
|
||||
"//third_party/cJSON:cjson",
|
||||
"//third_party/selinux:libselinux",
|
||||
]
|
||||
external_deps = [
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"hilog:libhilog",
|
||||
"init:libbegetutil",
|
||||
]
|
||||
}
|
620
test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp
Executable file
620
test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp
Executable file
@ -0,0 +1,620 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include "appspawn.h"
|
||||
#include "appspawn_hook.h"
|
||||
#include "appspawn_mount_permission.h"
|
||||
#include "appspawn_service.h"
|
||||
#include "appspawn_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
using namespace testing;
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace OHOS {
|
||||
class AppSpawnInterfaceTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
void SetUp() {}
|
||||
void TearDown() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnClientInit
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_001, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, nullptr);
|
||||
EXPECT_EQ(APPSPAWN_ARG_INVALID, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_002, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, nullptr);
|
||||
EXPECT_EQ(APPSPAWN_ARG_INVALID, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_003, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnClientInit("test", nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_004, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnClientInit(nullptr, nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_005, TestSize.Level0)
|
||||
{
|
||||
AppSpawnClientHandle handle;
|
||||
int ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnClientDestroy
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Destroy_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnClientHandle handle;
|
||||
int ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnClientDestroy(handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Destroy_002, TestSize.Level0)
|
||||
{
|
||||
AppSpawnClientHandle handle;
|
||||
int ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, &handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnClientDestroy(handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Destroy_003, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnClientDestroy(nullptr);
|
||||
EXPECT_EQ(APPSPAWN_SYSTEM_ERROR, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnClientSendMsg
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Send_Msg_001, TestSize.Level0)
|
||||
{
|
||||
int ret = 0;
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
AppSpawnResult result = {};
|
||||
ret = AppSpawnClientSendMsg(nullptr, reqHandle, &result);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Send_Msg_002, TestSize.Level0)
|
||||
{
|
||||
int ret = 0;
|
||||
AppSpawnClientHandle clientHandle = nullptr;
|
||||
ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnResult result = {};
|
||||
ret = AppSpawnClientSendMsg(clientHandle, nullptr, &result);
|
||||
EXPECT_NE(0, ret);
|
||||
AppSpawnClientDestroy(clientHandle);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Send_Msg_003, TestSize.Level0)
|
||||
{
|
||||
int ret = 0;
|
||||
AppSpawnClientHandle clientHandle = nullptr;
|
||||
ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
ret = AppSpawnClientSendMsg(clientHandle, reqHandle, nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
AppSpawnClientDestroy(clientHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgCreate
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_002, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_GET_RENDER_TERMINATION_STATUS, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_003, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_SPAWN_NATIVE_PROCESS, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_004, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_DUMP, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_005, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MAX_TYPE_INVALID, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_006, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication::@#$%^&*()test", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_008, TestSize.Level0)
|
||||
{
|
||||
char buffer[255];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_009, TestSize.Level0)
|
||||
{
|
||||
char buffer[257];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_010, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, nullptr, &reqHandle);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_011, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_012, TestSize.Level0)
|
||||
{
|
||||
const char *testMsg = "testMsg";
|
||||
char *p = const_cast<char *>(testMsg);
|
||||
AppSpawnReqMsgHandle handle = reinterpret_cast<AppSpawnReqMsgHandle>(p);
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &handle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_013, TestSize.Level0)
|
||||
{
|
||||
char buffer[128];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_014, TestSize.Level0)
|
||||
{
|
||||
char buffer[129];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgFree
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Free_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgFree(nullptr);
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgSetBundleInfo
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, "com.ohos.myapplication");
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_002, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnReqMsgSetBundleInfo(nullptr, 0, "com.ohos.myapplication");
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_005, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 1, "com.ohos.myapplication");
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_ReqMsgSetBundleInfo_006, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, -1, "com.ohos.myapplication");
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_007, TestSize.Level0)
|
||||
{
|
||||
char buffer[255];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer);
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_008, TestSize.Level0)
|
||||
{
|
||||
char buffer[257];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer);
|
||||
EXPECT_NE(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_009, TestSize.Level0)
|
||||
{
|
||||
char buffer[128];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer);
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_010, TestSize.Level0)
|
||||
{
|
||||
char buffer[129];
|
||||
(void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer));
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer);
|
||||
EXPECT_EQ(0, ret);
|
||||
AppSpawnReqMsgFree(reqHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgSetAppDacInfo
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_App_Dac_001, TestSize.Level0)
|
||||
{
|
||||
AppDacInfo dacInfo;
|
||||
dacInfo.uid = 20010029; // 20010029 test data
|
||||
dacInfo.gid = 20010029; // 20010029 test data
|
||||
dacInfo.gidCount = 2; // 2 count
|
||||
dacInfo.gidTable[0] = 20010029; // 20010029 test data
|
||||
dacInfo.gidTable[1] = 20010029 + 1; // 20010029 test data
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_App_Dac_002, TestSize.Level0)
|
||||
{
|
||||
AppDacInfo dacInfo;
|
||||
dacInfo.uid = 20010029; // 20010029 test data
|
||||
dacInfo.gid = 20010029; // 20010029 test data
|
||||
dacInfo.gidCount = 2; // 2 count
|
||||
dacInfo.gidTable[0] = 20010029; // 20010029 test data
|
||||
dacInfo.gidTable[1] = 20010029 + 1; // 20010029 test data
|
||||
int ret = AppSpawnReqMsgSetAppDacInfo(nullptr, &dacInfo);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_App_Dac_004, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgSetAppDomainInfo
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Domain_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, "system_core");
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Domain_002, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, "system_core");
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Domain_004, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgSetAppInternetPermissionInfo
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Permission_Info_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppInternetPermissionInfo(reqHandle, 102, 102);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Permission_Info_002, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnReqMsgSetAppInternetPermissionInfo(nullptr, 102, 102);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgSetAppAccessToken
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Access_Token_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, 12345678);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Access_Token_002, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnReqMsgSetAppAccessToken(nullptr, 12345678);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgSetAppOwnerId
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Owner_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, "ohos.permission.FILE_ACCESS_MANAGER");
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Owner_002, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnReqMsgSetAppOwnerId(nullptr, "ohos.permission.FILE_ACCESS_MANAGER");
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Owner_004, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgAddPermission
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Permission_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgAddPermission(reqHandle, "ohos.permission.READ_IMAGEVIDEO");
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Permission_002, TestSize.Level0)
|
||||
{
|
||||
int ret = AppSpawnReqMsgAddPermission(nullptr, "ohos.permission.READ_IMAGEVIDEO");
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Permission_004, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgAddPermission(reqHandle, nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgAddExtInfo
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
const char *testData = "ssssssssssssss sssssssss ssssssss";
|
||||
ret = AppSpawnReqMsgAddExtInfo(reqHandle, "tlv-name-1",
|
||||
reinterpret_cast<uint8_t *>(const_cast<char *>(testData)), strlen(testData));
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_002, TestSize.Level0)
|
||||
{
|
||||
const char *testData = "ssssssssssssss sssssssss ssssssss";
|
||||
int ret = AppSpawnReqMsgAddExtInfo(nullptr, "tlv-name-1",
|
||||
reinterpret_cast<uint8_t *>(const_cast<char *>(testData)), strlen(testData));
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_004, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
const char *testData = "ssssssssssssss sssssssss ssssssss";
|
||||
ret = AppSpawnReqMsgAddExtInfo(reqHandle, nullptr,
|
||||
reinterpret_cast<uint8_t *>(const_cast<char *>(testData)), strlen(testData));
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_005, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
const char *testData = "ssssssssssssss sssssssss ssssssss";
|
||||
ret = AppSpawnReqMsgAddExtInfo(reqHandle, "tlv-name-1", nullptr, strlen(testData));
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:AppSpawnReqMsgAddStringInfo
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_001, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
const char *testData = "ssssssssssssss sssssssss ssssssss";
|
||||
ret = AppSpawnReqMsgAddStringInfo(reqHandle, "test", testData);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_002, TestSize.Level0)
|
||||
{
|
||||
const char *testData = "ssssssssssssss sssssssss ssssssss";
|
||||
int ret = AppSpawnReqMsgAddStringInfo(nullptr, "test", testData);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_004, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
const char *testData = "ssssssssssssss sssssssss ssssssss";
|
||||
ret = AppSpawnReqMsgAddStringInfo(reqHandle, nullptr, testData);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_005, TestSize.Level0)
|
||||
{
|
||||
AppSpawnReqMsgHandle reqHandle = nullptr;
|
||||
int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle);
|
||||
EXPECT_EQ(0, ret);
|
||||
ret = AppSpawnReqMsgAddStringInfo(reqHandle, "test", nullptr);
|
||||
EXPECT_NE(0, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测试接口:GetPermissionByIndex
|
||||
*
|
||||
*/
|
||||
HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_GetPermissionByIndex_005, TestSize.Level0)
|
||||
{
|
||||
int32_t maxIndex = GetMaxPermissionIndex();
|
||||
for (int i = 0; i < maxIndex; i++) {
|
||||
EXPECT_NE(GetPermissionByIndex(i), nullptr);
|
||||
}
|
||||
|
||||
EXPECT_EQ(GetPermissionByIndex(maxIndex), nullptr);
|
||||
EXPECT_EQ(GetPermissionByIndex(-1), nullptr);
|
||||
|
||||
int32_t index = GetPermissionIndex("ohos.permission.ACCESS_BUNDLE_DIR");
|
||||
int ret = index >= 0 && index < maxIndex ? 0 : -1;
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
}
|
@ -249,7 +249,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_10, TestSize.Level0)
|
||||
HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_012, TestSize.Level0)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_012 start";
|
||||
AppSpawnContent_ appContent = {0};
|
||||
AppSpawnContent appContent = {0};
|
||||
AppSpawnClient appClient = {0};
|
||||
pid_t pid = -1;
|
||||
AppSandboxArg *sandboxArg = (AppSandboxArg *)malloc(sizeof(AppSandboxArg));
|
||||
|
@ -50,8 +50,6 @@ using nlohmann::json;
|
||||
extern "C" {
|
||||
#endif
|
||||
TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskHandle server, uint32_t flags);
|
||||
bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *appProperty,
|
||||
const uint8_t *buffer, uint32_t buffLen);
|
||||
void AddAppInfo(pid_t pid, const char *processName, AppOperateType code);
|
||||
void SignalHandler(const struct signalfd_siginfo *siginfo);
|
||||
int GetCgroupPath(const AppSpawnAppInfo *appInfo, char *buffer, uint32_t buffLen);
|
||||
@ -59,6 +57,95 @@ int GetCgroupPath(const AppSpawnAppInfo *appInfo, char *buffer, uint32_t buffLen
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ReceiveRequestDataToExtraInfo(const TaskHandle taskHandle, AppSpawnClientExt *client,
|
||||
const uint8_t *buffer, uint32_t buffLen)
|
||||
{
|
||||
if (client->property.extraInfo.totalLength) {
|
||||
ExtraInfo *extraInfo = &client->property.extraInfo;
|
||||
if (extraInfo->savedLength == 0) {
|
||||
extraInfo->data = (char *)malloc(extraInfo->totalLength);
|
||||
APPSPAWN_CHECK(extraInfo->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: malloc extraInfo failed %{public}u", extraInfo->totalLength);
|
||||
}
|
||||
|
||||
uint32_t saved = extraInfo->savedLength;
|
||||
uint32_t total = extraInfo->totalLength;
|
||||
char *data = extraInfo->data;
|
||||
|
||||
APPSPAWN_LOGI("Receiving extraInfo: (%{public}u saved + %{public}u incoming) / %{public}u total",
|
||||
saved, buffLen, total);
|
||||
|
||||
APPSPAWN_CHECK((total - saved) >= buffLen, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: too many data for extraInfo %{public}u ", buffLen);
|
||||
|
||||
int ret = memcpy_s(data + saved, buffLen, buffer, buffLen);
|
||||
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: memcpy extraInfo failed");
|
||||
|
||||
extraInfo->savedLength += buffLen;
|
||||
if (extraInfo->savedLength < extraInfo->totalLength) {
|
||||
return false;
|
||||
}
|
||||
extraInfo->data[extraInfo->totalLength - 1] = 0;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int CheckRequestMsgValid(AppSpawnClientExt *client)
|
||||
{
|
||||
if (client->property.extraInfo.totalLength >= EXTRAINFO_TOTAL_LENGTH_MAX) {
|
||||
APPSPAWN_LOGE("extrainfo total length invalid,len: %{public}d", client->property.extraInfo.totalLength);
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < APP_LEN_PROC_NAME; i++) {
|
||||
if (client->property.processName[i] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
APPSPAWN_LOGE("processname invalid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *client,
|
||||
const uint8_t *buffer, uint32_t buffLen)
|
||||
{
|
||||
APPSPAWN_CHECK(buffer != NULL && buffLen > 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: Invalid buff, bufferLen:%{public}d", buffLen);
|
||||
|
||||
// 1. receive AppParamter
|
||||
if (client->property.extraInfo.totalLength == 0) {
|
||||
APPSPAWN_CHECK(buffLen >= sizeof(client->property), LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: Invalid buffLen %{public}u", buffLen);
|
||||
|
||||
int ret = memcpy_s(&client->property, sizeof(client->property), buffer, sizeof(client->property));
|
||||
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "ReceiveRequestData: memcpy failed %{public}d:%{public}u", ret, buffLen);
|
||||
|
||||
// reset extraInfo
|
||||
client->property.extraInfo.savedLength = 0;
|
||||
client->property.extraInfo.data = NULL;
|
||||
|
||||
// update buffer
|
||||
buffer += sizeof(client->property);
|
||||
buffLen -= sizeof(client->property);
|
||||
ret = CheckRequestMsgValid(client);
|
||||
APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
return false, "Invalid request msg");
|
||||
}
|
||||
|
||||
// 2. check whether extraInfo exist
|
||||
if (client->property.extraInfo.totalLength == 0) { // no extraInfo
|
||||
APPSPAWN_LOGV("ReceiveRequestData: no extraInfo");
|
||||
return true;
|
||||
} else if (buffLen == 0) {
|
||||
APPSPAWN_LOGV("ReceiveRequestData: waiting for extraInfo");
|
||||
return false;
|
||||
}
|
||||
return ReceiveRequestDataToExtraInfo(taskHandle, client, buffer, buffLen);
|
||||
}
|
||||
|
||||
static int MakeDir(const char *dir, mode_t mode)
|
||||
{
|
||||
int rc = -1;
|
||||
@ -152,7 +239,7 @@ void AppSpawnStandardTest::SetUp()
|
||||
void AppSpawnStandardTest::TearDown()
|
||||
{}
|
||||
|
||||
int32_t TestSetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int32_t TestSetAppSandboxProperty(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -590,7 +677,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0)
|
||||
AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", (char*)longProcName.c_str(), longProcNameLen, 1);
|
||||
content->loadExtendLib = LoadExtendLib;
|
||||
content->runChildProcessor = RunChildProcessor;
|
||||
int ret = DoStartApp((AppSpawnContent_*)content, &clientExt->client, (char*)"", 0);
|
||||
int ret = DoStartApp((AppSpawnContent*)content, &clientExt->client, (char*)"", 0);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
if (strcpy_s(clientExt->property.bundleName, APP_LEN_BUNDLE_NAME, "moduleTestProcessName") != 0) {
|
||||
@ -598,12 +685,12 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0)
|
||||
}
|
||||
ret = SetAppSandboxProperty(nullptr, nullptr);
|
||||
EXPECT_NE(ret, 0);
|
||||
ret = SetAppSandboxProperty((AppSpawnContent_*)content, &clientExt->client);
|
||||
ret = SetAppSandboxProperty((AppSpawnContent*)content, &clientExt->client);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
// APP_NO_SANDBOX
|
||||
clientExt->property.flags |= APP_NO_SANDBOX;
|
||||
ret = SetAppSandboxProperty((AppSpawnContent_*)content, &clientExt->client);
|
||||
ret = SetAppSandboxProperty((AppSpawnContent*)content, &clientExt->client);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
clientExt->property.flags &= ~APP_NO_SANDBOX;
|
||||
@ -614,7 +701,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0)
|
||||
\"versions\":[\"v10001\", \"v10002\"] \
|
||||
}");
|
||||
clientExt->property.extraInfo.totalLength = strlen(clientExt->property.extraInfo.data);
|
||||
ret = SetAppSandboxProperty((AppSpawnContent_*)content, &clientExt->client);
|
||||
ret = SetAppSandboxProperty((AppSpawnContent*)content, &clientExt->client);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
free(content);
|
||||
|
@ -47,10 +47,9 @@ if (!defined(ohos_lite)) {
|
||||
|
||||
defines = [ "APPSPAWN_TEST" ]
|
||||
|
||||
deps = [ "//third_party/cJSON:cjson" ]
|
||||
|
||||
external_deps = [
|
||||
"bounds_checking_function:libsec_shared",
|
||||
"cJSON:cjson",
|
||||
"hilog:libhilog",
|
||||
"zlib:shared_libz",
|
||||
]
|
||||
|
121
util/include/appspawn_utils.h
Executable file
121
util/include/appspawn_utils.h
Executable file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef APPSPAWN_UTILS_H
|
||||
#define APPSPAWN_UTILS_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "appspawn_server.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifndef APPSPAWN_TEST
|
||||
#define APPSPAWN_STATIC static
|
||||
#else
|
||||
#define APPSPAWN_STATIC
|
||||
#endif
|
||||
|
||||
#ifndef APPSPAWN_BASE_DIR
|
||||
#define APPSPAWN_BASE_DIR ""
|
||||
#endif
|
||||
#if defined(__MUSL__)
|
||||
#define APPSPAWN_SOCKET_DIR APPSPAWN_BASE_DIR "/dev/unix/socket/"
|
||||
#else
|
||||
#define APPSPAWN_SOCKET_DIR APPSPAWN_BASE_DIR "/dev/socket/"
|
||||
#endif
|
||||
|
||||
#define APPSPAWN_CHECK_EXIT "AppSpawnCheckUnexpectedExitCall"
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
#define APP_COLD_START 0x01
|
||||
#define APP_ASAN_DETECTOR 0x02
|
||||
#define APP_DEVELOPER_MODE 0x04
|
||||
|
||||
#define MAX_LEN_SHORT_NAME 16
|
||||
#define DEFAULT_UMASK 0002
|
||||
#define UID_BASE 200000 // 20010029
|
||||
#define DEFAULT_DIR_MODE 0711
|
||||
#define USER_ID_BUFFER_SIZE 32
|
||||
|
||||
#define APPSPAWN_SEC_TO_NSEC 1000000000
|
||||
#define APPSPAWN_MSEC_TO_NSEC 1000000
|
||||
#define APPSPAWN_USEC_TO_NSEC 1000
|
||||
#define APPSPAWN_SEC_TO_MSEC 1000
|
||||
|
||||
#define MAX_JSON_FILE_LEN 102400
|
||||
|
||||
#define CHECK_FLAGS_BY_INDEX(flags, index) ((((flags) >> (index)) & 0x1) == 0x1)
|
||||
#ifndef ARRAY_LENGTH
|
||||
#define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
#define INVALID_PERMISSION_INDEX (-1)
|
||||
|
||||
typedef enum {
|
||||
APPSPAWN_OK = 0,
|
||||
APPSPAWN_SYSTEM_ERROR = 0xD000000,
|
||||
APPSPAWN_ARG_INVALID,
|
||||
APPSPAWN_MSG_INVALID,
|
||||
APPSPAWN_MSG_TOO_LONG,
|
||||
APPSPAWN_TLV_NOT_SUPPORT,
|
||||
APPSPAWN_TLV_NONE,
|
||||
APPSPAWN_SANDBOX_NONE,
|
||||
APPSPAWN_SANDBOX_LOAD_FAIL,
|
||||
APPSPAWN_SANDBOX_INVALID,
|
||||
APPSPAWN_SANDBOX_MOUNT_FAIL,
|
||||
APPSPAWN_SPAWN_TIMEOUT,
|
||||
APPSPAWN_CHILD_CRASH,
|
||||
APPSPAWN_NATIVE_NOT_SUPPORT,
|
||||
APPSPAWN_ACCESS_TOKEN_INVALID,
|
||||
APPSPAWN_PERMISSION_NOT_SUPPORT,
|
||||
APPSPAWN_BUFFER_NOT_ENOUGH,
|
||||
APPSPAWN_TIMEOUT,
|
||||
APPSPAWN_FORK_FAIL,
|
||||
APPSPAWN_NODE_EXIST,
|
||||
} AppSpawnErrorCode;
|
||||
|
||||
typedef struct cJSON cJSON;
|
||||
typedef struct TagParseJsonContext ParseJsonContext;
|
||||
typedef int (*ParseConfig)(const cJSON *root, ParseJsonContext *context);
|
||||
int ParseJsonConfig(const char *path, const char *fileName, ParseConfig parseConfig, ParseJsonContext *context);
|
||||
cJSON *GetJsonObjFromFile(const char *jsonPath);
|
||||
|
||||
uint8_t *Base64Decode(const char *data, uint32_t dataLen, uint32_t *outLen);
|
||||
char *Base64Encode(const uint8_t *data, uint32_t len);
|
||||
void AppSpawnDump(const char *fmt, ...);
|
||||
void SetDumpToStream(FILE *stream);
|
||||
|
||||
typedef int (*SplitStringHandle)(const char *str, void *context);
|
||||
int32_t StringSplit(const char *str, const char *separator, void *context, SplitStringHandle handle);
|
||||
char *GetLastStr(const char *str, const char *dst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // APPSPAWN_UTILS_H
|
@ -24,7 +24,7 @@
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
int32_t SetEnvInfo(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int32_t SetEnvInfo(struct AppSpawnContent *content, AppSpawnClient *client);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
259
util/src/appspawn_utils.c
Normal file
259
util/src/appspawn_utils.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "appspawn_utils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "appspawn_hook.h"
|
||||
#include "cJSON.h"
|
||||
#include "config_policy_utils.h"
|
||||
#include "parameter.h"
|
||||
#include "securec.h"
|
||||
|
||||
int MakeDirRec(const char *path, mode_t mode, int lastPath)
|
||||
{
|
||||
if (path == NULL || *path == '\0') {
|
||||
return -1;
|
||||
}
|
||||
APPSPAWN_CHECK(path != NULL && *path != '\0', return -1, "Invalid path to create");
|
||||
char buffer[PATH_MAX] = {0};
|
||||
const char slash = '/';
|
||||
const char *p = path;
|
||||
char *curPos = strchr(path, slash);
|
||||
while (curPos != NULL) {
|
||||
int len = curPos - p;
|
||||
p = curPos + 1;
|
||||
if (len == 0) {
|
||||
curPos = strchr(p, slash);
|
||||
continue;
|
||||
}
|
||||
int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1);
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy path");
|
||||
ret = mkdir(buffer, mode);
|
||||
if (ret == -1 && errno != EEXIST) {
|
||||
return errno;
|
||||
}
|
||||
curPos = strchr(p, slash);
|
||||
}
|
||||
if (lastPath) {
|
||||
if (mkdir(path, mode) == -1 && errno != EEXIST) {
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CheckDirRecursive(const char *path)
|
||||
{
|
||||
char buffer[PATH_MAX] = {0};
|
||||
const char slash = '/';
|
||||
const char *p = path;
|
||||
char *curPos = strchr(path, slash);
|
||||
while (curPos != NULL) {
|
||||
int len = curPos - p;
|
||||
p = curPos + 1;
|
||||
if (len == 0) {
|
||||
curPos = strchr(p, slash);
|
||||
continue;
|
||||
}
|
||||
int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1);
|
||||
APPSPAWN_CHECK(ret == 0, return, "Failed to copy path");
|
||||
ret = access(buffer, F_OK);
|
||||
APPSPAWN_CHECK(ret == 0, return, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
|
||||
curPos = strchr(p, slash);
|
||||
}
|
||||
int ret = access(path, F_OK);
|
||||
APPSPAWN_CHECK(ret == 0, return, "Dir not exit %{public}s errno: %{public}d", buffer, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
int SandboxMountPath(const MountArg *arg)
|
||||
{
|
||||
APPSPAWN_CHECK(arg != NULL && arg->originPath != NULL && arg->destinationPath != NULL,
|
||||
return APPSPAWN_ARG_INVALID, "Invalid arg ");
|
||||
int ret = mount(arg->originPath, arg->destinationPath, arg->fsType, arg->mountFlags, arg->options);
|
||||
if (ret != 0) {
|
||||
if (arg->originPath != NULL && strstr(arg->originPath, "/data/app/el2/") != NULL) {
|
||||
CheckDirRecursive(arg->originPath);
|
||||
}
|
||||
APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
|
||||
errno, arg->originPath, arg->destinationPath);
|
||||
return errno;
|
||||
}
|
||||
ret = mount(NULL, arg->destinationPath, NULL, arg->mountSharedFlag, NULL);
|
||||
if (ret != 0) {
|
||||
APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s",
|
||||
errno, arg->originPath, arg->destinationPath);
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TrimTail(char *buffer, uint32_t maxLen)
|
||||
{
|
||||
int32_t index = maxLen - 1;
|
||||
while (index > 0) {
|
||||
if (isspace(buffer[index])) {
|
||||
buffer[index] = '\0';
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t StringSplit(const char *str, const char *separator, void *context, SplitStringHandle handle)
|
||||
{
|
||||
APPSPAWN_CHECK(str != NULL && handle != NULL && separator != NULL, return APPSPAWN_ARG_INVALID, "Invalid arg ");
|
||||
|
||||
int ret = 0;
|
||||
char *tmp = (char *)str;
|
||||
char buffer[PATH_MAX] = {0};
|
||||
uint32_t len = strlen(separator);
|
||||
uint32_t index = 0;
|
||||
while ((*tmp != '\0') && (index < (uint32_t)sizeof(buffer))) {
|
||||
if (index == 0 && isspace(*tmp)) {
|
||||
tmp++;
|
||||
continue;
|
||||
}
|
||||
if (strncmp(tmp, separator, len) != 0) {
|
||||
buffer[index++] = *tmp;
|
||||
tmp++;
|
||||
continue;
|
||||
}
|
||||
tmp += len;
|
||||
buffer[index] = '\0';
|
||||
TrimTail(buffer, index);
|
||||
index = 0;
|
||||
|
||||
int result = handle(buffer, context);
|
||||
if (result != 0) {
|
||||
ret = result;
|
||||
}
|
||||
}
|
||||
if (index > 0) {
|
||||
buffer[index] = '\0';
|
||||
TrimTail(buffer, index);
|
||||
index = 0;
|
||||
int result = handle(buffer, context);
|
||||
if (result != 0) {
|
||||
ret = result;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *GetLastStr(const char *str, const char *dst)
|
||||
{
|
||||
char *end = (char *)str + strlen(str);
|
||||
size_t len = strlen(dst);
|
||||
while (end != str) {
|
||||
if (isspace(*end)) { // clear space
|
||||
*end = '\0';
|
||||
end--;
|
||||
continue;
|
||||
}
|
||||
if (strncmp(end, dst, len) == 0) {
|
||||
return end;
|
||||
}
|
||||
end--;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *ReadFile(const char *fileName)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
FILE *fd = NULL;
|
||||
do {
|
||||
struct stat fileStat;
|
||||
if (stat(fileName, &fileStat) != 0 ||
|
||||
fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) {
|
||||
return NULL;
|
||||
}
|
||||
APPSPAWN_LOGI("LoadAppSandboxConfig %{public}s size %{public}u", fileName, (uint32_t)fileStat.st_size);
|
||||
fd = fopen(fileName, "r");
|
||||
APPSPAWN_CHECK(fd != NULL, break, "Failed to open file %{public}s", fileName);
|
||||
|
||||
buffer = (char*)malloc((size_t)(fileStat.st_size + 1));
|
||||
APPSPAWN_CHECK(buffer != NULL, break, "Failed to alloc mem %{public}s", fileName);
|
||||
|
||||
int ret = fread(buffer, fileStat.st_size, 1, fd);
|
||||
APPSPAWN_CHECK(ret == 1, break, "Failed to read %{public}s to buffer", fileName);
|
||||
buffer[fileStat.st_size] = '\0';
|
||||
(void)fclose(fd);
|
||||
return buffer;
|
||||
} while (0);
|
||||
|
||||
if (fd != NULL) {
|
||||
(void)fclose(fd);
|
||||
fd = NULL;
|
||||
}
|
||||
if (buffer != NULL) {
|
||||
free(buffer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cJSON *GetJsonObjFromFile(const char *jsonPath)
|
||||
{
|
||||
APPSPAWN_CHECK_ONLY_EXPER(jsonPath != NULL && *jsonPath != '\0', NULL);
|
||||
char *buffer = ReadFile(jsonPath);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(buffer != NULL, NULL);
|
||||
return cJSON_Parse(buffer);
|
||||
}
|
||||
|
||||
int ParseJsonConfig(const char *basePath, const char *fileName, ParseConfig parseConfig, ParseJsonContext *context)
|
||||
{
|
||||
// load sandbox config
|
||||
char path[PATH_MAX] = {};
|
||||
CfgFiles *files = GetCfgFiles(basePath);
|
||||
if (files == NULL) {
|
||||
return APPSPAWN_SANDBOX_NONE;
|
||||
}
|
||||
int ret = 0;
|
||||
for (int i = 0; i < MAX_CFG_POLICY_DIRS_CNT; ++i) {
|
||||
if (files->paths[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
int len = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", files->paths[i], fileName);
|
||||
APPSPAWN_CHECK(len > 0 && (size_t)len < sizeof(path), ret = APPSPAWN_SANDBOX_INVALID;
|
||||
continue, "Failed to format sandbox config file name %{public}s %{public}s", files->paths[i], fileName);
|
||||
cJSON *root = GetJsonObjFromFile(path);
|
||||
APPSPAWN_CHECK(root != NULL, ret = APPSPAWN_SANDBOX_INVALID;
|
||||
continue, "Failed to load app data sandbox config %{public}s", path);
|
||||
int rc = parseConfig(root, context);
|
||||
if (rc != 0) {
|
||||
ret = rc;
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
FreeCfgFiles(files);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static FILE *g_dumpToStream = NULL;
|
||||
void SetDumpToStream(FILE *stream)
|
||||
{
|
||||
g_dumpToStream = stream;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
|
||||
const std::string APPENVLIST_TYPE = "|AppEnv|";
|
||||
|
||||
int32_t SetEnvInfo(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int32_t SetEnvInfo(struct AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
int ret = 0;
|
||||
OHOS::AppSpawn::ClientSocket::AppProperty *appProperty = &reinterpret_cast<AppSpawnClientExt *>(client)->property;
|
||||
|
@ -13,13 +13,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "json_utils.h"
|
||||
#include "appspawn_server.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include "appspawn_server.h"
|
||||
#include "cJSON.h"
|
||||
#include "config_policy_utils.h"
|
||||
#include "json_utils.h"
|
||||
#include "appspawn_utils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace OHOS;
|
||||
|
||||
@ -55,4 +58,55 @@ bool JsonUtils::GetStringFromJson(const nlohmann::json &json, const std::string
|
||||
}
|
||||
}
|
||||
} // namespace AppSpawn
|
||||
} // namespace OHOS
|
||||
} // namespace OHOS
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
cJSON *GetJsonObjFromFile(const char *jsonPath)
|
||||
{
|
||||
std::ifstream jsonFileStream;
|
||||
jsonFileStream.open(jsonPath, std::ios::in);
|
||||
APPSPAWN_CHECK_ONLY_EXPER(jsonFileStream.is_open(), return nullptr);
|
||||
std::ostringstream buf;
|
||||
char ch;
|
||||
while (buf && jsonFileStream.get(ch)) {
|
||||
buf.put(ch);
|
||||
}
|
||||
jsonFileStream.close();
|
||||
return cJSON_Parse(buf.str().c_str());
|
||||
}
|
||||
|
||||
int ParseJsonConfig(const char *basePath, const char *fileName, ParseConfig parseConfig, ParseJsonContext *context)
|
||||
{
|
||||
// load sandbox config
|
||||
CfgFiles *files = GetCfgFiles(basePath);
|
||||
if (files == nullptr) {
|
||||
return APPSPAWN_SANDBOX_NONE;
|
||||
}
|
||||
int ret = 0;
|
||||
for (int i = 0; i < MAX_CFG_POLICY_DIRS_CNT; ++i) {
|
||||
if (files->paths[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
std::string path = files->paths[i];
|
||||
path += fileName;
|
||||
APPSPAWN_LOGI("LoadAppSandboxConfig %{public}s", path.c_str());
|
||||
|
||||
cJSON *root = GetJsonObjFromFile(path.c_str());
|
||||
APPSPAWN_CHECK(root != nullptr, ret = APPSPAWN_SANDBOX_INVALID;
|
||||
continue, "Failed to load app data sandbox config %{public}s", path.c_str());
|
||||
int rc = parseConfig(root, context);
|
||||
if (rc != 0) {
|
||||
ret = rc;
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
FreeCfgFiles(files);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
Loading…
Reference in New Issue
Block a user