1/* 2 * Copyright (c) 2021 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#include <fcntl.h> 16#include <pthread.h> 17#include <string.h> 18#include <sys/time.h> 19 20#include "begetctl.h" 21#include "init_param.h" 22#include "param_init.h" 23#include "init_utils.h" 24#include "loop_event.h" 25#include "parameter.h" 26#include "plugin_test.h" 27#include "service_watcher.h" 28#include "parameter.h" 29#include "param_base.h" 30 31#define MAX_THREAD_NUMBER 100 32#define MAX_NUMBER 10 33#define READ_DURATION 100000 34#define CMD_INDEX 2 35 36static char *GetLocalBuffer(uint32_t *buffSize) 37{ 38 static char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX] = {0}; 39 if (buffSize != NULL) { 40 *buffSize = sizeof(buffer); 41 } 42 return buffer; 43} 44 45int g_stop = 0; 46static void *CmdReader(void *args) 47{ 48 (void)srand((unsigned)time(NULL)); 49 uint32_t buffSize = 0; 50 char *buffer = GetLocalBuffer(&buffSize); 51 while (g_stop == 0) { 52 int wait = READ_DURATION + READ_DURATION; // 100ms rand 53 uint32_t size = buffSize; 54 int ret = SystemGetParameter("test.randrom.read", buffer, &size); 55 if (ret == 0) { 56 printf("SystemGetParameter value %s %d \n", buffer, wait); 57 } else { 58 printf("SystemGetParameter fail %d \n", wait); 59 } 60 usleep(wait); 61 } 62 return NULL; 63} 64 65static int32_t BShellParamCmdRead(BShellHandle shell, int32_t argc, char *argv[]) 66{ 67 PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); 68 static pthread_t thread = 0; 69 PLUGIN_LOGV("BShellParamCmdWatch %s, threadId %d", argv[1], thread); 70 if (strcmp(argv[1], "start") == 0) { 71 if (thread != 0) { 72 return 0; 73 } 74 SystemSetParameter("test.randrom.read.start", "1"); 75 pthread_create(&thread, NULL, CmdReader, argv[1]); 76 } else if (strcmp(argv[1], "stop") == 0) { 77 if (thread == 0) { 78 return 0; 79 } 80 SystemSetParameter("test.randrom.read.start", "0"); 81 g_stop = 1; 82 pthread_join(thread, NULL); 83 thread = 0; 84 } 85 return 0; 86} 87 88typedef struct { 89 char name[PARAM_NAME_LEN_MAX]; 90 pthread_t thread; 91} TestWatchContext; 92 93static void HandleParamChange2(const char *key, const char *value, void *context) 94{ 95 PLUGIN_CHECK(key != NULL && value != NULL, return, "Invalid parameter"); 96 long long commit = GetSystemCommitId(); 97 size_t index = (size_t)context; 98 printf("[%zu] Receive parameter commit %lld change %s %s \n", index, commit, key, value); 99 static int addWatcher = 0; 100 int ret = 0; 101 if ((index == 4) && !addWatcher) { // 4 when context == 4 add 102 index = 5; // 5 add context 103 ret = SystemWatchParameter(key, HandleParamChange2, (void *)index); 104 if (ret != 0) { 105 printf("Add watcher %s fail %zu \n", key, index); 106 } 107 addWatcher = 1; 108 return; 109 } 110 if (index == 2) { // 2 when context == 2 delete 3 111 index = 3; // 3 delete context 112 RemoveParameterWatcher(key, HandleParamChange2, (void *)index); 113 if (ret != 0) { 114 printf("Remove watcher fail %zu \n", index); 115 } 116 return; 117 } 118 if (index == 1) { // 1 when context == 1 delete 1 119 RemoveParameterWatcher(key, HandleParamChange2, (void *)index); 120 if (ret != 0) { 121 printf("Remove watcher fail %zu \n", index); 122 } 123 return; 124 } 125 if ((index == 5) && (addWatcher == 1)) { // 5 when context == 5 delete 5 126 RemoveParameterWatcher(key, HandleParamChange2, (void *)index); 127 if (ret != 0) { 128 printf("Remove watcher fail %zu \n", index); 129 } 130 addWatcher = 0; 131 } 132} 133 134static void HandleParamChange1(const char *key, const char *value, void *context) 135{ 136 PLUGIN_CHECK(key != NULL && value != NULL, return, "Invalid parameter"); 137 long long commit = GetSystemCommitId(); 138 size_t index = (size_t)context; 139 printf("[%zu] Receive parameter commit %lld change %s %s \n", index, commit, key, value); 140} 141 142static void *CmdThreadWatcher(void *args) 143{ 144 TestWatchContext *context = (TestWatchContext *)args; 145 for (size_t i = 1; i <= MAX_NUMBER; i++) { 146 int ret = SystemWatchParameter(context->name, HandleParamChange2, (void *)i); 147 if (ret != 0) { 148 printf("Add watcher %s fail %zu \n", context->name, i); 149 } 150 ret = SetParameter(context->name, context->name); 151 if (ret != 0) { 152 printf("Set parameter %s fail %zu \n", context->name, i); 153 } 154 } 155 sleep(1); 156 for (size_t i = 1; i <= MAX_NUMBER; i++) { 157 int ret = RemoveParameterWatcher(context->name, HandleParamChange2, (void *)i); 158 if (ret != 0) { 159 printf("Remove watcher %s fail %zu \n", context->name, i); 160 } 161 } 162 free(context); 163 return NULL; 164} 165 166static void StartWatcherInThread(const char *prefix) 167{ 168 TestWatchContext *context[MAX_THREAD_NUMBER] = { NULL }; 169 for (size_t i = 0; i < MAX_THREAD_NUMBER; i++) { 170 context[i] = calloc(1, sizeof(TestWatchContext)); 171 PLUGIN_CHECK(context[i] != NULL, return, "Failed to alloc context"); 172 int len = sprintf_s(context[i]->name, sizeof(context[i]->name), "%s.%zu", prefix, i); 173 if (len > 0) { 174 printf("Add watcher %s \n", context[i]->name); 175 pthread_create(&context[i]->thread, NULL, CmdThreadWatcher, context[i]); 176 } 177 } 178} 179 180static void StartWatcher(const char *prefix) 181{ 182 static size_t index = 0; 183 int ret = SystemWatchParameter(prefix, HandleParamChange1, (void *)index); 184 if (ret != 0) { 185 printf("Add watcher %s fail \n", prefix); 186 return; 187 } 188 index++; 189} 190 191static int32_t BShellParamCmdWatch(BShellHandle shell, int32_t argc, char *argv[]) 192{ 193 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 194 PLUGIN_LOGV("BShellParamCmdWatch %s", argv[1]); 195 StartWatcher(argv[1]); 196 197 if (argc <= CMD_INDEX) { 198 return 0; 199 } 200 if (strcmp(argv[CMD_INDEX], "thread") == 0) { // 2 cmd index 201 StartWatcherInThread(argv[1]); 202 return 0; 203 } 204 205 int maxCount = StringToInt(argv[CMD_INDEX], -1); // 2 cmd index 206 if (maxCount <= 0 || maxCount > 65535) { // 65535 max count 207 PLUGIN_LOGE("Invalid input %s", argv[CMD_INDEX]); 208 return 0; 209 } 210 uint32_t buffSize = 0; 211 char *buffer = GetLocalBuffer(&buffSize); 212 size_t count = 0; 213 while (count < (size_t)maxCount) { // 100 max count 214 int len = sprintf_s(buffer, buffSize, "%s.%zu", argv[1], count); 215 PLUGIN_CHECK(len > 0, return -1, "Invalid buffer"); 216 buffer[len] = '\0'; 217 StartWatcher(buffer); 218 count++; 219 } 220 return 0; 221} 222 223static int32_t BShellParamCmdInstall(BShellHandle shell, int32_t argc, char *argv[]) 224{ 225 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 226 PLUGIN_LOGV("BShellParamCmdInstall %s %s", argv[0], argv[1]); 227 uint32_t buffSize = 0; 228 char *buffer = GetLocalBuffer(&buffSize); 229 int ret = sprintf_s(buffer, buffSize, "ohos.servicectrl.%s", argv[0]); 230 PLUGIN_CHECK(ret > 0, return -1, "Invalid buffer"); 231 buffer[ret] = '\0'; 232 SystemSetParameter(buffer, argv[1]); 233 return 0; 234} 235 236static int32_t BShellParamCmdDisplay(BShellHandle shell, int32_t argc, char *argv[]) 237{ 238 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 239 PLUGIN_LOGV("BShellParamCmdDisplay %s %s", argv[0], argv[1]); 240 SystemSetParameter("ohos.servicectrl.display", argv[1]); 241 return 0; 242} 243 244void ServiceStatusChangeTest(const char *key, const ServiceInfo *status) 245{ 246 PLUGIN_LOGI("group-test-stage3: wait service %s status: %d", key, status->status); 247 if (status->status == SERVICE_READY || status->status == SERVICE_STARTED) { 248 PLUGIN_LOGI("Service %s start work", key); 249 } 250} 251 252static int32_t BShellParamCmdGroupTest(BShellHandle shell, int32_t argc, char *argv[]) 253{ 254 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 255 PLUGIN_LOGI("BShellParamCmdGroupTest %s stage: %s", argv[0], argv[1]); 256 if (argc > 2 && strcmp(argv[1], "wait") == 0) { // 2 service name index 257 PLUGIN_LOGI("group-test-stage3: wait service %s", argv[2]); // 2 service name index 258 ServiceWatchForStatus(argv[2], ServiceStatusChangeTest); // 2 service name index 259 LE_RunLoop(LE_GetDefaultLoop()); 260 LE_CloseLoop(LE_GetDefaultLoop()); 261 } 262 return 0; 263} 264 265static int32_t BShellParamCmdUdidGet(BShellHandle shell, int32_t argc, char *argv[]) 266{ 267 PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); 268 PLUGIN_LOGI("BShellParamCmdUdidGet "); 269 char localDeviceId[65] = {0}; // 65 udid len 270 AclGetDevUdid(localDeviceId, 65); // 65 udid len 271 BShellEnvOutput(shell, " udid: %s\r\n", localDeviceId); 272 return 0; 273} 274 275static int CalcValue(const char *value) 276{ 277 char *begin = (char *)value; 278 while (*begin != '\0') { 279 if (*begin == ' ') { 280 begin++; 281 } else { 282 break; 283 } 284 } 285 char *end = begin + strlen(begin); 286 while (end > begin) { 287 if (*end > '9' || *end < '0') { 288 *end = '\0'; 289 } 290 end--; 291 } 292 return StringToInt(begin, -1); 293} 294 295static int32_t BShellParamCmdMemGet(BShellHandle shell, int32_t argc, char *argv[]) 296{ 297 PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); 298 uint32_t buffSize = 0; // 1024 max buffer for decode 299 char *buff = GetLocalBuffer(&buffSize); 300 PLUGIN_CHECK(buff != NULL, return -1, "Failed to get local buffer"); 301 int ret = sprintf_s(buff, buffSize - 1, "/proc/%s/smaps", argv[1]); 302 PLUGIN_CHECK(ret > 0, return -1, "Failed to format path %s", argv[1]); 303 buff[ret] = '\0'; 304 char *realPath = GetRealPath(buff); 305 PLUGIN_CHECK(realPath != NULL, return -1, "Failed to get real path"); 306 int all = 0; 307 if (argc > 2 && strcmp(argv[2], "all") == 0) { // 2 2 max arg 308 all = 1; 309 } 310 FILE *fp = fopen(realPath, "r"); 311 free(realPath); 312 int value = 0; 313 while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) { 314 buff[buffSize - 1] = '\0'; 315 if (strncmp(buff, "Pss:", strlen("Pss:")) == 0) { 316 int v = CalcValue(buff + strlen("Pss:")); 317 if (all) { 318 printf("Pss: %d kb\n", v); 319 } 320 value += v; 321 } else if (strncmp(buff, "SwapPss:", strlen("SwapPss:")) == 0) { 322 int v = CalcValue(buff + strlen("SwapPss:")); 323 if (all) { 324 printf("SwapPss: %d kb\n", v); 325 } 326 value += v; 327 } 328 } 329 if (fp != NULL) { 330 fclose(fp); 331 printf("Total mem %d kb\n", value); 332 } else { 333 printf("Failed to get memory for %s %s \n", argv[1], buff); 334 } 335 return 0; 336} 337 338void CmdServiceStatusChange(const char *key, const ServiceInfo *status) 339{ 340 static const char *serviceStatusMap[] = { 341 "idle", 342 "starting", 343 "running", 344 "ready", 345 "stopping", 346 "stopped", 347 "error", 348 "suspended", 349 "freezed", 350 "disabled", 351 "critical", 352 }; 353 PLUGIN_CHECK(key != NULL && status != NULL, return, "Invalid parameter"); 354 if (status->status == SERVICE_STARTED || status->status == SERVICE_READY) { 355 printf("Service %s status: %s pid %d \n", key, 356 ((status->status < ARRAY_LENGTH(serviceStatusMap)) ? serviceStatusMap[status->status] : "unknown"), 357 status->pid); 358 } else { 359 printf("Service %s status: %s \n", key, 360 (status->status < ARRAY_LENGTH(serviceStatusMap)) ? serviceStatusMap[status->status] : "unknown"); 361 } 362} 363 364static int32_t BShellParamCmdWatchService(BShellHandle shell, int32_t argc, char *argv[]) 365{ 366 PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); 367 return ServiceWatchForStatus(argv[1], CmdServiceStatusChange); 368} 369 370int32_t BShellCmdRegister(BShellHandle shell, int execMode) 371{ 372 if (execMode == 0) { 373 const CmdInfo infos[] = { 374 {"init", BShellParamCmdGroupTest, "init group test", "init group test [stage]", "init group test"}, 375 {"display", BShellParamCmdMemGet, "display memory pid", "display memory [pid]", "display memory"}, 376 }; 377 for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { 378 BShellEnvRegisterCmd(shell, &infos[i]); 379 } 380 } else { 381 const CmdInfo infos[] = { 382 {"display", BShellParamCmdDisplay, "display system service", "display service", "display service"}, 383 {"read", BShellParamCmdRead, "read system parameter", "read [start | stop]", ""}, 384 {"watcher", BShellParamCmdWatch, 385 "watcher system parameter", "watcher parameter [name]", "watcher parameter"}, 386 {"install", BShellParamCmdInstall, "install plugin", "install [name]", ""}, 387 {"uninstall", BShellParamCmdInstall, "uninstall plugin", "uninstall [name]", ""}, 388 {"group", BShellParamCmdGroupTest, "group test", "group test [stage]", "group test"}, 389 {"display", BShellParamCmdUdidGet, "display udid", "display udid", "display udid"}, 390 {"display", BShellParamCmdMemGet, "display memory pid", "display memory [pid]", "display memory"}, 391 {"watcher", BShellParamCmdWatchService, 392 "watcher service status", "watcher service [name]", "watcher service"}, 393 }; 394 for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { 395 BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); 396 } 397 } 398 return 0; 399} 400