* 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 <dlfcn.h>
#include <string.h>
#include <unistd.h>
#include "appspawn_server.h"
#include "appspawn_silk.h"
#include "appspawn_utils.h"
#include "config_policy_utils.h"
#include "cJSON.h"
#include "json_utils.h"
#include "securec.h"
#define SILK_JSON_CONFIG_PATH "/vendor/etc/silk/silk.json"
#define SILK_JSON_ENABLE_ITEM "enabled_app_list"
#define SILK_JSON_LIBRARY_PATH "libsilk.so.0.1"
#define SILK_JSON_MAX 128
#define SILK_JSON_NAME_MAX 256
APPSPAWN_STATIC struct SilkConfig g_silkConfig = {0};
static void FreeSilkConfigItems(void)
{
for (int i = 0; i < g_silkConfig.configCursor; i++) {
if (g_silkConfig.configItems[i] != NULL) {
free(g_silkConfig.configItems[i]);
g_silkConfig.configItems[i] = NULL;
}
}
}
static void FreeSilkConfig(void)
{
free(g_silkConfig.configItems);
g_silkConfig.configItems = NULL;
g_silkConfig.configCursor = 0;
}
static void FreeAllSilkConfig(void)
{
FreeSilkConfigItems();
FreeSilkConfig();
}
APPSPAWN_STATIC bool ParseSilkConfig(const cJSON *root, struct SilkConfig *config)
{
bool isSuccess = false;
cJSON *silkJson = cJSON_GetObjectItemCaseSensitive(root, SILK_JSON_ENABLE_ITEM);
if (silkJson == NULL) {
return isSuccess;
}
uint32_t configCount = (uint32_t)cJSON_GetArraySize(silkJson);
APPSPAWN_CHECK(configCount <= SILK_JSON_MAX, configCount = SILK_JSON_MAX,
"config count %{public}u is larger than %{public}d", configCount, SILK_JSON_MAX);
config->configItems = (char **)malloc(configCount * sizeof(char *));
APPSPAWN_CHECK(config->configItems != NULL, return isSuccess, "Alloc for silk config items failed");
int ret = memset_s(config->configItems, configCount * sizeof(char *), 0, configCount * sizeof(char *));
APPSPAWN_CHECK(ret == 0, free(config->configItems);
config->configItems = NULL; return isSuccess,
"Memset silk config items failed");
for (uint32_t i = 0; i < configCount; ++i) {
const char *appName = cJSON_GetStringValue(cJSON_GetArrayItem(silkJson, i));
APPSPAWN_CHECK(appName != NULL, break, "appName is NULL");
APPSPAWN_LOGI("Enable silk appName %{public}s", appName);
int len = strlen(appName) + 1;
APPSPAWN_CHECK(len <= SILK_JSON_NAME_MAX, continue,
"appName %{public}s is larger than the maximum limit", appName);
char **item = &config->configItems[config->configCursor];
*item = (char *)malloc(len * sizeof(char));
APPSPAWN_CHECK(*item != NULL, break, "Alloc for config item failed");
ret = memset_s(*item, len * sizeof(char), 0, len * sizeof(char));
APPSPAWN_CHECK(ret == 0, free(*item);
*item = NULL; break,
"Memset config item %{public}s failed", appName);
ret = strncpy_s(*item, len, appName, len - 1);
APPSPAWN_CHECK(ret == 0, free(*item);
*item = NULL; break,
"Copy config item %{public}s failed", appName);
config->configCursor++;
if (i == configCount -1) {
isSuccess = true;
}
}
if (!isSuccess) {
FreeAllSilkConfig();
}
return isSuccess;
}
void LoadSilkConfig(void)
{
cJSON *root = GetJsonObjFromFile(SILK_JSON_CONFIG_PATH);
APPSPAWN_CHECK_LOGV(root != NULL, return, "Failed to load silk config");
(void)ParseSilkConfig(root, &g_silkConfig);
cJSON_Delete(root);
}
bool LoadSilkLibrary(const char *packageName)
{
bool isSuccess = false;
APPSPAWN_CHECK_LOGV(g_silkConfig.configItems != NULL, return isSuccess,
"ConfigItems is NULL");
APPSPAWN_CHECK_LOGV(packageName != NULL, FreeAllSilkConfig(); return isSuccess,
"PackageName is NULL");
char **appName = NULL;
void *handle = NULL;
for (int i = 0; i < g_silkConfig.configCursor; i++) {
appName = &g_silkConfig.configItems[i];
if (*appName == NULL) {
break;
}
if (handle == NULL && strcmp(*appName, packageName) == 0) {
handle = dlopen(SILK_JSON_LIBRARY_PATH, RTLD_NOW);
if (handle != NULL) {
isSuccess = true;
}
APPSPAWN_LOGI("Enable Silk AppName %{public}s result:%{public}s",
*appName, handle ? "success" : "failed");
}
free(*appName);
*appName = NULL;
}
FreeSilkConfig();
return isSuccess;
}