• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <getopt.h>
16 #include <unistd.h>
17 #include <cinttypes>
18 
19 #include "appexecfwk_errors.h"
20 #include "app_log_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         // {"dump", std::bind(&FormMgrShellCommand::RunAsDumpCommand, 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         APP_LOGI("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             APP_LOGI("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                     APP_LOGE("'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         // if(result == OHOS::ERR_OK) {
155         //     break;
156         // }
157     }
158 
159     if (result == OHOS::ERR_OK) {
160         result = ExecuteQuery(bundleName, formId, cmdFlag);
161     } else {
162         resultReceiver_.append(HELP_MSG_QUERY);
163     }
164 
165     return result;
166 }
167 /**
168  * @brief Handle command args.
169  * @param optopt Command optopt.
170  * @return Returns ERR_OK on success, others on failure.
171  */
HandleUnknownOption(const char optopt)172 int32_t FormMgrShellCommand::HandleUnknownOption(const char optopt)
173 {
174     int32_t result = OHOS::ERR_OK;
175     switch (optopt) {
176         case 'n':
177         case 'i': {
178             // 'fm query -n' with no argument: fm query -n
179             // 'fm query --bundle-name' with no argument: fm query --bundle-name
180             // 'fm query -i' with no argument: fm query -i
181             // 'fm query --form-id' with no argument: fm query --form-id
182             APP_LOGE("'fm query' %{public}s with no argument.", argv_[optind - 1]);
183             resultReceiver_.append("error: option '");
184             resultReceiver_.append(argv_[optind - 1]);
185             resultReceiver_.append("' requires a value.\n");
186             result = OHOS::ERR_INVALID_VALUE;
187             break;
188         }
189         case 0: {
190             // 'fm query' with a unknown option: fm query --x
191             // 'fm query' with a unknown option: fm query --xxx
192             std::string unknownOption = "";
193             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
194             APP_LOGE("'fm query' with a unknown option: %{public}s", unknownOption.c_str());
195             resultReceiver_.append(unknownOptionMsg);
196             result = OHOS::ERR_INVALID_VALUE;
197             break;
198         }
199         default: {
200             // 'fm query' with a unknown option: fm query -x
201             // 'fm query' with a unknown option: fm query -xxx
202             std::string unknownOption = "";
203             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
204             APP_LOGE("'fm query' with a unknown option: %{public}s", unknownOption.c_str());
205             resultReceiver_.append(unknownOptionMsg);
206             result = OHOS::ERR_INVALID_VALUE;
207             break;
208         }
209     }
210 
211     return result;
212 }
213 /**
214  * @brief Handle command args.
215  * @param option Command option.
216  * @param bundleName BundleName.
217  * @param formId The id of the form.
218  * @param cmdFlag Command Flag.
219  * @return Returns ERR_OK on success, others on failure.
220  */
HandleNormalOption(const int option,std::string & bundleName,int64_t & formId,int32_t & cmdFlag)221 int32_t FormMgrShellCommand::HandleNormalOption(const int option, std::string &bundleName, int64_t &formId, int32_t &cmdFlag)
222 {
223     APP_LOGI("%{public}s start, option: %{public}d", __func__, option);
224     int32_t result = OHOS::ERR_OK;
225     switch (option) {
226         case 'h': {
227             // 'fm query -h'
228             // 'fm query --help'
229             APP_LOGI("'fm query' %{public}s", argv_[optind - 1]);
230             result = OHOS::ERR_INVALID_VALUE;
231             break;
232         }
233         case 's': {
234             // 'fm query -s'
235             // 'fm query --storage'
236             cmdFlag = COMMAND_QUERY_STORAGE;
237             break;
238         }
239         case 'n': {
240             // 'fm query -n <bundle-name>'
241             // 'fm query --bundle-name <bundle-name>'
242             if(optarg == nullptr) {
243                 resultReceiver_.append("error: option ");
244                 resultReceiver_.append("'-n'");
245                 resultReceiver_.append(" requires a value.\n");
246                 result = OHOS::ERR_INVALID_VALUE;
247                 break;
248             }
249             cmdFlag = COMMAND_QUERY_NAME;
250             bundleName = optarg;
251             break;
252         }
253         case 'i': {
254             // 'fm query -i <form-id> '
255             // 'fm query --form-id <form-id> '
256             if(optarg == nullptr) {
257                 resultReceiver_.append("error: option ");
258                 resultReceiver_.append("'-i'");
259                 resultReceiver_.append(" requires a value.\n");
260                 result = OHOS::ERR_INVALID_VALUE;
261                 break;
262             }
263             cmdFlag = COMMAND_QUERY_ID;
264             formId = std::stoll(optarg);
265             break;
266         }
267         default: {
268             result = OHOS::ERR_INVALID_VALUE;
269             APP_LOGI("'fm query' invalid option.");
270             break;
271         }
272     }
273     APP_LOGI("%{public}s end, result: %{public}d", __func__, result);
274     return result;
275 }
276 /**
277  * @brief Execute query form info command.
278  * @param bundleName BundleName.
279  * @param formId The id of the form.
280  * @param cmdFlag Command Flag.
281  * @return Returns ERR_OK on success, others on failure.
282  */
ExecuteQuery(const std::string & bundleName,const int64_t formId,const int32_t cmdFlag)283 int32_t FormMgrShellCommand::ExecuteQuery(const std::string &bundleName, const int64_t formId, const int32_t cmdFlag)
284 {
285     APP_LOGI("%{public}s start, bundleName: %{public}s, formId:%{public}" PRId64 "", __func__, bundleName.c_str(), formId);
286     int32_t result = OHOS::ERR_OK;
287     switch (cmdFlag) {
288         case COMMAND_QUERY_STORAGE: {
289             result = QueryStorageFormInfos();
290             break;
291         }
292         case COMMAND_QUERY_NAME: {
293             result = QueryFormInfoByBundleName(bundleName);
294             break;
295         }
296         case COMMAND_QUERY_ID: {
297             result = QueryFormInfoByFormId(formId);
298             break;
299         }
300         default: {
301             APP_LOGI("'fm query' invalid command.");
302             break;
303         }
304         APP_LOGI("%{public}s end, cmdFlag: %{public}d", __func__, cmdFlag);
305     }
306 
307     if (result == OHOS::ERR_OK) {
308         resultReceiver_ = STRING_QUERY_FORM_INFO_OK + "\n" + resultReceiver_;
309     } else if(result == OHOS::ERR_APPEXECFWK_FORM_NOT_EXIST_ID){
310         resultReceiver_ = STRING_QUERY_FORM_INFO_OK + "\n";
311         resultReceiver_.append(GetMessageFromCode(result));
312     } else {
313         resultReceiver_ = STRING_QUERY_FORM_INFO_NG + "\n";
314         resultReceiver_.append(GetMessageFromCode(result));
315     }
316 
317     return result;
318 }
319 /**
320  * @brief Query all of form storage infos.
321  * @return Returns ERR_OK on success, others on failure.
322  */
QueryStorageFormInfos()323 int32_t FormMgrShellCommand::QueryStorageFormInfos()
324 {
325     APP_LOGI("%{public}s start", __func__);
326 
327     int errCode = ConnectFms();
328     if(errCode != OHOS::ERR_OK) {
329         return errCode;
330     }
331 
332     std::string formInfos;
333     MessageParcel data;
334     if (!WriteInterfaceToken(data)) {
335         APP_LOGE("%{public}s, failed to write interface token", __func__);
336         return ERR_APPEXECFWK_PARCEL_ERROR;
337     }
338 
339     int result = GetStringInfo(IFormMgr::Message::FORM_MGR_STORAGE_FORM_INFOS, data, formInfos);
340     if (result == ERR_OK) {
341         resultReceiver_= formInfos;
342     } else {
343         APP_LOGE("'fm query' failed to query form info.");
344     }
345     APP_LOGI("%{public}s end, formInfo: %{public}s", __func__, resultReceiver_.c_str());
346 
347     return result;
348 }
349 /**
350  * @brief Query form infos by bundleName.
351  * @param bundleName BundleName.
352  * @return Returns ERR_OK on success, others on failure.
353  */
QueryFormInfoByBundleName(const std::string & bundleName)354 int32_t FormMgrShellCommand::QueryFormInfoByBundleName(const std::string& bundleName)
355 {
356     APP_LOGI("%{public}s start, bundleName: %{public}s", __func__, bundleName.c_str());
357 
358     int errCode = ConnectFms();
359     if(errCode != OHOS::ERR_OK) {
360         return errCode;
361     }
362 
363     std::string formInfos;
364     MessageParcel data;
365     if (!WriteInterfaceToken(data)) {
366         APP_LOGE("%{public}s, failed to write interface token", __func__);
367         return ERR_APPEXECFWK_PARCEL_ERROR;
368     }
369 
370     if (!data.WriteString(bundleName)) {
371         APP_LOGE("%{public}s, failed to write bundleName", __func__);
372         return ERR_APPEXECFWK_PARCEL_ERROR;
373     }
374 
375     int result = GetStringInfo(IFormMgr::Message::FORM_MGR_FORM_INFOS_BY_NAME, data, formInfos);
376     if (result == ERR_OK) {
377         APP_LOGI("%{public}s, DumpFormInfoByBundleName success", __func__);
378         resultReceiver_ = formInfos;
379     } else {
380         APP_LOGE("'fm query' failed to query form info.");
381     }
382     APP_LOGI("%{public}s end, formInfo: %{public}s", __func__, resultReceiver_.c_str());
383 
384     return result;
385 }
386 /**
387  * @brief Query form infos by form id.
388  * @param formId The id of the form.
389  * @return Returns ERR_OK on success, others on failure.
390  */
QueryFormInfoByFormId(const std::int64_t formId)391 int32_t FormMgrShellCommand::QueryFormInfoByFormId(const std::int64_t formId)
392 {
393     APP_LOGI("%{public}s start, formId: %{public}" PRId64 "", __func__, formId);
394 
395     int errCode = ConnectFms();
396     if(errCode != OHOS::ERR_OK) {
397         return errCode;
398     }
399 
400     std::string formInfo;
401     MessageParcel data;
402     if (!WriteInterfaceToken(data)) {
403         APP_LOGE("%{public}s, failed to write interface token", __func__);
404         return ERR_APPEXECFWK_PARCEL_ERROR;
405     }
406     if (!data.WriteInt64(formId)) {
407         APP_LOGE("%{public}s, failed to write formId", __func__);
408         return ERR_APPEXECFWK_PARCEL_ERROR;
409     }
410 
411     int result = GetStringInfo(IFormMgr::Message::FORM_MGR_FORM_INFOS_BY_ID, data, formInfo);
412     if (result == ERR_OK) {
413         resultReceiver_ = formInfo;
414     }  else if(result == OHOS::ERR_APPEXECFWK_FORM_NOT_EXIST_ID) {
415         APP_LOGW("'fm query' no form info.");
416     } else {
417         APP_LOGE("'fm query' failed to query form info.");
418     }
419     APP_LOGI("%{public}s end, formInfo: %{public}s", __func__, resultReceiver_.c_str());
420 
421     return result;
422 }
WriteInterfaceToken(MessageParcel & data)423 bool FormMgrShellCommand::WriteInterfaceToken(MessageParcel &data)
424 {
425     if (!data.WriteInterfaceToken(IFormMgr::GetDescriptor())) {
426         APP_LOGE("%{public}s, failed to write interface token", __func__);
427         return false;
428     }
429     return true;
430 }
GetStringInfo(IFormMgr::Message code,MessageParcel & data,std::string & stringInfo)431 int FormMgrShellCommand::GetStringInfo(IFormMgr::Message code, MessageParcel &data, std::string &stringInfo)
432 {
433     int error;
434     MessageParcel reply;
435     error = SendTransactCmd(code, data, reply);
436     if (error != ERR_OK) {
437         return error;
438     }
439 
440     error = reply.ReadInt32();
441     if (error != ERR_OK) {
442         APP_LOGE("%{public}s, failed to read reply result: %{public}d", __func__, error);
443         return error;
444     }
445     std::vector<std::string> stringInfoList;
446     if (!reply.ReadStringVector(&stringInfoList)) {
447         APP_LOGE("%{public}s, failed to read string vector from reply", __func__);
448         return false;
449     }
450     if (stringInfoList.empty()) {
451         APP_LOGI("%{public}s, No string info", __func__);
452         return ERR_APPEXECFWK_FORM_NOT_EXIST_ID;
453     }
454     for (auto &info : stringInfoList) {
455         stringInfo += info;
456     }
457     APP_LOGD("%{public}s, get string info success", __func__);
458     return ERR_OK;
459 }
SendTransactCmd(IFormMgr::Message code,MessageParcel & data,MessageParcel & reply)460 int FormMgrShellCommand::SendTransactCmd(IFormMgr::Message code, MessageParcel &data, MessageParcel &reply)
461 {
462     MessageOption option(MessageOption::TF_SYNC);
463 
464     if (!remoteObject_) {
465         APP_LOGE("%{public}s, failed to get remote object, cmd: %{public}d", __func__, code);
466         return ERR_APPEXECFWK_SERVICE_NOT_CONNECTED;
467     }
468     int32_t result = remoteObject_->SendRequest(static_cast<uint32_t>(code), data, reply, option);
469     if (result != ERR_OK) {
470         APP_LOGE("%{public}s, failed to SendRequest: %{public}d, cmd: %{public}d", __func__, result, code);
471         return result;
472     }
473     return ERR_OK;
474 }
475 /**
476  * @brief Connect form manager service.
477  * @return Returns ERR_OK on success, others on failure.
478  */
ConnectFms()479 int32_t FormMgrShellCommand::ConnectFms()
480 {
481     if(remoteObject_ != nullptr) {
482         return OHOS::ERR_OK;
483     }
484     sptr<ISystemAbilityManager> systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
485     if (systemManager == nullptr) {
486         APP_LOGE("%{private}s:fail to get system ability manager", __func__);
487         return ERR_APPEXECFWK_FORM_GET_FMS_FAILED;
488     }
489     remoteObject_ = systemManager->GetSystemAbility(FORM_MGR_SERVICE_ID);
490     if (remoteObject_ == nullptr) {
491         APP_LOGE("%{private}s:fail to connect FormMgrService", __func__);
492         return ERR_APPEXECFWK_FORM_GET_FMS_FAILED;
493     }
494 
495     APP_LOGI("%{public}s end, get fms proxy success", __func__);
496     return OHOS::ERR_OK;
497 }
498 }  // namespace AppExecFwk
499 }  // namespace OHOS