1 /*
2  * Copyright (c) 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 
16 #include "quick_fix_command.h"
17 
18 #include "app_log_wrapper.h"
19 #include "common_event_data.h"
20 #include "common_event_manager.h"
21 #include "common_event_support.h"
22 #include "quick_fix_manager_client.h"
23 #include "status_receiver_impl.h"
24 #include "want.h"
25 
26 namespace OHOS {
27 namespace AppExecFwk {
28 class ApplyQuickFixMonitor : public EventFwk::CommonEventSubscriber,
29                              public std::enable_shared_from_this<ApplyQuickFixMonitor> {
30 public:
ApplyQuickFixMonitor(const EventFwk::CommonEventSubscribeInfo & subscribeInfo,sptr<StatusReceiverImpl> receiver)31     ApplyQuickFixMonitor(const EventFwk::CommonEventSubscribeInfo &subscribeInfo, sptr<StatusReceiverImpl> receiver)
32         : EventFwk::CommonEventSubscriber(subscribeInfo), statusReceiver_(receiver)
33     {}
34 
35     virtual ~ApplyQuickFixMonitor() = default;
36 
OnReceiveEvent(const EventFwk::CommonEventData & eventData)37     void OnReceiveEvent(const EventFwk::CommonEventData &eventData)
38     {
39         APP_LOGD("function called.");
40         AAFwk::Want want = eventData.GetWant();
41         int32_t applyResult = want.GetIntParam("applyResult", -1);
42         std::string resultInfo = want.GetStringParam("applyResultInfo");
43         std::string bundleName = want.GetStringParam("bundleName");
44         APP_LOGD("bundleName: %{public}s, applyResult: %{public}d, resultInfo: %{public}s.",
45             bundleName.c_str(), applyResult, resultInfo.c_str());
46         resultInfo_ = resultInfo;
47         statusReceiver_->OnFinished(applyResult, resultInfo);
48     }
49 
GetResultInfo()50     std::string GetResultInfo()
51     {
52         return resultInfo_;
53     }
54 
55 private:
56     sptr<StatusReceiverImpl> statusReceiver_ = nullptr;
57     std::string resultInfo_;
58 };
59 
ApplyQuickFix(const std::vector<std::string> & quickFixFiles,std::string & resultInfo,bool isDebug)60 int32_t QuickFixCommand::ApplyQuickFix(const std::vector<std::string> &quickFixFiles, std::string &resultInfo,
61     bool isDebug)
62 {
63     if (quickFixFiles.empty()) {
64         resultInfo.append("quick fix file is empty.\n");
65         return ERR_INVALID_VALUE;
66     }
67 
68     for (auto file : quickFixFiles) {
69         APP_LOGI("apply hqf file %{private}s.", file.c_str());
70     }
71 
72     APP_LOGI("IsDEBUG is %d", isDebug);
73 
74     sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl());
75     if (statusReceiver == nullptr) {
76         resultInfo.append("Create status receiver failed.\n");
77         return ERR_INVALID_VALUE;
78     }
79 
80     EventFwk::MatchingSkills matchingSkills;
81     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_QUICK_FIX_APPLY_RESULT);
82     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
83     auto applyMonitor = std::make_shared<ApplyQuickFixMonitor>(subscribeInfo, statusReceiver);
84     EventFwk::CommonEventManager::SubscribeCommonEvent(applyMonitor);
85 
86     auto result = DelayedSingleton<AAFwk::QuickFixManagerClient>::GetInstance()->ApplyQuickFix(quickFixFiles, isDebug);
87     if (result == ERR_OK) {
88         APP_LOGD("Waiting apply finished.");
89         result = statusReceiver->GetResultCode();
90     }
91 
92     if (result == ERR_OK) {
93         resultInfo.append("apply quickfix succeed.\n");
94     } else {
95         if (applyMonitor->GetResultInfo().empty()) {
96             resultInfo.append("apply quickfix failed with errno: " + std::to_string(result) + ".\n");
97         } else {
98             resultInfo.append("apply quickfix failed with error: " + applyMonitor->GetResultInfo() + ".\n");
99         }
100     }
101 
102     return result;
103 }
104 
GetApplyedQuickFixInfo(const std::string & bundleName,std::string & resultInfo)105 int32_t QuickFixCommand::GetApplyedQuickFixInfo(const std::string &bundleName, std::string &resultInfo)
106 {
107     if (bundleName.empty()) {
108         resultInfo.append("bundle name is empty.\n");
109         return ERR_INVALID_VALUE;
110     }
111 
112     AAFwk::ApplicationQuickFixInfo quickFixInfo;
113     auto result = AAFwk::QuickFixManagerClient::GetInstance()->GetApplyedQuickFixInfo(bundleName, quickFixInfo);
114     if (result == ERR_OK) {
115         resultInfo.append("Information as follows:\n");
116         resultInfo.append(GetQuickFixInfoString(quickFixInfo));
117     } else {
118         resultInfo.append("Get quick fix info failed with errno " + std::to_string(result) + ".\n");
119     }
120 
121     return result;
122 }
123 
GetQuickFixInfoString(const AAFwk::ApplicationQuickFixInfo & quickFixInfo)124 std::string QuickFixCommand::GetQuickFixInfoString(const AAFwk::ApplicationQuickFixInfo &quickFixInfo)
125 {
126     std::string info = "ApplicationQuickFixInfo:\n";
127     info.append("  bundle name: " + quickFixInfo.bundleName + "\n");
128     info.append("  bundle version code: " + std::to_string(quickFixInfo.bundleVersionCode) + "\n");
129     info.append("  bundle version name: " + quickFixInfo.bundleVersionName + "\n");
130     AppqfInfo appqfInfo = quickFixInfo.appqfInfo;
131     info.append("  patch version code: " + std::to_string(appqfInfo.versionCode) + "\n");
132     info.append("  patch version name: " + appqfInfo.versionName + "\n");
133     info.append("  cpu abi: " + appqfInfo.cpuAbi + "\n");
134     info.append("  native library path: " + appqfInfo.nativeLibraryPath + "\n");
135     std::string type;
136     if (appqfInfo.type == AppExecFwk::QuickFixType::PATCH) {
137         type = "patch";
138     } else if (appqfInfo.type == AppExecFwk::QuickFixType::HOT_RELOAD) {
139         type = "hotreload";
140     }
141     info.append("  type: " + type + "\n");
142     for (auto hqfInfo : appqfInfo.hqfInfos) {
143         info.append("  ModuelQuickFixInfo:\n");
144         info.append("    module name: " + hqfInfo.moduleName + "\n");
145         info.append("    module sha256: " + hqfInfo.hapSha256 + "\n");
146         info.append("    file path: " + hqfInfo.hqfFilePath + "\n");
147     }
148 
149     return info;
150 }
151 } // namespace AppExecFwk
152 } // namespace OHOS