• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 <cinttypes>
16 #include <getopt.h>
17 #include <unistd.h>
18 
19 #include "appexecfwk_errors.h"
20 #include "hilog_wrapper.h"
21 #include "fms_command.h"
22 #include "if_system_ability_manager.h"
23 #include "ipc_skeleton.h"
24 #include "iservice_registry.h"
25 #include "string_ex.h"
26 #include "system_ability_definition.h"
27 
28 using namespace OHOS::AAFwk;
29 
30 namespace OHOS {
31 namespace AppExecFwk {
32 namespace {
33 const int COMMAND_QUERY_INVALID = -1;
34 const int COMMAND_QUERY_STORAGE = 0;
35 const int COMMAND_QUERY_NAME = 1;
36 const int COMMAND_QUERY_ID = 2;
37 
38 // const std::string BUNDLE_NAME_EMPTY = "";
39 
40 const std::string SHORT_OPTIONS = "hsn:i:";
41 const struct option LONG_OPTIONS[] = {
42     {"help", no_argument, nullptr, 'h'},
43     {"storage", no_argument, nullptr, 's'},
44     {"bundle-name", required_argument, nullptr, 'n'},
45     {"form-id", required_argument, nullptr, 'i'},
46     {0, 0, 0, 0},
47 };
48 }  // namespace
49 
FormMgrShellCommand(int argc,char * argv[])50 FormMgrShellCommand::FormMgrShellCommand(int argc, char *argv[]) : ShellCommand(argc, argv, FM_TOOL_NAME)
51 {
52 }
init()53 ErrCode FormMgrShellCommand::init()
54 {
55     return ERR_OK;
56 }
57 /**
58  * @brief Create command map.
59  */
CreateCommandMap()60 ErrCode FormMgrShellCommand::CreateCommandMap()
61 {
62     commandMap_ = {
63         {"help", std::bind(&FormMgrShellCommand::RunAsHelpCommand, this)},
64         {"query", std::bind(&FormMgrShellCommand::RunAsQueryCommand, this)},
65     };
66 
67     return OHOS::ERR_OK;
68 }
69 /**
70  * @brief Create message map.
71  */
CreateMessageMap()72 ErrCode FormMgrShellCommand::CreateMessageMap()
73 {
74     messageMap_ = {
75         //  error + message
76         {
77             ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR,
78             "error: fm query internal error.",
79         },
80         {
81             ERR_APPEXECFWK_FORM_INVALID_PARAM,
82             "error: fm query param error.",
83         },
84         {
85             ERR_APPEXECFWK_FORM_PERMISSION_DENY,
86             "error: fm query permission denied.",
87         },
88         {
89             ERR_APPEXECFWK_FORM_NOT_EXIST_ID,
90             "warning: fm query no form info.",
91         },
92         {
93             ERR_APPEXECFWK_FORM_COMMON_CODE,
94             "error: unknown.",
95         },
96     };
97 
98     return OHOS::ERR_OK;
99 }
100 /**
101  * @brief Run help command.
102  */
RunAsHelpCommand()103 ErrCode FormMgrShellCommand::RunAsHelpCommand()
104 {
105     resultReceiver_.append(FM_HELP_MSG);
106 
107     return OHOS::ERR_OK;
108 }
109 /**
110  * @brief Run query form info command.
111  */
RunAsQueryCommand()112 ErrCode FormMgrShellCommand::RunAsQueryCommand()
113 {
114     int32_t result = OHOS::ERR_OK;
115     int32_t cmdFlag = COMMAND_QUERY_INVALID;
116     int option = -1;
117     int counter = 0;
118     std::string bundleName = "";
119     int64_t formId = 0;
120 
121     while (true) {
122         counter++;
123         option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
124         HILOG_INFO("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
125         if (optind < 0 || optind > argc_) {
126             return OHOS::ERR_INVALID_VALUE;
127         }
128 
129         for (int i = 0; i < argc_; i++) {
130             HILOG_INFO("argv_[%{public}d]: %{public}s", i, argv_[i]);
131         }
132 
133         if (option == -1) {
134             if (counter == 1) {
135                 // When scanning the first argument
136                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
137                     // 'fm query' with no option: fm query
138                     // 'fm query' with a wrong argument: fm query xxx
139                     HILOG_ERROR("'fm query' with no option.");
140                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
141                     result = OHOS::ERR_INVALID_VALUE;
142                 }
143             }
144             break;
145         }
146 
147         if (option == '?') {
148             result = HandleUnknownOption(optopt);
149             break;
150         }
151 
152         result = HandleNormalOption(option, bundleName, formId, cmdFlag);
153     }
154 
155     if (result == OHOS::ERR_OK) {
156         result = ExecuteQuery(bundleName, formId, cmdFlag);
157     } else {
158         resultReceiver_.append(HELP_MSG_QUERY);
159     }
160 
161     return result;
162 }
163 /**
164  * @brief Handle command args.
165  * @param optopt Command optopt.
166  * @return Returns ERR_OK on success, others on failure.
167  */
HandleUnknownOption(const char optopt)168 int32_t FormMgrShellCommand::HandleUnknownOption(const char optopt)
169 {
170     int32_t result = OHOS::ERR_OK;
171     switch (optopt) {
172         case 'n':
173         case 'i': {
174             // 'fm query -n' with no argument: fm query -n
175             // 'fm query --bundle-name' with no argument: fm query --bundle-name
176             // 'fm query -i' with no argument: fm query -i
177             // 'fm query --form-id' with no argument: fm query --form-id
178             HILOG_ERROR("'fm query' %{public}s with no argument.", argv_[optind - 1]);
179             resultReceiver_.append("error: option '");
180             resultReceiver_.append(argv_[optind - 1]);
181             resultReceiver_.append("' requires a value.\n");
182             result = OHOS::ERR_INVALID_VALUE;
183             break;
184         }
185         case 0: {
186             // 'fm query' with a unknown option: fm query --x
187             // 'fm query' with a unknown option: fm query --xxx
188             std::string unknownOption = "";
189             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
190             HILOG_ERROR("'fm query' with a unknown option: %{public}s", unknownOption.c_str());
191             resultReceiver_.append(unknownOptionMsg);
192             result = OHOS::ERR_INVALID_VALUE;
193             break;
194         }
195         default: {
196             // 'fm query' with a unknown option: fm query -x
197             // 'fm query' with a unknown option: fm query -xxx
198             std::string unknownOption = "";
199             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
200             HILOG_ERROR("'fm query' with a unknown option: %{public}s", unknownOption.c_str());
201             resultReceiver_.append(unknownOptionMsg);
202             result = OHOS::ERR_INVALID_VALUE;
203             break;
204         }
205     }
206 
207     return result;
208 }
209 /**
210  * @brief Handle command args.
211  * @param option Command option.
212  * @param bundleName BundleName.
213  * @param formId The id of the form.
214  * @param cmdFlag Command Flag.
215  * @return Returns ERR_OK on success, others on failure.
216  */
HandleNormalOption(const int option,std::string & bundleName,int64_t & formId,int32_t & cmdFlag)217 int32_t FormMgrShellCommand::HandleNormalOption(const int option, std::string &bundleName, int64_t &formId, int32_t &cmdFlag)
218 {
219     HILOG_INFO("%{public}s start, option: %{public}d", __func__, option);
220     int32_t result = OHOS::ERR_OK;
221     switch (option) {
222         case 'h': {
223             // 'fm query -h'
224             // 'fm query --help'
225             HILOG_INFO("'fm query' %{public}s", argv_[optind - 1]);
226             result = OHOS::ERR_INVALID_VALUE;
227             break;
228         }
229         case 's': {
230             // 'fm query -s'
231             // 'fm query --storage'
232             cmdFlag = COMMAND_QUERY_STORAGE;
233             break;
234         }
235         case 'n': {
236             // 'fm query -n <bundle-name>'
237             // 'fm query --bundle-name <bundle-name>'
238             if (optarg == nullptr) {
239                 resultReceiver_.append("error: option ");
240                 resultReceiver_.append("'-n'");
241                 resultReceiver_.append(" requires a value.\n");
242                 result = OHOS::ERR_INVALID_VALUE;
243                 break;
244             }
245             cmdFlag = COMMAND_QUERY_NAME;
246             bundleName = optarg;
247             break;
248         }
249         case 'i': {
250             // 'fm query -i <form-id> '
251             // 'fm query --form-id <form-id> '
252             if (optarg == nullptr) {
253                 resultReceiver_.append("error: option ");
254                 resultReceiver_.append("'-i'");
255                 resultReceiver_.append(" requires a value.\n");
256                 result = OHOS::ERR_INVALID_VALUE;
257                 break;
258             }
259             cmdFlag = COMMAND_QUERY_ID;
260             formId = std::stoll(optarg);
261             break;
262         }
263         default: {
264             result = OHOS::ERR_INVALID_VALUE;
265             HILOG_INFO("'fm query' invalid option.");
266             break;
267         }
268     }
269     HILOG_INFO("%{public}s end, result: %{public}d", __func__, result);
270     return result;
271 }
272 /**
273  * @brief Execute query form info command.
274  * @param bundleName BundleName.
275  * @param formId The id of the form.
276  * @param cmdFlag Command Flag.
277  * @return Returns ERR_OK on success, others on failure.
278  */
ExecuteQuery(const std::string & bundleName,const int64_t formId,const int32_t cmdFlag)279 int32_t FormMgrShellCommand::ExecuteQuery(const std::string &bundleName, const int64_t formId, const int32_t cmdFlag)
280 {
281     HILOG_INFO("%{public}s start, bundleName: %{public}s, formId:%{public}" PRId64 "", __func__, bundleName.c_str(), formId);
282     int32_t result = OHOS::ERR_OK;
283     switch (cmdFlag) {
284         case COMMAND_QUERY_STORAGE: {
285             result = QueryStorageFormInfos();
286             break;
287         }
288         case COMMAND_QUERY_NAME: {
289             result = QueryFormInfoByBundleName(bundleName);
290             break;
291         }
292         case COMMAND_QUERY_ID: {
293             result = QueryFormInfoByFormId(formId);
294             break;
295         }
296         default: {
297             HILOG_INFO("'fm query' invalid command.");
298             break;
299         }
300         HILOG_INFO("%{public}s end, cmdFlag: %{public}d", __func__, cmdFlag);
301     }
302 
303     if (result == OHOS::ERR_OK) {
304         resultReceiver_ = STRING_QUERY_FORM_INFO_OK + "\n" + resultReceiver_;
305     } else if (result == OHOS::ERR_APPEXECFWK_FORM_NOT_EXIST_ID) {
306         resultReceiver_ = STRING_QUERY_FORM_INFO_OK + "\n";
307         resultReceiver_.append(GetMessageFromCode(result));
308     } else {
309         resultReceiver_ = STRING_QUERY_FORM_INFO_NG + "\n";
310         resultReceiver_.append(GetMessageFromCode(result));
311     }
312 
313     return result;
314 }
315 /**
316  * @brief Query all of form storage infos.
317  * @return Returns ERR_OK on success, others on failure.
318  */
QueryStorageFormInfos()319 int32_t FormMgrShellCommand::QueryStorageFormInfos()
320 {
321     HILOG_INFO("%{public}s start", __func__);
322 
323     int errCode = ConnectFms();
324     if (errCode != OHOS::ERR_OK) {
325         return errCode;
326     }
327 
328     std::string formInfos;
329     MessageParcel data;
330     if (!WriteInterfaceToken(data)) {
331         HILOG_ERROR("%{public}s, failed to write interface token", __func__);
332         return ERR_APPEXECFWK_PARCEL_ERROR;
333     }
334 
335     int result = GetStringInfo(IFormMgr::Message::FORM_MGR_STORAGE_FORM_INFOS, data, formInfos);
336     if (result == ERR_OK) {
337         resultReceiver_= formInfos;
338     } else {
339         HILOG_ERROR("'fm query' failed to query form info.");
340     }
341     HILOG_INFO("%{public}s end, formInfo: %{public}s", __func__, resultReceiver_.c_str());
342 
343     return result;
344 }
345 /**
346  * @brief Query form infos by bundleName.
347  * @param bundleName BundleName.
348  * @return Returns ERR_OK on success, others on failure.
349  */
QueryFormInfoByBundleName(const std::string & bundleName)350 int32_t FormMgrShellCommand::QueryFormInfoByBundleName(const std::string& bundleName)
351 {
352     HILOG_INFO("%{public}s start, bundleName: %{public}s", __func__, bundleName.c_str());
353 
354     int errCode = ConnectFms();
355     if (errCode != OHOS::ERR_OK) {
356         return errCode;
357     }
358 
359     std::string formInfos;
360     MessageParcel data;
361     if (!WriteInterfaceToken(data)) {
362         HILOG_ERROR("%{public}s, failed to write interface token", __func__);
363         return ERR_APPEXECFWK_PARCEL_ERROR;
364     }
365 
366     if (!data.WriteString(bundleName)) {
367         HILOG_ERROR("%{public}s, failed to write bundleName", __func__);
368         return ERR_APPEXECFWK_PARCEL_ERROR;
369     }
370 
371     int result = GetStringInfo(IFormMgr::Message::FORM_MGR_FORM_INFOS_BY_NAME, data, formInfos);
372     if (result == ERR_OK) {
373         HILOG_INFO("%{public}s, DumpFormInfoByBundleName success", __func__);
374         resultReceiver_ = formInfos;
375     } else {
376         HILOG_ERROR("'fm query' failed to query form info.");
377     }
378     HILOG_INFO("%{public}s end, formInfo: %{public}s", __func__, resultReceiver_.c_str());
379 
380     return result;
381 }
382 /**
383  * @brief Query form infos by form id.
384  * @param formId The id of the form.
385  * @return Returns ERR_OK on success, others on failure.
386  */
QueryFormInfoByFormId(const std::int64_t formId)387 int32_t FormMgrShellCommand::QueryFormInfoByFormId(const std::int64_t formId)
388 {
389     HILOG_INFO("%{public}s start, formId: %{public}" PRId64 "", __func__, formId);
390 
391     int errCode = ConnectFms();
392     if (errCode != OHOS::ERR_OK) {
393         return errCode;
394     }
395 
396     std::string formInfo;
397     MessageParcel data;
398     if (!WriteInterfaceToken(data)) {
399         HILOG_ERROR("%{public}s, failed to write interface token", __func__);
400         return ERR_APPEXECFWK_PARCEL_ERROR;
401     }
402     if (!data.WriteInt64(formId)) {
403         HILOG_ERROR("%{public}s, failed to write formId", __func__);
404         return ERR_APPEXECFWK_PARCEL_ERROR;
405     }
406 
407     int result = GetStringInfo(IFormMgr::Message::FORM_MGR_FORM_INFOS_BY_ID, data, formInfo);
408     if (result == ERR_OK) {
409         resultReceiver_ = formInfo;
410     } else if (result == OHOS::ERR_APPEXECFWK_FORM_NOT_EXIST_ID) {
411         HILOG_WARN("'fm query' no form info.");
412     } else {
413         HILOG_ERROR("'fm query' failed to query form info.");
414     }
415     HILOG_INFO("%{public}s end, formInfo: %{public}s", __func__, resultReceiver_.c_str());
416 
417     return result;
418 }
WriteInterfaceToken(MessageParcel & data)419 bool FormMgrShellCommand::WriteInterfaceToken(MessageParcel &data)
420 {
421     if (!data.WriteInterfaceToken(IFormMgr::GetDescriptor())) {
422         HILOG_ERROR("%{public}s, failed to write interface token", __func__);
423         return false;
424     }
425     return true;
426 }
GetStringInfo(IFormMgr::Message code,MessageParcel & data,std::string & stringInfo)427 int FormMgrShellCommand::GetStringInfo(IFormMgr::Message code, MessageParcel &data, std::string &stringInfo)
428 {
429     int error;
430     MessageParcel reply;
431     error = SendTransactCmd(code, data, reply);
432     if (error != ERR_OK) {
433         return error;
434     }
435 
436     error = reply.ReadInt32();
437     if (error != ERR_OK) {
438         HILOG_ERROR("%{public}s, failed to read reply result: %{public}d", __func__, error);
439         return error;
440     }
441     std::vector<std::string> stringInfoList;
442     if (!reply.ReadStringVector(&stringInfoList)) {
443         HILOG_ERROR("%{public}s, failed to read string vector from reply", __func__);
444         return false;
445     }
446     if (stringInfoList.empty()) {
447         HILOG_INFO("%{public}s, No string info", __func__);
448         return ERR_APPEXECFWK_FORM_NOT_EXIST_ID;
449     }
450     for (auto &info : stringInfoList) {
451         stringInfo += info;
452     }
453     HILOG_DEBUG("%{public}s, get string info success", __func__);
454     return ERR_OK;
455 }
SendTransactCmd(IFormMgr::Message code,MessageParcel & data,MessageParcel & reply)456 int FormMgrShellCommand::SendTransactCmd(IFormMgr::Message code, MessageParcel &data, MessageParcel &reply)
457 {
458     MessageOption option(MessageOption::TF_SYNC);
459 
460     if (!remoteObject_) {
461         HILOG_ERROR("%{public}s, failed to get remote object, cmd: %{public}d", __func__, code);
462         return ERR_APPEXECFWK_SERVICE_NOT_CONNECTED;
463     }
464     int32_t result = remoteObject_->SendRequest(static_cast<uint32_t>(code), data, reply, option);
465     if (result != ERR_OK) {
466         HILOG_ERROR("%{public}s, failed to SendRequest: %{public}d, cmd: %{public}d", __func__, result, code);
467         return result;
468     }
469     return ERR_OK;
470 }
471 /**
472  * @brief Connect form manager service.
473  * @return Returns ERR_OK on success, others on failure.
474  */
ConnectFms()475 int32_t FormMgrShellCommand::ConnectFms()
476 {
477     if (remoteObject_ != nullptr) {
478         return OHOS::ERR_OK;
479     }
480     sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
481     if (systemManager == nullptr) {
482         HILOG_ERROR("%{private}s:fail to get system ability manager", __func__);
483         return ERR_APPEXECFWK_FORM_GET_FMS_FAILED;
484     }
485     remoteObject_ = systemManager->GetSystemAbility(FORM_MGR_SERVICE_ID);
486     if (remoteObject_ == nullptr) {
487         HILOG_ERROR("%{private}s:fail to connect FormMgrService", __func__);
488         return ERR_APPEXECFWK_FORM_GET_FMS_FAILED;
489     }
490 
491     HILOG_INFO("%{public}s end, get fms proxy success", __func__);
492     return OHOS::ERR_OK;
493 }
494 }  // namespace AppExecFwk
495 }  // namespace OHOS
496