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