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_manager_errors.h"
19 #include "hilog_tag_wrapper.h"
20 #include "insight_intent_execute_callback_interface.h"
21 #include "insight_intent_utils.h"
22 #include "permission_verification.h"
23 #include "want_params_wrapper.h"
24
25 namespace OHOS {
26 namespace AAFwk {
27 namespace {
28 constexpr size_t INSIGHT_INTENT_EXECUTE_RECORDS_MAX_SIZE = 256;
29 constexpr char EXECUTE_INSIGHT_INTENT_PERMISSION[] = "ohos.permission.EXECUTE_INSIGHT_INTENT";
30 }
31 using namespace AppExecFwk;
32
OnRemoteDied(const wptr<OHOS::IRemoteObject> & remote)33 void InsightIntentExecuteRecipient::OnRemoteDied(const wptr<OHOS::IRemoteObject> &remote)
34 {
35 TAG_LOGD(AAFwkTag::INTENT, "InsightIntentExecuteRecipient OnRemoteDied, %{public}" PRIu64, intentId_);
36 auto object = remote.promote();
37 if (object == nullptr) {
38 TAG_LOGE(AAFwkTag::INTENT, "null remote object");
39 return;
40 }
41 DelayedSingleton<InsightIntentExecuteManager>::GetInstance()->RemoteDied(intentId_);
42 }
43
44 InsightIntentExecuteManager::InsightIntentExecuteManager() = default;
45
46 InsightIntentExecuteManager::~InsightIntentExecuteManager() = default;
47
CheckAndUpdateParam(uint64_t key,const sptr<IRemoteObject> & callerToken,const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> & param)48 int32_t InsightIntentExecuteManager::CheckAndUpdateParam(uint64_t key, const sptr<IRemoteObject> &callerToken,
49 const std::shared_ptr<AppExecFwk::InsightIntentExecuteParam> ¶m)
50 {
51 int32_t result = CheckCallerPermission();
52 if (result != ERR_OK) {
53 return result;
54 }
55 if (callerToken == nullptr) {
56 TAG_LOGE(AAFwkTag::INTENT, "null callerToken");
57 return ERR_INVALID_VALUE;
58 }
59 if (param == nullptr) {
60 TAG_LOGE(AAFwkTag::INTENT, "null param");
61 return ERR_INVALID_VALUE;
62 }
63 if (param->bundleName_.empty() || param->moduleName_.empty() || param->abilityName_.empty() ||
64 param->insightIntentName_.empty()) {
65 TAG_LOGE(AAFwkTag::INTENT, "invalid param");
66 return ERR_INVALID_VALUE;
67 }
68 uint64_t intentId = 0;
69 result = AddRecord(key, callerToken, param->bundleName_, intentId);
70 if (result != ERR_OK) {
71 return result;
72 }
73
74 param->insightIntentId_ = intentId;
75 return ERR_OK;
76 }
77
CheckAndUpdateWant(Want & want,ExecuteMode executeMode)78 int32_t InsightIntentExecuteManager::CheckAndUpdateWant(Want &want, ExecuteMode executeMode)
79 {
80 int32_t result = IsValidCall(want);
81 if (result != ERR_OK) {
82 return result;
83 }
84 uint64_t intentId = 0;
85 ElementName elementName = want.GetElement();
86 result = AddRecord(0, nullptr, want.GetBundle(), intentId);
87 if (result != ERR_OK) {
88 return result;
89 }
90
91 std::string srcEntry;
92 auto ret = AbilityRuntime::InsightIntentUtils::GetSrcEntry(elementName,
93 want.GetStringParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME), executeMode, srcEntry);
94 if (ret != ERR_OK || srcEntry.empty()) {
95 TAG_LOGE(AAFwkTag::INTENT, "empty srcEntry");
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 TAG_LOGD(AAFwkTag::INTENT, "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 TAG_LOGD(AAFwkTag::INTENT, "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 TAG_LOGE(AAFwkTag::INTENT, "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 TAG_LOGE(AAFwkTag::INTENT, "intent record is null, id: %{public}" PRIu64, intentId);
150 return ERR_INVALID_VALUE;
151 }
152
153 TAG_LOGD(AAFwkTag::INTENT, "callback start, id:%{public}" PRIu64, intentId);
154 if (record->state != InsightIntentExecuteState::EXECUTING) {
155 TAG_LOGW(AAFwkTag::INTENT, "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 TAG_LOGE(AAFwkTag::INTENT, "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 TAG_LOGD(AAFwkTag::INTENT, "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 TAG_LOGE(AAFwkTag::INTENT, "intent not found, id: %{public}" PRIu64, intentId);
179 return ERR_INVALID_VALUE;
180 }
181 if (result->second == nullptr) {
182 TAG_LOGE(AAFwkTag::INTENT, "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 TAG_LOGE(AAFwkTag::INTENT, "intent not found, id: %{public}" PRIu64, intentId);
196 return ERR_INVALID_VALUE;
197 }
198 if (result->second == nullptr) {
199 TAG_LOGE(AAFwkTag::INTENT, "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 TAG_LOGE(AAFwkTag::INTENT, "null param");
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 std::string srcEntry;
225 auto ret = AbilityRuntime::InsightIntentUtils::GetSrcEntry(want.GetElement(), param->insightIntentName_,
226 static_cast<AppExecFwk::ExecuteMode>(param->executeMode_), srcEntry);
227 if (!srcEntry.empty()) {
228 want.SetParam(INSIGHT_INTENT_SRC_ENTRY, srcEntry);
229 } else if (ret == ERR_INSIGHT_INTENT_GET_PROFILE_FAILED &&
230 param->executeMode_ == AppExecFwk::ExecuteMode::UI_ABILITY_FOREGROUND) {
231 TAG_LOGI(AAFwkTag::INTENT, "Insight intent srcEntry invalid, may need free install on demand");
232 std::string startTime = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
233 std::chrono::system_clock::now().time_since_epoch()).count());
234 want.SetParam(Want::PARAM_RESV_START_TIME, startTime);
235 want.AddFlags(Want::FLAG_INSTALL_ON_DEMAND);
236 } else {
237 TAG_LOGE(AAFwkTag::INTENT, "Insight intent srcEntry invalid");
238 return ERR_INVALID_VALUE;
239 }
240
241 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME, param->insightIntentName_);
242 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_MODE, param->executeMode_);
243 want.SetParam(INSIGHT_INTENT_EXECUTE_PARAM_ID, std::to_string(param->insightIntentId_));
244 if (param->displayId_ != INVALID_DISPLAY_ID) {
245 want.SetParam(Want::PARAM_RESV_DISPLAY_ID, param->displayId_);
246 TAG_LOGD(AAFwkTag::INTENT, "Generate want with displayId: %{public}d", param->displayId_);
247 }
248 return ERR_OK;
249 }
250
IsValidCall(const Want & want)251 int32_t InsightIntentExecuteManager::IsValidCall(const Want &want)
252 {
253 std::string insightIntentName = want.GetStringParam(INSIGHT_INTENT_EXECUTE_PARAM_NAME);
254 if (insightIntentName.empty()) {
255 TAG_LOGE(AAFwkTag::INTENT, "empty insightIntentName");
256 return ERR_INVALID_VALUE;
257 }
258 TAG_LOGD(AAFwkTag::INTENT, "insightIntentName: %{public}s", insightIntentName.c_str());
259
260 int32_t ret = CheckCallerPermission();
261 if (ret != ERR_OK) {
262 return ret;
263 }
264 return ERR_OK;
265 }
266
CheckCallerPermission()267 int32_t InsightIntentExecuteManager::CheckCallerPermission()
268 {
269 bool isSystemAppCall = PermissionVerification::GetInstance()->JudgeCallerIsAllowedToUseSystemAPI();
270 if (!isSystemAppCall) {
271 TAG_LOGE(AAFwkTag::INTENT, "The caller is not system-app, can not use system-api");
272 return ERR_NOT_SYSTEM_APP;
273 }
274
275 bool isCallingPerm = PermissionVerification::GetInstance()->VerifyCallingPermission(
276 EXECUTE_INSIGHT_INTENT_PERMISSION);
277 if (!isCallingPerm) {
278 TAG_LOGE(AAFwkTag::INTENT, "Permission %{public}s verification failed", EXECUTE_INSIGHT_INTENT_PERMISSION);
279 return ERR_PERMISSION_DENIED;
280 }
281 return ERR_OK;
282 }
283 } // namespace AAFwk
284 } // namespace OHOS
285