169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License.
569570cc8Sopenharmony_ci * You may obtain a copy of the License at
669570cc8Sopenharmony_ci *
769570cc8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
869570cc8Sopenharmony_ci *
969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and
1369570cc8Sopenharmony_ci * limitations under the License.
1469570cc8Sopenharmony_ci */
1569570cc8Sopenharmony_ci
1669570cc8Sopenharmony_ci#include "appspawn_message.h"
1769570cc8Sopenharmony_ci#include "appspawn_server.h"
1869570cc8Sopenharmony_ci#include <errno.h>
1969570cc8Sopenharmony_ci#include <time.h>
2069570cc8Sopenharmony_ci
2169570cc8Sopenharmony_ci#include "iproxy_server.h"
2269570cc8Sopenharmony_ci#include "iunknown.h"
2369570cc8Sopenharmony_ci#include "ipc_skeleton.h"
2469570cc8Sopenharmony_ci#include "message.h"
2569570cc8Sopenharmony_ci#include "ohos_errno.h"
2669570cc8Sopenharmony_ci#include "ohos_init.h"
2769570cc8Sopenharmony_ci#include "samgr_lite.h"
2869570cc8Sopenharmony_ci#include "service.h"
2969570cc8Sopenharmony_ci#include "securec.h"
3069570cc8Sopenharmony_ci
3169570cc8Sopenharmony_cistatic const int INVALID_PID = -1;
3269570cc8Sopenharmony_cistatic const int CLIENT_ID = 100;
3369570cc8Sopenharmony_ci
3469570cc8Sopenharmony_ci#ifdef OHOS_DEBUG
3569570cc8Sopenharmony_ciuint64_t DiffTime(const struct timespec *startTime, const struct timespec *endTime)
3669570cc8Sopenharmony_ci{
3769570cc8Sopenharmony_ci    uint64_t diff = (uint64_t)((endTime->tv_sec - startTime->tv_sec) * 1000000);  // 1000000 s-us
3869570cc8Sopenharmony_ci    if (endTime->tv_nsec > startTime->tv_nsec) {
3969570cc8Sopenharmony_ci        diff += (endTime->tv_nsec - startTime->tv_nsec) / 1000;  // 1000 ns - us
4069570cc8Sopenharmony_ci    } else {
4169570cc8Sopenharmony_ci        diff -= (startTime->tv_nsec - endTime->tv_nsec) / 1000;  // 1000 ns - us
4269570cc8Sopenharmony_ci    }
4369570cc8Sopenharmony_ci    return diff;
4469570cc8Sopenharmony_ci}
4569570cc8Sopenharmony_ci#endif
4669570cc8Sopenharmony_ci
4769570cc8Sopenharmony_citypedef struct AppSpawnFeatureApi {
4869570cc8Sopenharmony_ci    INHERIT_SERVER_IPROXY;
4969570cc8Sopenharmony_ci} AppSpawnFeatureApi;
5069570cc8Sopenharmony_ci
5169570cc8Sopenharmony_citypedef struct AppSpawnService {
5269570cc8Sopenharmony_ci    INHERIT_SERVICE;
5369570cc8Sopenharmony_ci    INHERIT_IUNKNOWNENTRY(AppSpawnFeatureApi);
5469570cc8Sopenharmony_ci    Identity identity;
5569570cc8Sopenharmony_ci} AppSpawnService;
5669570cc8Sopenharmony_ci
5769570cc8Sopenharmony_cistatic const char *GetName(Service *service)
5869570cc8Sopenharmony_ci{
5969570cc8Sopenharmony_ci    UNUSED(service);
6069570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] get service name %s.", APPSPAWN_SERVICE_NAME);
6169570cc8Sopenharmony_ci    return APPSPAWN_SERVICE_NAME;
6269570cc8Sopenharmony_ci}
6369570cc8Sopenharmony_ci
6469570cc8Sopenharmony_cistatic BOOL Initialize(Service *service, Identity identity)
6569570cc8Sopenharmony_ci{
6669570cc8Sopenharmony_ci    if (service == NULL) {
6769570cc8Sopenharmony_ci        APPSPAWN_LOGE("[appspawn] initialize, service NULL!");
6869570cc8Sopenharmony_ci        return FALSE;
6969570cc8Sopenharmony_ci    }
7069570cc8Sopenharmony_ci
7169570cc8Sopenharmony_ci    AppSpawnService *spawnService = (AppSpawnService *)service;
7269570cc8Sopenharmony_ci    spawnService->identity = identity;
7369570cc8Sopenharmony_ci
7469570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] initialize, identity<%d, %d>", \
7569570cc8Sopenharmony_ci        identity.serviceId, identity.featureId);
7669570cc8Sopenharmony_ci    return TRUE;
7769570cc8Sopenharmony_ci}
7869570cc8Sopenharmony_ci
7969570cc8Sopenharmony_cistatic BOOL MessageHandle(Service *service, Request *msg)
8069570cc8Sopenharmony_ci{
8169570cc8Sopenharmony_ci    UNUSED(service);
8269570cc8Sopenharmony_ci    UNUSED(msg);
8369570cc8Sopenharmony_ci    APPSPAWN_LOGE("[appspawn] message handle not support yet!");
8469570cc8Sopenharmony_ci    return FALSE;
8569570cc8Sopenharmony_ci}
8669570cc8Sopenharmony_ci
8769570cc8Sopenharmony_cistatic TaskConfig GetTaskConfig(Service *service)
8869570cc8Sopenharmony_ci{
8969570cc8Sopenharmony_ci    UNUSED(service);
9069570cc8Sopenharmony_ci    TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL, 0x800, 20, SHARED_TASK};
9169570cc8Sopenharmony_ci    return config;
9269570cc8Sopenharmony_ci}
9369570cc8Sopenharmony_ci
9469570cc8Sopenharmony_cistatic int GetMessageSt(MessageSt *msgSt, IpcIo *req)
9569570cc8Sopenharmony_ci{
9669570cc8Sopenharmony_ci    if (msgSt == NULL || req == NULL) {
9769570cc8Sopenharmony_ci        return EC_FAILURE;
9869570cc8Sopenharmony_ci    }
9969570cc8Sopenharmony_ci
10069570cc8Sopenharmony_ci    size_t len = 0;
10169570cc8Sopenharmony_ci    char* str = ReadString(req, &len);
10269570cc8Sopenharmony_ci    if (str == NULL || len == 0) {
10369570cc8Sopenharmony_ci        APPSPAWN_LOGE("[appspawn] invoke, get data failed.");
10469570cc8Sopenharmony_ci        return EC_FAILURE;
10569570cc8Sopenharmony_ci    }
10669570cc8Sopenharmony_ci
10769570cc8Sopenharmony_ci    int ret = SplitMessage(str, len, msgSt);  // after split message, str no need to free(linux version)
10869570cc8Sopenharmony_ci    return ret;
10969570cc8Sopenharmony_ci}
11069570cc8Sopenharmony_ci
11169570cc8Sopenharmony_cistatic AppSpawnContentLite *g_appSpawnContentLite = NULL;
11269570cc8Sopenharmony_ciAppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int cold)
11369570cc8Sopenharmony_ci{
11469570cc8Sopenharmony_ci    UNUSED(longProcName);
11569570cc8Sopenharmony_ci    UNUSED(longProcNameLen);
11669570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnCreateContent %s", socketName);
11769570cc8Sopenharmony_ci    AppSpawnContentLite *appSpawnContent = (AppSpawnContentLite *)malloc(sizeof(AppSpawnContentLite));
11869570cc8Sopenharmony_ci    APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn");
11969570cc8Sopenharmony_ci    int ret = memset_s(appSpawnContent, sizeof(AppSpawnContentLite), 0, sizeof(AppSpawnContentLite));
12069570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, free(appSpawnContent);
12169570cc8Sopenharmony_ci        return NULL, "Failed to memset content");
12269570cc8Sopenharmony_ci    appSpawnContent->content.longProcName = NULL;
12369570cc8Sopenharmony_ci    appSpawnContent->content.longProcNameLen = 0;
12469570cc8Sopenharmony_ci    g_appSpawnContentLite = appSpawnContent;
12569570cc8Sopenharmony_ci    return appSpawnContent;
12669570cc8Sopenharmony_ci}
12769570cc8Sopenharmony_ci
12869570cc8Sopenharmony_cistatic int Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
12969570cc8Sopenharmony_ci{
13069570cc8Sopenharmony_ci#ifdef OHOS_DEBUG
13169570cc8Sopenharmony_ci    struct timespec tmStart = {0};
13269570cc8Sopenharmony_ci    clock_gettime(CLOCK_REALTIME, &tmStart);
13369570cc8Sopenharmony_ci#endif
13469570cc8Sopenharmony_ci
13569570cc8Sopenharmony_ci    UNUSED(iProxy);
13669570cc8Sopenharmony_ci    UNUSED(origin);
13769570cc8Sopenharmony_ci
13869570cc8Sopenharmony_ci    if (reply == NULL || funcId != ID_CALL_CREATE_SERVICE || req == NULL) {
13969570cc8Sopenharmony_ci        APPSPAWN_LOGE("[appspawn] invoke, funcId %d invalid, reply %d.", funcId, INVALID_PID);
14069570cc8Sopenharmony_ci        WriteInt64(reply, INVALID_PID);
14169570cc8Sopenharmony_ci        return EC_BADPTR;
14269570cc8Sopenharmony_ci    }
14369570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] invoke.");
14469570cc8Sopenharmony_ci    AppSpawnClientLite client = {};
14569570cc8Sopenharmony_ci    client.client.id = CLIENT_ID;
14669570cc8Sopenharmony_ci    client.client.flags = 0;
14769570cc8Sopenharmony_ci    if (GetMessageSt(&client.message, req) != EC_SUCCESS) {
14869570cc8Sopenharmony_ci        APPSPAWN_LOGE("[appspawn] invoke, parse failed! reply %d.", INVALID_PID);
14969570cc8Sopenharmony_ci        WriteInt64(reply, INVALID_PID);
15069570cc8Sopenharmony_ci        return EC_FAILURE;
15169570cc8Sopenharmony_ci    }
15269570cc8Sopenharmony_ci
15369570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] invoke, msg<%s,%s,%d,%d %d>", client.message.bundleName, client.message.identityID,
15469570cc8Sopenharmony_ci        client.message.uID, client.message.gID, client.message.capsCnt);
15569570cc8Sopenharmony_ci    pid_t newPid = 0;
15669570cc8Sopenharmony_ci    int ret = AppSpawnProcessMsg(&g_appSpawnContentLite->content, &client.client, &newPid);
15769570cc8Sopenharmony_ci    if (ret != 0) {
15869570cc8Sopenharmony_ci        newPid = -1;
15969570cc8Sopenharmony_ci    }
16069570cc8Sopenharmony_ci    FreeMessageSt(&client.message);
16169570cc8Sopenharmony_ci    WriteInt64(reply, newPid);
16269570cc8Sopenharmony_ci
16369570cc8Sopenharmony_ci#ifdef OHOS_DEBUG
16469570cc8Sopenharmony_ci    struct timespec tmEnd = {0};
16569570cc8Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &tmEnd);
16669570cc8Sopenharmony_ci    long long diff = DiffTime(&tmStart, &tmEnd);
16769570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] invoke, reply pid %d, timeused %lld ns.", newPid, diff);
16869570cc8Sopenharmony_ci#else
16969570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] invoke, reply pid %d.", newPid);
17069570cc8Sopenharmony_ci#endif  // OHOS_DEBUG
17169570cc8Sopenharmony_ci
17269570cc8Sopenharmony_ci    return ((newPid > 0) ? EC_SUCCESS : EC_FAILURE);
17369570cc8Sopenharmony_ci}
17469570cc8Sopenharmony_ci
17569570cc8Sopenharmony_cistatic AppSpawnService g_appSpawnService = {
17669570cc8Sopenharmony_ci    .GetName = GetName,
17769570cc8Sopenharmony_ci    .Initialize = Initialize,
17869570cc8Sopenharmony_ci    .MessageHandle = MessageHandle,
17969570cc8Sopenharmony_ci    .GetTaskConfig = GetTaskConfig,
18069570cc8Sopenharmony_ci    SERVER_IPROXY_IMPL_BEGIN,
18169570cc8Sopenharmony_ci    .Invoke = Invoke,
18269570cc8Sopenharmony_ci    IPROXY_END,
18369570cc8Sopenharmony_ci};
18469570cc8Sopenharmony_ci
18569570cc8Sopenharmony_civoid AppSpawnInit(void)
18669570cc8Sopenharmony_ci{
18769570cc8Sopenharmony_ci    if (SAMGR_GetInstance()->RegisterService((Service *)&g_appSpawnService) != TRUE) {
18869570cc8Sopenharmony_ci        APPSPAWN_LOGE("[appspawn] register service failed!");
18969570cc8Sopenharmony_ci        return;
19069570cc8Sopenharmony_ci    }
19169570cc8Sopenharmony_ci
19269570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] register service succeed.");
19369570cc8Sopenharmony_ci
19469570cc8Sopenharmony_ci    if (SAMGR_GetInstance()->RegisterDefaultFeatureApi(APPSPAWN_SERVICE_NAME, \
19569570cc8Sopenharmony_ci        GET_IUNKNOWN(g_appSpawnService)) != TRUE) {
19669570cc8Sopenharmony_ci        (void)SAMGR_GetInstance()->UnregisterService(APPSPAWN_SERVICE_NAME);
19769570cc8Sopenharmony_ci        APPSPAWN_LOGE("[appspawn] register featureapi failed!");
19869570cc8Sopenharmony_ci        return;
19969570cc8Sopenharmony_ci    }
20069570cc8Sopenharmony_ci
20169570cc8Sopenharmony_ci    APPSPAWN_LOGI("[appspawn] register featureapi succeed.");
20269570cc8Sopenharmony_ci}
20369570cc8Sopenharmony_ci
20469570cc8Sopenharmony_ciSYSEX_SERVICE_INIT(AppSpawnInit);
205