• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &param, 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> &param, 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> &param, 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