1 /*
2 * Copyright (c) 2025 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 "svc_control.h"
16
17 #include <cstdio>
18 #include <string>
19 #include <map>
20 #include <functional>
21
22 #include "iservice_registry.h"
23 #include "if_local_ability_manager.h"
24 #include "string_ex.h"
25 #include "ipc_skeleton.h"
26 #include "safwk_log.h"
27
28 namespace OHOS {
SvcControl()29 SvcControl::SvcControl()
30 {
31 }
32
~SvcControl()33 SvcControl::~SvcControl()
34 {
35 }
36
HelpInfo(int32_t fd)37 void SvcControl::HelpInfo(int32_t fd)
38 {
39 dprintf(fd, "svc wifi | bluetooth | nearlink enable | disable | help\n");
40 }
41
CmdErrorToString(SvcCmd cmd)42 std::string SvcControl::CmdErrorToString(SvcCmd cmd)
43 {
44 if (cmd < SvcCmd::ARGS_CNT_NOT_ENOUGH) {
45 return "exception error code";
46 }
47 std::unordered_map<SvcCmd, std::string> errToString = {
48 { SvcCmd::ARGS_INVALID, "argument invalid" },
49 { SvcCmd::ARGS_CNT_EXCEED, "argument's cnt exceed" },
50 { SvcCmd::ARGS_CNT_NOT_ENOUGH, "argument's cnt not enough" },
51 };
52 return errToString[cmd];
53 }
54
Main(int32_t argc,char * argv[],int32_t outFd)55 int32_t SvcControl::Main(int32_t argc, char *argv[], int32_t outFd)
56 {
57 HILOGI(TAG, "enter SVC main, proc:%{public}d", getpid());
58 if (argv == nullptr) {
59 dprintf(outFd, "argument is null\n");
60 HelpInfo(outFd);
61 HILOGE(TAG, "argument is null");
62 return -1;
63 }
64 SvcCmd cmd = Parse(argc, argv);
65 if (cmd == SvcCmd::HELP_CMD) {
66 HelpInfo(outFd);
67 return 0;
68 } else if (cmd <= SvcCmd::ARGS_INVALID) {
69 dprintf(outFd, "parse failed, parse status: %s\n", CmdErrorToString(cmd).c_str());
70 HelpInfo(outFd);
71 HILOGE(TAG, "parse failed, parse status: %{public}d", static_cast<int32_t>(cmd));
72 return -1;
73 }
74
75 int32_t saId = static_cast<int32_t>(cmd);
76 auto sysm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
77 if (sysm == nullptr) {
78 dprintf(outFd, "get object of system ability manager failed\n");
79 HILOGE(TAG, "GetSystemAbilityManager failed");
80 return -1;
81 }
82 sptr<IRemoteObject> localObj = sysm->GetLocalAbilityManagerProxy(saId);
83 if (localObj == nullptr) {
84 (void)sysm->LoadSystemAbility(saId, TIME_OUT);
85 localObj = sysm->GetLocalAbilityManagerProxy(saId);
86 }
87 if (localObj == nullptr) {
88 dprintf(outFd, "get object of local ability manager proxy failed\n");
89 HILOGE(TAG, "GetLocalAbilityManagerProxy failed");
90 return -1;
91 }
92
93 sptr<ILocalAbilityManager> localAbilityManager = iface_cast<ILocalAbilityManager>(localObj);
94 std::vector<std::u16string> args;
95 SetCmdArgs(argc, argv, args);
96
97 int32_t ret = localAbilityManager->ServiceControlCmd(outFd, saId, args);
98 if (ret != NO_ERROR) {
99 dprintf(outFd, "set service cmd failed, ret: %d\n", ret);
100 HILOGE(TAG, "set ServiceControlCmd failed, ret: %{public}d", ret);
101 return -1;
102 }
103 dprintf(outFd, "set service cmd success\n");
104 return ret;
105 }
106
Parse(int32_t argc,char * argv[])107 SvcCmd SvcControl::Parse(int32_t argc, char *argv[])
108 {
109 if (argc < ARG_MIN_COUNT) {
110 HILOGE(TAG, "need more arguments(%{public}d), min size %{public}d", argc, ARG_MIN_COUNT);
111 return SvcCmd::ARGS_CNT_NOT_ENOUGH;
112 }
113 if (argc > ARG_MAX_COUNT) {
114 HILOGE(TAG, "too many arguments(%{public}d), limit size %{public}d", argc, ARG_MAX_COUNT);
115 return SvcCmd::ARGS_CNT_EXCEED;
116 }
117
118 for (int32_t i = 0; i < argc; ++i) {
119 if (argv[i] == nullptr) {
120 HILOGE(TAG, "argument(%{public}d) is null", i);
121 return SvcCmd::ARGS_INVALID;
122 }
123 size_t len = strlen(argv[i]);
124 if (len == 0) {
125 HILOGE(TAG, "argument(%{public}d) is empty", i);
126 return SvcCmd::ARGS_INVALID;
127 } else if (len > SINGLE_ARG_MAXLEN) {
128 HILOGE(TAG, "too long argument(%{public}d), limit size: %{public}d", i, SINGLE_ARG_MAXLEN);
129 return SvcCmd::ARGS_INVALID;
130 }
131 }
132
133 constexpr int32_t cnt = 1;
134 bool isEnd = false;
135 SvcCmd cmd = ParseCmd(argv, cnt, isEnd);
136 if (cmd == SvcCmd::ARGS_INVALID) {
137 HILOGE(TAG, "the %{public}dth argument(%{public}s) is abnormal", cnt, argv[cnt]);
138 } else if (isEnd && argc > cnt + 1) {
139 cmd = SvcCmd::ARGS_CNT_EXCEED;
140 HILOGE(TAG, "too many arguments(%{public}d), current limit size %{public}d", argc, cnt + 1);
141 } else if (!isEnd && argc == cnt + 1) {
142 cmd = SvcCmd::ARGS_CNT_NOT_ENOUGH;
143 HILOGE(TAG, "the argument(%{public}s) need more sub-argument", argv[cnt]);
144 }
145 return cmd;
146 }
147
ParseCmd(char * argv[],int32_t cnt,bool & isEnd)148 SvcCmd SvcControl::ParseCmd(char *argv[], int32_t cnt, bool &isEnd)
149 {
150 struct {
151 std::string op;
152 SvcCmd cmd;
153 bool isEnd;
154 } options[] = {
155 { "wifi", SvcCmd::WIFI_CMD, false },
156 { "bluetooth", SvcCmd::BLUETOOTH_CMD, false },
157 { "nearlink", SvcCmd::NEARLINK_CMD, false },
158 { "help", SvcCmd::HELP_CMD, true },
159 };
160 SvcCmd cmd = SvcCmd::ARGS_INVALID;
161 for (auto &op: options) {
162 if (op.op == argv[cnt]) {
163 cmd = op.cmd;
164 isEnd = op.isEnd;
165 break;
166 }
167 }
168 return cmd;
169 }
170
SetCmdArgs(int32_t argc,char * argv[],std::vector<std::u16string> & args)171 void SvcControl::SetCmdArgs(int32_t argc, char *argv[], std::vector<std::u16string>& args)
172 {
173 std::string argStr;
174 for (int32_t i = 0; i < ARG_MIN_COUNT; ++i) {
175 argStr += argv[i];
176 argStr += " ";
177 }
178 for (int32_t i = ARG_MIN_COUNT; i < argc; ++i) {
179 args.push_back(Str8ToStr16(std::string(argv[i])));
180 argStr += argv[i];
181 argStr += " ";
182 }
183 HILOGI(TAG, "svc cmd: %{public}s, callingUid=%{public}d, callingPid=%{public}d", argStr.c_str(),
184 IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingPid());
185 }
186 }
187