• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 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 "ability_tool.h"
17 
18 #include <cstdio>
19 #include <cstring>
20 #include <ohos_errno.h>
21 #include <liteipc_adapter.h>
22 #include <samgr_lite.h>
23 #include <securec.h>
24 #include <semaphore.h>
25 
26 #include "ability_errors.h"
27 #include "ability_kit_command.h"
28 #include "ability_manager.h"
29 #include "ability_service_interface.h"
30 #include "adapter.h"
31 #include "want_utils.h"
32 
33 namespace OHOS {
34 namespace {
35 constexpr int WAIT_TIMEOUT = 30; // 5 second
36 constexpr int MAX_BUFFER_SIZE_PER = 1024; // 1024 byte
37 constexpr char CMD_START_ABILITY[] = "start";
38 constexpr char CMD_STOP_ABILITY[] = "stopability";
39 constexpr char CMD_TERMINATE_APP[] = "terminate";
40 constexpr char CMD_DUMP_ABILITY[] = "dump";
41 } // namespace
42 
43 static sem_t g_sem;
44 
~AbilityTool()45 AbilityTool::~AbilityTool()
46 {
47     ClearElement(&elementName_);
48     UnregisterIpcCallback(identity_);
49 }
50 
SetBundleName(const char * bundleName)51 bool AbilityTool::SetBundleName(const char *bundleName)
52 {
53     if (bundleName == nullptr || strlen(bundleName) == 0) {
54         return false;
55     }
56     SetElementBundleName(&elementName_, bundleName);
57     return true;
58 }
59 
SetAbilityName(const char * abilityName)60 bool AbilityTool::SetAbilityName(const char *abilityName)
61 {
62     if (abilityName == nullptr || strlen(abilityName) == 0) {
63         return false;
64     }
65     SetElementAbilityName(&elementName_, abilityName);
66     return true;
67 }
68 
SetExtra(const char * extra)69 void AbilityTool::SetExtra(const char *extra)
70 {
71     extra_ = const_cast<char *>(extra);
72 }
73 
SetCommand(const char * command)74 bool AbilityTool::SetCommand(const char *command)
75 {
76     if (command == nullptr) {
77         return false;
78     }
79     if (strcmp(command, CMD_START_ABILITY) != 0 &&
80         strcmp(command, CMD_STOP_ABILITY) != 0 &&
81         strcmp(command, CMD_TERMINATE_APP) != 0 &&
82         strcmp(command, CMD_DUMP_ABILITY) != 0) {
83         return false;
84     }
85     printf("receive command: %s\n", command);
86     command_ = const_cast<char *>(command);
87     return true;
88 }
89 
SetDumpAll()90 void AbilityTool::SetDumpAll()
91 {
92     dumpAll_ = true;
93 }
94 
RunCommand()95 bool AbilityTool::RunCommand()
96 {
97     if (command_ == nullptr) {
98         printf("unknown command\n");
99         return false;
100     }
101     IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(AMS_SERVICE, AMS_INNER_FEATURE);
102     if (iUnknown == nullptr) {
103         printf("ams inner unknown is null\n");
104         return false;
105     }
106     IClientProxy *innerProxy = nullptr;
107     (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&innerProxy);
108     if (innerProxy == nullptr) {
109         printf("ams inner feature is null\n");
110         return false;
111     }
112 
113     if (RegisterIpcCallback(AbilityTool::AaCallback, 0, IPC_WAIT_FOREVER, &identity_, this) != 0) {
114         printf("registerIpcCallback failed\n");
115         return false;
116     }
117     bool retVal = false;
118     if (strcmp(command_, CMD_START_ABILITY) == 0) {
119         retVal = InnerStartAbility();
120     } else if (strcmp(command_, CMD_STOP_ABILITY) == 0) {
121         retVal = InnerStopAbility();
122     } else if (strcmp(command_, CMD_TERMINATE_APP) == 0) {
123         retVal = TerminateApp(innerProxy);
124     } else if (strcmp(command_, CMD_DUMP_ABILITY) == 0) {
125         retVal = Dump(innerProxy);
126     } else {
127         printf("unknown command: %s\n", command_);
128     }
129     return retVal;
130 }
131 
BuildWant()132 Want* AbilityTool::BuildWant()
133 {
134     Want *want = new Want();
135     if (memset_s(want, sizeof(Want), 0, sizeof(Want)) != EOK) {
136         delete want;
137         return nullptr;
138     }
139     if (!dumpAll_) {
140         if (elementName_.abilityName == nullptr || strlen(elementName_.abilityName) == 0 ||
141             elementName_.bundleName == nullptr || strlen(elementName_.bundleName) == 0) {
142             printf("ability name or bundle name is not entered\n");
143             delete want;
144             return nullptr;
145         }
146         SetWantElement(want, elementName_);
147     }
148     if (strcmp(command_, CMD_DUMP_ABILITY) == 0) {
149         SetWantSvcIdentity(want, identity_);
150     }
151     if (extra_ != nullptr) {
152         SetWantData(want, extra_, strlen(extra_) + 1);
153     }
154     return want;
155 }
156 
InnerStartAbility()157 bool AbilityTool::InnerStartAbility()
158 {
159     Want *want = BuildWant();
160     if (want == nullptr) {
161         return false;
162     }
163     int ret = StartAbility(want);
164     ClearWant(want);
165     delete want;
166     return ret == ERR_OK;
167 }
168 
InnerStopAbility()169 bool AbilityTool::InnerStopAbility()
170 {
171     Want *want = BuildWant();
172     if (want == nullptr) {
173         return false;
174     }
175     int ret = StopAbility(want);
176     ClearWant(want);
177     delete want;
178     return ret == ERR_OK;
179 }
180 
TerminateApp(IClientProxy * proxy) const181 bool AbilityTool::TerminateApp(IClientProxy *proxy) const
182 {
183     if (proxy == nullptr) {
184         return false;
185     }
186     if (elementName_.bundleName == nullptr || strlen(elementName_.bundleName) == 0) {
187         printf("invalid argument\n");
188         return false;
189     }
190     IpcIo req;
191     char data[IPC_IO_DATA_MAX];
192     IpcIoInit(&req, data, IPC_IO_DATA_MAX, 0);
193     IpcIoPushString(&req, elementName_.bundleName);
194     return proxy->Invoke(proxy, TERMINATE_APP, &req, nullptr, nullptr) == EC_SUCCESS;
195 }
196 
Dump(IClientProxy * proxy)197 bool AbilityTool::Dump(IClientProxy *proxy)
198 {
199     if (proxy == nullptr) {
200         return false;
201     }
202     Want *want = BuildWant();
203     if (want == nullptr) {
204         return false;
205     }
206 
207     IpcIo req;
208     char data[IPC_IO_DATA_MAX];
209     IpcIoInit(&req, data, IPC_IO_DATA_MAX, MAX_OBJECTS);
210     if (!SerializeWant(&req, want)) {
211         printf("SerializeWant failed\n");
212         ClearWant(want);
213         delete want;
214         return false;
215     }
216     ClearWant(want);
217     delete want;
218     if (proxy->Invoke(proxy, DUMP_ABILITY, &req, nullptr, nullptr) != EC_SUCCESS) {
219         printf("dumpAbility failed\n");
220         return false;
221     }
222     if (sem_init(&g_sem, 0, 0)) {
223         printf("sem_init failed\n");
224         return false;
225     }
226     printf("wait for callback\n");
227     struct timespec ts = { 0, 0 };
228     clock_gettime(CLOCK_REALTIME, &ts);
229     ts.tv_sec += WAIT_TIMEOUT;
230     sem_timedwait(&g_sem, &ts);
231     printf("sem exit\n");
232     return true;
233 }
234 
AaCallback(const IpcContext * context,void * ipcMsg,IpcIo * data,void * arg)235 int32_t AbilityTool::AaCallback(const IpcContext* context, void *ipcMsg, IpcIo *data, void *arg)
236 {
237     printf("get ability info\n");
238     if (ipcMsg == nullptr) {
239         printf("ams call back error, ipcMsg is null\n");
240         return -1;
241     }
242     auto abilityTool = static_cast<AbilityTool *>(arg);
243     if (abilityTool == nullptr) {
244         printf("ams call back error, abilityTool is null\n");
245         FreeBuffer(nullptr, ipcMsg);
246         return -1;
247     }
248 
249     uint32_t funcId = 0;
250     GetCode(ipcMsg, &funcId);
251     uint32_t flag = 0;
252     GetFlag(ipcMsg, &flag);
253     switch (funcId) {
254         case SCHEDULER_APP_INIT: {
255             ElementName element = {};
256             DeserializeElement(&element, data);
257             int ret = IpcIoPopInt32(data);
258             printf("ams call back, start %s.%s ret = %d\n", element.bundleName, element.abilityName, ret);
259             ClearElement(&element);
260             break;
261         }
262         case SCHEDULER_DUMP_ABILITY: {
263 #ifdef __LINUX__
264             size_t len = 0;
265             char *result = reinterpret_cast<char *>(IpcIoPopString(data, &len));
266 #else
267             BuffPtr *buff = IpcIoPopDataBuff(data);
268             if ((buff == nullptr) || (buff->buff == nullptr)) {
269                 printf("ams call back error, buff is empty\n");
270                 if (flag == LITEIPC_FLAG_ONEWAY) {
271                     FreeBuffer(nullptr, ipcMsg);
272                 }
273                 return false;
274             }
275             char *result = static_cast<char *>(buff->buff);
276             if ((buff->buffSz > 0) && (result[buff->buffSz - 1] != '\0')) {
277                 printf("Wrong message format.\n}\n");
278                 FreeBuffer(nullptr, buff->buff);
279                 break;
280             }
281             int len = strlen(result);
282 #endif
283             printf("dump ability info:\n");
284             if (!abilityTool->dumpAll_) {
285                 printf("[%s][%s]\n", abilityTool->elementName_.bundleName, abilityTool->elementName_.abilityName);
286             }
287             printf("{\n");
288             for (int i = 0; i <= (len - 1) / MAX_BUFFER_SIZE_PER; i++) {
289                 int start = MAX_BUFFER_SIZE_PER * i;
290                 int size = (len - start) < MAX_BUFFER_SIZE_PER ? (len - start) : MAX_BUFFER_SIZE_PER;
291                 printf("%-.*s", size, result + start);
292             }
293             printf("}\n");
294 #ifndef __LINUX__
295             FreeBuffer(nullptr, buff->buff);
296 #endif
297             break;
298         }
299         default: {
300             printf("ams call back error, funcId: %u\n", funcId);
301             break;
302         }
303     }
304     if (flag == LITEIPC_FLAG_ONEWAY) {
305         FreeBuffer(nullptr, ipcMsg);
306     }
307     sem_post(&g_sem);
308     return 0;
309 }
310 } // namespace OHOS
311