1 /*
2 * Copyright (c) 2023 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 "insight_intent_execute_manager.h"
17
18 #include <cinttypes>
19
20 #include "ability_manager_errors.h"
21 #include "hilog_wrapper.h"
22 #include "insight_intent_execute_callback_interface.h"
23 #include "insight_intent_utils.h"
24 #include "permission_verification.h"
25 #include "want_params_wrapper.h"
26
27 namespace OHOS {
28 namespace AAFwk {
29 namespace {
30 constexpr size_t INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE = 256;
31 constexpr char EXECUTE_INSIGHT_INTENT_PERMISSION[] = "ohos.permission.EXECUTE_INSIGHT_INTENT";
32 }
33 using namespace AppExecFwk;
34
OnRemoteDied(const wptr<OHOS::IRemoteObject> & remote)35 void InsightIntentExecuteRecipient::OnRemoteDied(const wptr<OHOS::IRemoteObject> &remote)
36 {
37 HILOG_DEBUG("InsightIntentExecuteRecipient OnRemoteDied, %{public}" PRIu64, intentId_);
38 auto object = remote.promote();
39 if (object == nullptr) {
40 HILOG_ERROR("remote object is nullptr");
41 return;
42 }
43 DelayedSingleton<InsightIntentExecuteManager>::GetInstance()->RemoteDied(intentId_);
44 }
45
46 InsightIntentExecuteManager::InsightIntentExecuteManager() = default;
47
48 InsightIntentExecuteManager::~InsightIntentExecuteManager() = default;
49
CheckAndUpdateParam(uint64_t key,const sptr<IRemoteObject> & callerToken,const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> & param)50 int32_t InsightIntentExecuteManager::CheckAndUpdateParam(uint64_t key, const sptr<IRemoteObject> &callerToken,
51 const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> ¶m)
52 {
53 int32_t result = CheckCallerPermission();
54 if (result != ERR_OK) {
55 return result;
56 }
57 if (callerToken == nullptr) {
58 HILOG_ERROR("callerToken is nullptr");
59 return ERR_INVALID_VALUE;
60 }
61 if (param == nullptr) {
62 HILOG_ERROR("param is nullptr");
63 return ERR_INVALID_VALUE;
64 }
65 if (param->bundleName_.empty() || param->moduleName_.empty() || param->abilityName_.empty() ||
66 param->insightIntentName_.empty()) {
67 HILOG_ERROR("invalid param");
68 return ERR_INVALID_VALUE;
69 }
70 uint64_t intentId = 0;
71 result = AddRecord(key, callerToken, param->bundleName_, intentId);
72 if (result != ERR_OK) {
73 return result;
74 }
75
76 param->insightIntentId_ = intentId;
77 return ERR_OK;
78 }
79
CheckAndUpdateWant(Want & want,ExecuteMode executeMode)80 int32_t InsightIntentExecuteManager::CheckAndUpdateWant(Want &want, ExecuteMode executeMode)
81 {
82 int32_t result = IsValidCall(want);
83 if (result != ERR_OK) {
84 return result;
85 }
86 uint64_t intentId = 0;
87 ElementName elementName = want.GetElement();
88 result = AddRecord(0, nullptr, want.GetBundle(), intentId);
89 if (result != ERR_OK) {
90 return result;
91 }
92 auto srcEntry = AbilityRuntime::InsightIntentUtils::GetSrcEntry(elementName.GetBundleName(),
93 elementName.GetModuleName(), want.GetStringParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME));
94 if (srcEntry.empty()) {
95 HILOG_ERROR("Insight intent srcEntry invalid.");
96 return ERR_INVALID_VALUE;
97 }
98 want.SetParam(INSIGHT_INTENT_SRC_ENTRY, srcEntry);
99 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_ID, std::to_string(intentId));
100 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_MODE, executeMode);
101 HILOG_DEBUG("check done. insightIntentId: %{public}" PRIu64, intentId);
102 return ERR_OK;
103 }
104
AddRecord(uint64_t key,const sptr<IRemoteObject> & callerToken,const std::string & bundleName,uint64_t & intentId)105 int32_t InsightIntentExecuteManager::AddRecord(uint64_t key, const sptr<IRemoteObject> &callerToken,
106 const std::string &bundleName, uint64_t &intentId)
107 {
108 std::lock_guard<ffrt::mutex> lock(mutex_);
109 intentId = ++intentIdCount_;
110 auto record = std::make_shared<InsightIntentExecuteRecord>();
111 record->key = key;
112 record->state = InsightIntentExecuteState::EXECUTING;
113 record->callerToken = callerToken;
114 record->bundleName = bundleName;
115 if (callerToken != nullptr) {
116 record->deathRecipient = sptr<InsightIntentExecuteRecipient>::MakeSptr(intentId);
117 callerToken->AddDeathRecipient(record->deathRecipient);
118 }
119
120 // replace
121 records_[intentId] = record;
122 if (intentId > INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE) {
123 // save the latest INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE records
124 records_.erase(intentId - INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE);
125 }
126 HILOG_DEBUG("init done, records_ size: %{public}zu", records_.size());
127 return ERR_OK;
128 }
129
RemoveExecuteIntent(uint64_t intentId)130 int32_t InsightIntentExecuteManager::RemoveExecuteIntent(uint64_t intentId)
131 {
132 std::lock_guard<ffrt::mutex> lock(mutex_);
133 records_.erase(intentId);
134 return ERR_OK;
135 }
136
ExecuteIntentDone(uint64_t intentId,int32_t resultCode,const AppExecFwk::InsightIntentExecuteResult & result)137 int32_t InsightIntentExecuteManager::ExecuteIntentDone(uint64_t intentId, int32_t resultCode,
138 const AppExecFwk::InsightIntentExecuteResult &result)
139 {
140 std::lock_guard<ffrt::mutex> lock(mutex_);
141 auto findResult = records_.find(intentId);
142 if (findResult == records_.end()) {
143 HILOG_ERROR("intent not found, id: %{public}" PRIu64, intentId);
144 return ERR_INVALID_VALUE;
145 }
146
147 std::shared_ptr<InsightIntentExecuteRecord> record = findResult->second;
148 if (record == nullptr) {
149 HILOG_ERROR("intent record is null, id: %{public}" PRIu64, intentId);
150 return ERR_INVALID_VALUE;
151 }
152
153 HILOG_DEBUG("callback start, id:%{public}" PRIu64, intentId);
154 if (record->state != InsightIntentExecuteState::EXECUTING) {
155 HILOG_WARN("Insight intent execute state is not EXECUTING, id:%{public}" PRIu64, intentId);
156 return ERR_INVALID_OPERATION;
157 }
158 record->state = InsightIntentExecuteState::EXECUTE_DONE;
159 sptr<IInsightIntentExecuteCallback> remoteCallback = iface_cast<IInsightIntentExecuteCallback>(record->callerToken);
160 if (remoteCallback == nullptr) {
161 HILOG_ERROR("Failed to get IIntentExecuteCallback");
162 return ERR_INVALID_VALUE;
163 }
164 remoteCallback->OnExecuteDone(record->key, resultCode, result);
165 if (record->callerToken != nullptr) {
166 record->callerToken->RemoveDeathRecipient(record->deathRecipient);
167 record->callerToken = nullptr;
168 }
169 HILOG_DEBUG("execute done, records_ size: %{public}zu", records_.size());
170 return ERR_OK;
171 }
172
RemoteDied(uint64_t intentId)173 int32_t InsightIntentExecuteManager::RemoteDied(uint64_t intentId)
174 {
175 std::lock_guard<ffrt::mutex> lock(mutex_);
176 auto result = records_.find(intentId);
177 if (result == records_.end()) {
178 HILOG_ERROR("intent not found, id: %{public}" PRIu64, intentId);
179 return ERR_INVALID_VALUE;
180 }
181 if (result->second == nullptr) {
182 HILOG_ERROR("intent record is null, id: %{public}" PRIu64, intentId);
183 return ERR_INVALID_VALUE;
184 }
185 result->second->callerToken = nullptr;
186 result->second->state = InsightIntentExecuteState::REMOTE_DIED;
187 return ERR_OK;
188 }
189
GetBundleName(uint64_t intentId,std::string & bundleName) const190 int32_t InsightIntentExecuteManager::GetBundleName(uint64_t intentId, std::string &bundleName) const
191 {
192 std::lock_guard<ffrt::mutex> lock(mutex_);
193 auto result = records_.find(intentId);
194 if (result == records_.end()) {
195 HILOG_ERROR("intent not found, id: %{public}" PRIu64, intentId);
196 return ERR_INVALID_VALUE;
197 }
198 if (result->second == nullptr) {
199 HILOG_ERROR("intent record is null, id: %{public}" PRIu64, intentId);
200 return ERR_INVALID_VALUE;
201 }
202 bundleName = result->second->bundleName;
203 return ERR_OK;
204 }
205
GenerateWant(const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> & param,Want & want)206 int32_t InsightIntentExecuteManager::GenerateWant(
207 const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> ¶m, Want &want)
208 {
209 if (param == nullptr) {
210 HILOG_ERROR("param is nullptr");
211 return ERR_INVALID_VALUE;
212 }
213 want.SetElementName("", param->bundleName_, param->abilityName_, param->moduleName_);
214
215 if (param->insightIntentParam_ != nullptr) {
216 sptr<AAFwk::IWantParams> pExecuteParams = WantParamWrapper::Box(*param->insightIntentParam_);
217 if (pExecuteParams != nullptr) {
218 WantParams wantParams;
219 wantParams.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_PARAM, pExecuteParams);
220 want.SetParams(wantParams);
221 }
222 }
223
224 auto srcEntry = AbilityRuntime::InsightIntentUtils::GetSrcEntry(param->bundleName_, param->moduleName_,
225 param->insightIntentName_);
226 if (srcEntry.empty()) {
227 HILOG_ERROR("Insight intent srcEntry invalid.");
228 return ERR_INVALID_VALUE;
229 }
230 want.SetParam(INSIGHT_INTENT_SRC_ENTRY, srcEntry);
231
232 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME, param->insightIntentName_);
233 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_MODE, param->executeMode_);
234 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_ID, std::to_string(param->insightIntentId_));
235 return ERR_OK;
236 }
237
IsValidCall(const Want & want)238 int32_t InsightIntentExecuteManager::IsValidCall(const Want &want)
239 {
240 std::string insightIntentName = want.GetStringParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME);
241 if (insightIntentName.empty()) {
242 HILOG_ERROR("insightIntentName is empty");
243 return ERR_INVALID_VALUE;
244 }
245 HILOG_DEBUG("insightIntentName: %{public}s", insightIntentName.c_str());
246
247 int32_t ret = CheckCallerPermission();
248 if (ret != ERR_OK) {
249 return ret;
250 }
251 return ERR_OK;
252 }
253
CheckCallerPermission()254 int32_t InsightIntentExecuteManager::CheckCallerPermission()
255 {
256 bool isSystemAppCall = PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI();
257 if (!isSystemAppCall) {
258 HILOG_ERROR("The caller is not system-app, can not use system-api");
259 return ERR_NOT_SYSTEM_APP;
260 }
261
262 bool isCallingPerm = PermissionVerification::GetInstance()->VerifyCallingPermission(
263 EXECUTE_INSIGHT_INTENT_PERMISSION);
264 if (!isCallingPerm) {
265 HILOG_ERROR("Permission %{public}s verification failed", EXECUTE_INSIGHT_INTENT_PERMISSION);
266 return ERR_PERMISSION_DENIED;
267 }
268 return ERR_OK;
269 }
270 } // namespace AAFwk
271 } // namespace OHOS
272