1 /*
2 * Copyright (c) 2023-2024 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 "ability_config.h"
19 #include "ability_manager_errors.h"
20 #include "hilog_tag_wrapper.h"
21 #include "insight_intent_execute_callback_interface.h"
22 #include "insight_intent_utils.h"
23 #include "permission_verification.h"
24 #include "want_params_wrapper.h"
25 #include "time_util.h"
26 #include "res_sched_util.h"
27
28 namespace OHOS {
29 namespace AAFwk {
30 namespace {
31 constexpr size_t INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE = 256;
32 constexpr char EXECUTE_INSIGHT_INTENT_PERMISSION[] = "ohos.permission.EXECUTE_INSIGHT_INTENT";
33 constexpr int32_t OPERATION_DURATION = 10000;
34 }
35 using namespace AppExecFwk;
36
OnRemoteDied(const wptr<OHOS::IRemoteObject> & remote)37 void InsightIntentExecuteRecipient::OnRemoteDied(const wptr<OHOS::IRemoteObject> &remote)
38 {
39 TAG_LOGD(AAFwkTag::INTENT, "InsightIntentExecuteRecipient OnRemoteDied, %{public}" PRIu64, intentId_);
40 auto object = remote.promote();
41 if (object == nullptr) {
42 TAG_LOGE(AAFwkTag::INTENT, "null object");
43 return;
44 }
45 DelayedSingleton<InsightIntentExecuteManager>::GetInstance()->RemoteDied(intentId_);
46 }
47
48 InsightIntentExecuteManager::InsightIntentExecuteManager() = default;
49
50 InsightIntentExecuteManager::~InsightIntentExecuteManager() = default;
51
CheckAndUpdateParam(uint64_t key,const sptr<IRemoteObject> & callerToken,const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> & param,std::string callerBundleName)52 int32_t InsightIntentExecuteManager::CheckAndUpdateParam(uint64_t key, const sptr<IRemoteObject> &callerToken,
53 const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> ¶m, std::string callerBundleName)
54 {
55 int32_t result = CheckCallerPermission();
56 if (result != ERR_OK) {
57 return result;
58 }
59 if (callerToken == nullptr) {
60 TAG_LOGE(AAFwkTag::INTENT, "null callerToken");
61 return ERR_INVALID_VALUE;
62 }
63 if (param == nullptr) {
64 TAG_LOGE(AAFwkTag::INTENT, "null param");
65 return ERR_INVALID_VALUE;
66 }
67 if (param->bundleName_.empty() || param->moduleName_.empty() || param->abilityName_.empty() ||
68 param->insightIntentName_.empty()) {
69 TAG_LOGE(AAFwkTag::INTENT, "invalid param");
70 return ERR_INVALID_VALUE;
71 }
72 uint64_t intentId = 0;
73 result = AddRecord(key, callerToken, param->bundleName_, intentId, callerBundleName);
74 if (result != ERR_OK) {
75 return result;
76 }
77
78 param->insightIntentId_ = intentId;
79 return ERR_OK;
80 }
81
CheckAndUpdateWant(Want & want,ExecuteMode executeMode,std::string callerBundleName)82 int32_t InsightIntentExecuteManager::CheckAndUpdateWant(Want &want, ExecuteMode executeMode,
83 std::string callerBundleName)
84 {
85 auto uriVec = want.GetStringArrayParam(AbilityConfig::PARAMS_STREAM);
86 auto uriVecTemp = want.GetStringArrayParam(INSIGHT_INTENT_EXECUTE_PARAM_URI);
87 uriVec.insert(uriVec.begin(), uriVecTemp.begin(), uriVecTemp.end());
88 want.SetParam(AbilityConfig::PARAMS_STREAM, uriVec);
89 auto myflags = want.GetIntParam(INSIGHT_INTENT_EXECUTE_PARAM_FLAGS, 0);
90 myflags |= want.GetFlags();
91 want.SetFlags(myflags);
92
93 int32_t result = IsValidCall(want);
94 if (result != ERR_OK) {
95 return result;
96 }
97 uint64_t intentId = 0;
98 ElementName elementName = want.GetElement();
99 result = AddRecord(0, nullptr, want.GetBundle(), intentId, callerBundleName);
100 if (result != ERR_OK) {
101 return result;
102 }
103
104 std::string srcEntry;
105 auto ret = AbilityRuntime::InsightIntentUtils::GetSrcEntry(elementName,
106 want.GetStringParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME), executeMode, srcEntry);
107 if (ret != ERR_OK || srcEntry.empty()) {
108 TAG_LOGE(AAFwkTag::INTENT, "empty srcEntry");
109 return ERR_INVALID_VALUE;
110 }
111 want.SetParam(INSIGHT_INTENT_SRC_ENTRY, srcEntry);
112 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_ID, std::to_string(intentId));
113 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_MODE, executeMode);
114 TAG_LOGD(AAFwkTag::INTENT, "check done. insightIntentId: %{public}" PRIu64, intentId);
115 return ERR_OK;
116 }
117
AddRecord(uint64_t key,const sptr<IRemoteObject> & callerToken,const std::string & bundleName,uint64_t & intentId,const std::string & callerBundleName)118 int32_t InsightIntentExecuteManager::AddRecord(uint64_t key, const sptr<IRemoteObject> &callerToken,
119 const std::string &bundleName, uint64_t &intentId, const std::string &callerBundleName)
120 {
121 std::lock_guard<ffrt::mutex> lock(mutex_);
122 intentId = ++intentIdCount_;
123 auto record = std::make_shared<InsightIntentExecuteRecord>();
124 record->key = key;
125 record->state = InsightIntentExecuteState::EXECUTING;
126 record->callerToken = callerToken;
127 record->bundleName = bundleName;
128 record->callerBundleName = callerBundleName;
129 if (callerToken != nullptr) {
130 record->deathRecipient = sptr<InsightIntentExecuteRecipient>::MakeSptr(intentId);
131 callerToken->AddDeathRecipient(record->deathRecipient);
132 }
133
134 // replace
135 records_[intentId] = record;
136 if (intentId > INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE) {
137 // save the latest INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE records
138 records_.erase(intentId - INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE);
139 }
140 TAG_LOGD(AAFwkTag::INTENT, "init done, records_ size: %{public}zu", records_.size());
141 return ERR_OK;
142 }
143
RemoveExecuteIntent(uint64_t intentId)144 int32_t InsightIntentExecuteManager::RemoveExecuteIntent(uint64_t intentId)
145 {
146 std::lock_guard<ffrt::mutex> lock(mutex_);
147 records_.erase(intentId);
148 return ERR_OK;
149 }
150
ExecuteIntentDone(uint64_t intentId,int32_t resultCode,const AppExecFwk::InsightIntentExecuteResult & result)151 int32_t InsightIntentExecuteManager::ExecuteIntentDone(uint64_t intentId, int32_t resultCode,
152 const AppExecFwk::InsightIntentExecuteResult &result)
153 {
154 std::lock_guard<ffrt::mutex> lock(mutex_);
155 auto findResult = records_.find(intentId);
156 if (findResult == records_.end()) {
157 TAG_LOGE(AAFwkTag::INTENT, "intent not found, id: %{public}" PRIu64, intentId);
158 return ERR_INVALID_VALUE;
159 }
160
161 std::shared_ptr<InsightIntentExecuteRecord> record = findResult->second;
162 if (record == nullptr) {
163 TAG_LOGE(AAFwkTag::INTENT, "null record, id: %{public}" PRIu64, intentId);
164 return ERR_INVALID_VALUE;
165 }
166
167 TAG_LOGD(AAFwkTag::INTENT, "callback start, id:%{public}" PRIu64, intentId);
168 if (record->state != InsightIntentExecuteState::EXECUTING) {
169 TAG_LOGW(AAFwkTag::INTENT, "insight intent execute state is not EXECUTING, id:%{public}" PRIu64, intentId);
170 return ERR_INVALID_OPERATION;
171 }
172 record->state = InsightIntentExecuteState::EXECUTE_DONE;
173 sptr<IInsightIntentExecuteCallback> remoteCallback = iface_cast<IInsightIntentExecuteCallback>(record->callerToken);
174 if (remoteCallback == nullptr) {
175 TAG_LOGE(AAFwkTag::INTENT, "intentExecuteCallback empty");
176 return ERR_INVALID_VALUE;
177 }
178 remoteCallback->OnExecuteDone(record->key, resultCode, result);
179 if (record->callerToken != nullptr) {
180 record->callerToken->RemoveDeathRecipient(record->deathRecipient);
181 record->callerToken = nullptr;
182 }
183 TAG_LOGD(AAFwkTag::INTENT, "execute done, records_ size: %{public}zu", records_.size());
184 return ERR_OK;
185 }
186
RemoteDied(uint64_t intentId)187 int32_t InsightIntentExecuteManager::RemoteDied(uint64_t intentId)
188 {
189 std::lock_guard<ffrt::mutex> lock(mutex_);
190 auto result = records_.find(intentId);
191 if (result == records_.end()) {
192 TAG_LOGE(AAFwkTag::INTENT, "intent not found, id: %{public}" PRIu64, intentId);
193 return ERR_INVALID_VALUE;
194 }
195 if (result->second == nullptr) {
196 TAG_LOGE(AAFwkTag::INTENT, "null intent record , id: %{public}" PRIu64, intentId);
197 return ERR_INVALID_VALUE;
198 }
199 result->second->callerToken = nullptr;
200 result->second->state = InsightIntentExecuteState::REMOTE_DIED;
201 return ERR_OK;
202 }
203
GetBundleName(uint64_t intentId,std::string & bundleName) const204 int32_t InsightIntentExecuteManager::GetBundleName(uint64_t intentId, std::string &bundleName) const
205 {
206 std::lock_guard<ffrt::mutex> lock(mutex_);
207 auto result = records_.find(intentId);
208 if (result == records_.end()) {
209 TAG_LOGE(AAFwkTag::INTENT, "intent not found, id: %{public}" PRIu64, intentId);
210 return ERR_INVALID_VALUE;
211 }
212 if (result->second == nullptr) {
213 TAG_LOGE(AAFwkTag::INTENT, "null intent record,id: %{public}" PRIu64, intentId);
214 return ERR_INVALID_VALUE;
215 }
216 bundleName = result->second->bundleName;
217 return ERR_OK;
218 }
219
GetCallerBundleName(uint64_t intentId,std::string & callerBundleName) const220 int32_t InsightIntentExecuteManager::GetCallerBundleName(uint64_t intentId, std::string &callerBundleName) const
221 {
222 std::lock_guard<ffrt::mutex> lock(mutex_);
223 auto result = records_.find(intentId);
224 if (result == records_.end()) {
225 TAG_LOGE(AAFwkTag::INTENT, "intent not found, id: %{public}" PRIu64, intentId);
226 return ERR_INVALID_VALUE;
227 }
228 if (result->second == nullptr) {
229 TAG_LOGE(AAFwkTag::INTENT, "null intent record,id: %{public}" PRIu64, intentId);
230 return ERR_INVALID_VALUE;
231 }
232 callerBundleName = result->second->callerBundleName;
233 return ERR_OK;
234 }
235
AddWantUirsAndFlagsFromParam(const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> & param,Want & want)236 int32_t InsightIntentExecuteManager::AddWantUirsAndFlagsFromParam(
237 const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> ¶m, Want &want)
238 {
239 if (param == nullptr) {
240 TAG_LOGE(AAFwkTag::INTENT, "null param");
241 return ERR_INVALID_VALUE;
242 }
243 if (param->uris_.size() > 0) {
244 auto uriVec = want.GetStringArrayParam(AbilityConfig::PARAMS_STREAM);
245 for (auto &uri : param->uris_) {
246 if (!uri.empty()) {
247 uriVec.insert(uriVec.begin(), uri);
248 }
249 }
250 want.SetParam(AbilityConfig::PARAMS_STREAM, uriVec);
251 auto flags = want.GetFlags();
252 flags |= param->flags_;
253 want.SetFlags(flags);
254 }
255 return ERR_OK;
256 }
257
GenerateWant(const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> & param,Want & want)258 int32_t InsightIntentExecuteManager::GenerateWant(
259 const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> ¶m, Want &want)
260 {
261 if (param == nullptr) {
262 TAG_LOGE(AAFwkTag::INTENT, "null param");
263 return ERR_INVALID_VALUE;
264 }
265 want.SetElementName("", param->bundleName_, param->abilityName_, param->moduleName_);
266
267 if (param->insightIntentParam_ != nullptr) {
268 sptr<AAFwk::IWantParams> pExecuteParams = WantParamWrapper::Box(*param->insightIntentParam_);
269 if (pExecuteParams != nullptr) {
270 WantParams wantParams;
271 wantParams.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_PARAM, pExecuteParams);
272 want.SetParams(wantParams);
273 }
274 }
275
276 std::string srcEntry;
277 auto ret = AbilityRuntime::InsightIntentUtils::GetSrcEntry(want.GetElement(), param->insightIntentName_,
278 static_cast<AppExecFwk::ExecuteMode>(param->executeMode_), srcEntry);
279 if (!srcEntry.empty()) {
280 want.SetParam(INSIGHT_INTENT_SRC_ENTRY, srcEntry);
281 } else if (ret == ERR_INSIGHT_INTENT_GET_PROFILE_FAILED &&
282 param->executeMode_ == AppExecFwk::ExecuteMode::UI_ABILITY_FOREGROUND) {
283 TAG_LOGI(AAFwkTag::INTENT, "insight intent srcEntry invalid, try free install ondemand");
284 std::string startTime = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
285 std::chrono::system_clock::now().time_since_epoch()).count());
286 want.SetParam(Want::PARAM_RESV_START_TIME, startTime);
287 want.AddFlags(Want::FLAG_INSTALL_ON_DEMAND);
288 } else {
289 TAG_LOGE(AAFwkTag::INTENT, "insight intent srcEntry invalid");
290 return ERR_INVALID_VALUE;
291 }
292
293 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME, param->insightIntentName_);
294 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_MODE, param->executeMode_);
295 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_ID, std::to_string(param->insightIntentId_));
296 if (param->displayId_ != INVALID_DISPLAY_ID) {
297 want.SetParam(Want::PARAM_RESV_DISPLAY_ID, param->displayId_);
298 TAG_LOGD(AAFwkTag::INTENT, "Generate want with displayId: %{public}d", param->displayId_);
299 }
300
301 return AddWantUirsAndFlagsFromParam(param, want);
302 }
303
IsValidCall(const Want & want)304 int32_t InsightIntentExecuteManager::IsValidCall(const Want &want)
305 {
306 std::string insightIntentName = want.GetStringParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME);
307 if (insightIntentName.empty()) {
308 TAG_LOGE(AAFwkTag::INTENT, "empty insightIntentName");
309 return ERR_INVALID_VALUE;
310 }
311 TAG_LOGD(AAFwkTag::INTENT, "insightIntentName: %{public}s", insightIntentName.c_str());
312
313 int32_t ret = CheckCallerPermission();
314 if (ret != ERR_OK) {
315 return ret;
316 }
317 return ERR_OK;
318 }
319
CheckCallerPermission()320 int32_t InsightIntentExecuteManager::CheckCallerPermission()
321 {
322 bool isSystemAppCall = PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI();
323 if (!isSystemAppCall) {
324 TAG_LOGE(AAFwkTag::INTENT, "system-api cannot use");
325 return ERR_NOT_SYSTEM_APP;
326 }
327
328 bool isCallingPerm = PermissionVerification::GetInstance()->VerifyCallingPermission(
329 EXECUTE_INSIGHT_INTENT_PERMISSION);
330 if (!isCallingPerm) {
331 TAG_LOGE(AAFwkTag::INTENT, "permission %{public}s verification failed", EXECUTE_INSIGHT_INTENT_PERMISSION);
332 return ERR_PERMISSION_DENIED;
333 }
334 return ERR_OK;
335 }
336
SetIntentExemptionInfo(int32_t uid)337 void InsightIntentExecuteManager::SetIntentExemptionInfo(int32_t uid)
338 {
339 std::lock_guard<ffrt::mutex> guard(intentExemptionLock_);
340 std::map<int32_t, int64_t>::iterator iter = intentExemptionDeadlineTime_.find(uid);
341 intentExemptionDeadlineTime_[uid] = AbilityRuntime::TimeUtil::CurrentTimeMillis();
342 }
343
CheckIntentIsExemption(int32_t uid)344 bool InsightIntentExecuteManager::CheckIntentIsExemption(int32_t uid)
345 {
346 std::lock_guard<ffrt::mutex> guard(intentExemptionLock_);
347 if (intentExemptionDeadlineTime_.find(uid) != intentExemptionDeadlineTime_.end()) {
348 if (AbilityRuntime::TimeUtil::CurrentTimeMillis() - INTENT_EXEMPTION_DURATION <=
349 intentExemptionDeadlineTime_[uid]) {
350 TAG_LOGD(AAFwkTag::ABILITYMGR, "exemption check uid:%{public}d", uid);
351 return true;
352 } else {
353 intentExemptionDeadlineTime_.erase(uid);
354 return false;
355 }
356 }
357 return false;
358 }
359
GetAllIntentExemptionInfo() const360 std::map<int32_t, int64_t> InsightIntentExecuteManager::GetAllIntentExemptionInfo() const
361 {
362 std::lock_guard<ffrt::mutex> guard(intentExemptionLock_);
363 return intentExemptionDeadlineTime_;
364 }
365 } // namespace AAFwk
366 } // namespace OHOS
367