1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <dlfcn.h>
17#include <string.h>
18#include <unistd.h>
19
20#include "appspawn_server.h"
21#include "appspawn_silk.h"
22#include "appspawn_utils.h"
23#include "config_policy_utils.h"
24#include "cJSON.h"
25#include "json_utils.h"
26#include "securec.h"
27
28#define SILK_JSON_CONFIG_PATH   "/vendor/etc/silk/silk.json"
29#define SILK_JSON_ENABLE_ITEM   "enabled_app_list"
30#define SILK_JSON_LIBRARY_PATH  "/vendor/lib64/chipsetsdk/libsilk.so.0.1"
31
32#define SILK_JSON_MAX 128
33#define SILK_JSON_NAME_MAX 256
34
35struct SilkConfig {
36    char **configItems;
37    int configCursor;
38};
39
40static struct SilkConfig g_silkConfig = {0};
41
42static void ParseSilkConfig(const cJSON *root, struct SilkConfig *config)
43{
44    cJSON *silkJson = cJSON_GetObjectItemCaseSensitive(root, SILK_JSON_ENABLE_ITEM);
45    if (silkJson == NULL) {
46        return;
47    }
48
49    uint32_t configCount = (uint32_t)cJSON_GetArraySize(silkJson);
50    APPSPAWN_CHECK(configCount <= SILK_JSON_MAX, configCount = SILK_JSON_MAX,
51                   "config count %{public}u is larger than %{public}d", configCount, SILK_JSON_MAX);
52    config->configItems = (char **)malloc(configCount * sizeof(char *));
53    APPSPAWN_CHECK(config->configItems != NULL, return, "Alloc for silk config items failed");
54    int ret = memset_s(config->configItems, configCount * sizeof(char *), 0, configCount * sizeof(char *));
55    APPSPAWN_CHECK(ret == 0, free(config->configItems);
56                   config->configItems = NULL; return,
57                   "Memset silk config items failed");
58
59    for (uint32_t i = 0; i < configCount; ++i) {
60        const char *appName = cJSON_GetStringValue(cJSON_GetArrayItem(silkJson, i));
61        APPSPAWN_CHECK(appName != NULL, break, "appName is NULL");
62        APPSPAWN_LOGI("Enable silk appName %{public}s", appName);
63
64        int len = strlen(appName) + 1;
65        APPSPAWN_CHECK(len <= SILK_JSON_NAME_MAX, continue,
66                       "appName %{public}s is larger than the maximum limit", appName);
67        char **item = &config->configItems[config->configCursor];
68        *item = (char *)malloc(len * sizeof(char));
69        APPSPAWN_CHECK(*item != NULL, break, "Alloc for config item failed");
70
71        ret = memset_s(*item, len * sizeof(char), 0, len * sizeof(char));
72        APPSPAWN_CHECK(ret == 0, free(*item);
73                       *item = NULL; break,
74                       "Memset config item %{public}s failed", appName);
75
76        ret = strncpy_s(*item, len, appName, len - 1);
77        APPSPAWN_CHECK(ret == 0, free(*item);
78                       *item = NULL; break,
79                       "Copy config item %{public}s failed", appName);
80        config->configCursor++;
81    }
82}
83
84void LoadSilkConfig(void)
85{
86    cJSON *root = GetJsonObjFromFile(SILK_JSON_CONFIG_PATH);
87    APPSPAWN_CHECK(root != NULL, return, "Failed to load silk config");
88    ParseSilkConfig(root, &g_silkConfig);
89    cJSON_Delete(root);
90}
91
92static void FreeSilkConfigItems(void)
93{
94    for (int i = 0; i < g_silkConfig.configCursor; i++) {
95        if (g_silkConfig.configItems[i] != NULL) {
96            free(g_silkConfig.configItems[i]);
97            g_silkConfig.configItems[i] = NULL;
98        }
99    }
100}
101
102static void FreeSilkConfig(void)
103{
104    free(g_silkConfig.configItems);
105    g_silkConfig.configItems = NULL;
106    g_silkConfig.configCursor = 0;
107}
108
109static void FreeAllSilkConfig(void)
110{
111    FreeSilkConfigItems();
112    FreeSilkConfig();
113}
114
115void LoadSilkLibrary(const char *packageName)
116{
117    APPSPAWN_CHECK(g_silkConfig.configItems != NULL, return,
118                   "Load silk library failed for configItems is NULL");
119    APPSPAWN_CHECK(packageName != NULL, FreeAllSilkConfig(); return,
120                   "Load silk library failed for packageName is NULL");
121    char **appName = NULL;
122    void *handle = NULL;
123    for (int i = 0; i < g_silkConfig.configCursor; i++) {
124        appName = &g_silkConfig.configItems[i];
125        if (*appName == NULL) {
126            break;
127        }
128        if (handle == NULL && strcmp(*appName, packageName) == 0) {
129            handle = dlopen(SILK_JSON_LIBRARY_PATH, RTLD_NOW);
130            APPSPAWN_LOGI("Enable Silk AppName %{public}s result:%{public}s",
131                *appName, handle ? "success" : "failed");
132        }
133        free(*appName);
134        *appName = NULL;
135    }
136    FreeSilkConfig();
137}