169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (c) 2024 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 <dlfcn.h>
1769570cc8Sopenharmony_ci#include <string.h>
1869570cc8Sopenharmony_ci#include <unistd.h>
1969570cc8Sopenharmony_ci
2069570cc8Sopenharmony_ci#include "appspawn_server.h"
2169570cc8Sopenharmony_ci#include "appspawn_silk.h"
2269570cc8Sopenharmony_ci#include "appspawn_utils.h"
2369570cc8Sopenharmony_ci#include "config_policy_utils.h"
2469570cc8Sopenharmony_ci#include "cJSON.h"
2569570cc8Sopenharmony_ci#include "json_utils.h"
2669570cc8Sopenharmony_ci#include "securec.h"
2769570cc8Sopenharmony_ci
2869570cc8Sopenharmony_ci#define SILK_JSON_CONFIG_PATH   "/vendor/etc/silk/silk.json"
2969570cc8Sopenharmony_ci#define SILK_JSON_ENABLE_ITEM   "enabled_app_list"
3069570cc8Sopenharmony_ci#define SILK_JSON_LIBRARY_PATH  "/vendor/lib64/chipsetsdk/libsilk.so.0.1"
3169570cc8Sopenharmony_ci
3269570cc8Sopenharmony_ci#define SILK_JSON_MAX 128
3369570cc8Sopenharmony_ci#define SILK_JSON_NAME_MAX 256
3469570cc8Sopenharmony_ci
3569570cc8Sopenharmony_cistruct SilkConfig {
3669570cc8Sopenharmony_ci    char **configItems;
3769570cc8Sopenharmony_ci    int configCursor;
3869570cc8Sopenharmony_ci};
3969570cc8Sopenharmony_ci
4069570cc8Sopenharmony_cistatic struct SilkConfig g_silkConfig = {0};
4169570cc8Sopenharmony_ci
4269570cc8Sopenharmony_cistatic void ParseSilkConfig(const cJSON *root, struct SilkConfig *config)
4369570cc8Sopenharmony_ci{
4469570cc8Sopenharmony_ci    cJSON *silkJson = cJSON_GetObjectItemCaseSensitive(root, SILK_JSON_ENABLE_ITEM);
4569570cc8Sopenharmony_ci    if (silkJson == NULL) {
4669570cc8Sopenharmony_ci        return;
4769570cc8Sopenharmony_ci    }
4869570cc8Sopenharmony_ci
4969570cc8Sopenharmony_ci    uint32_t configCount = (uint32_t)cJSON_GetArraySize(silkJson);
5069570cc8Sopenharmony_ci    APPSPAWN_CHECK(configCount <= SILK_JSON_MAX, configCount = SILK_JSON_MAX,
5169570cc8Sopenharmony_ci                   "config count %{public}u is larger than %{public}d", configCount, SILK_JSON_MAX);
5269570cc8Sopenharmony_ci    config->configItems = (char **)malloc(configCount * sizeof(char *));
5369570cc8Sopenharmony_ci    APPSPAWN_CHECK(config->configItems != NULL, return, "Alloc for silk config items failed");
5469570cc8Sopenharmony_ci    int ret = memset_s(config->configItems, configCount * sizeof(char *), 0, configCount * sizeof(char *));
5569570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, free(config->configItems);
5669570cc8Sopenharmony_ci                   config->configItems = NULL; return,
5769570cc8Sopenharmony_ci                   "Memset silk config items failed");
5869570cc8Sopenharmony_ci
5969570cc8Sopenharmony_ci    for (uint32_t i = 0; i < configCount; ++i) {
6069570cc8Sopenharmony_ci        const char *appName = cJSON_GetStringValue(cJSON_GetArrayItem(silkJson, i));
6169570cc8Sopenharmony_ci        APPSPAWN_CHECK(appName != NULL, break, "appName is NULL");
6269570cc8Sopenharmony_ci        APPSPAWN_LOGI("Enable silk appName %{public}s", appName);
6369570cc8Sopenharmony_ci
6469570cc8Sopenharmony_ci        int len = strlen(appName) + 1;
6569570cc8Sopenharmony_ci        APPSPAWN_CHECK(len <= SILK_JSON_NAME_MAX, continue,
6669570cc8Sopenharmony_ci                       "appName %{public}s is larger than the maximum limit", appName);
6769570cc8Sopenharmony_ci        char **item = &config->configItems[config->configCursor];
6869570cc8Sopenharmony_ci        *item = (char *)malloc(len * sizeof(char));
6969570cc8Sopenharmony_ci        APPSPAWN_CHECK(*item != NULL, break, "Alloc for config item failed");
7069570cc8Sopenharmony_ci
7169570cc8Sopenharmony_ci        ret = memset_s(*item, len * sizeof(char), 0, len * sizeof(char));
7269570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, free(*item);
7369570cc8Sopenharmony_ci                       *item = NULL; break,
7469570cc8Sopenharmony_ci                       "Memset config item %{public}s failed", appName);
7569570cc8Sopenharmony_ci
7669570cc8Sopenharmony_ci        ret = strncpy_s(*item, len, appName, len - 1);
7769570cc8Sopenharmony_ci        APPSPAWN_CHECK(ret == 0, free(*item);
7869570cc8Sopenharmony_ci                       *item = NULL; break,
7969570cc8Sopenharmony_ci                       "Copy config item %{public}s failed", appName);
8069570cc8Sopenharmony_ci        config->configCursor++;
8169570cc8Sopenharmony_ci    }
8269570cc8Sopenharmony_ci}
8369570cc8Sopenharmony_ci
8469570cc8Sopenharmony_civoid LoadSilkConfig(void)
8569570cc8Sopenharmony_ci{
8669570cc8Sopenharmony_ci    cJSON *root = GetJsonObjFromFile(SILK_JSON_CONFIG_PATH);
8769570cc8Sopenharmony_ci    APPSPAWN_CHECK(root != NULL, return, "Failed to load silk config");
8869570cc8Sopenharmony_ci    ParseSilkConfig(root, &g_silkConfig);
8969570cc8Sopenharmony_ci    cJSON_Delete(root);
9069570cc8Sopenharmony_ci}
9169570cc8Sopenharmony_ci
9269570cc8Sopenharmony_cistatic void FreeSilkConfigItems(void)
9369570cc8Sopenharmony_ci{
9469570cc8Sopenharmony_ci    for (int i = 0; i < g_silkConfig.configCursor; i++) {
9569570cc8Sopenharmony_ci        if (g_silkConfig.configItems[i] != NULL) {
9669570cc8Sopenharmony_ci            free(g_silkConfig.configItems[i]);
9769570cc8Sopenharmony_ci            g_silkConfig.configItems[i] = NULL;
9869570cc8Sopenharmony_ci        }
9969570cc8Sopenharmony_ci    }
10069570cc8Sopenharmony_ci}
10169570cc8Sopenharmony_ci
10269570cc8Sopenharmony_cistatic void FreeSilkConfig(void)
10369570cc8Sopenharmony_ci{
10469570cc8Sopenharmony_ci    free(g_silkConfig.configItems);
10569570cc8Sopenharmony_ci    g_silkConfig.configItems = NULL;
10669570cc8Sopenharmony_ci    g_silkConfig.configCursor = 0;
10769570cc8Sopenharmony_ci}
10869570cc8Sopenharmony_ci
10969570cc8Sopenharmony_cistatic void FreeAllSilkConfig(void)
11069570cc8Sopenharmony_ci{
11169570cc8Sopenharmony_ci    FreeSilkConfigItems();
11269570cc8Sopenharmony_ci    FreeSilkConfig();
11369570cc8Sopenharmony_ci}
11469570cc8Sopenharmony_ci
11569570cc8Sopenharmony_civoid LoadSilkLibrary(const char *packageName)
11669570cc8Sopenharmony_ci{
11769570cc8Sopenharmony_ci    APPSPAWN_CHECK(g_silkConfig.configItems != NULL, return,
11869570cc8Sopenharmony_ci                   "Load silk library failed for configItems is NULL");
11969570cc8Sopenharmony_ci    APPSPAWN_CHECK(packageName != NULL, FreeAllSilkConfig(); return,
12069570cc8Sopenharmony_ci                   "Load silk library failed for packageName is NULL");
12169570cc8Sopenharmony_ci    char **appName = NULL;
12269570cc8Sopenharmony_ci    void *handle = NULL;
12369570cc8Sopenharmony_ci    for (int i = 0; i < g_silkConfig.configCursor; i++) {
12469570cc8Sopenharmony_ci        appName = &g_silkConfig.configItems[i];
12569570cc8Sopenharmony_ci        if (*appName == NULL) {
12669570cc8Sopenharmony_ci            break;
12769570cc8Sopenharmony_ci        }
12869570cc8Sopenharmony_ci        if (handle == NULL && strcmp(*appName, packageName) == 0) {
12969570cc8Sopenharmony_ci            handle = dlopen(SILK_JSON_LIBRARY_PATH, RTLD_NOW);
13069570cc8Sopenharmony_ci            APPSPAWN_LOGI("Enable Silk AppName %{public}s result:%{public}s",
13169570cc8Sopenharmony_ci                *appName, handle ? "success" : "failed");
13269570cc8Sopenharmony_ci        }
13369570cc8Sopenharmony_ci        free(*appName);
13469570cc8Sopenharmony_ci        *appName = NULL;
13569570cc8Sopenharmony_ci    }
13669570cc8Sopenharmony_ci    FreeSilkConfig();
13769570cc8Sopenharmony_ci}