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 "ecological_rule/ability_ecological_rule_mgr_service.h"
17
18 #include "ability_manager_errors.h"
19 #include "iservice_registry.h"
20 #include "hilog_tag_wrapper.h"
21 #include "hitrace_meter.h"
22 #include "ipc_capacity_wrap.h"
23 #include "record_cost_time_util.h"
24
25 namespace OHOS {
26 using AAFwk::RecordCostTimeUtil;
27 namespace EcologicalRuleMgrService {
28
29 using namespace std::chrono;
30
31 static inline const std::u16string ERMS_INTERFACE_TOKEN =
32 u"ohos.cloud.ecologicalrulemgrservice.IEcologicalRuleMgrService";
33 constexpr int32_t CYCLE_LIMIT = 1000;
34 const int32_t ECOLOGICALRULEMANAGERSERVICE_ID = 6105;
35
36 std::mutex AbilityEcologicalRuleMgrServiceClient::instanceLock_;
37 std::mutex AbilityEcologicalRuleMgrServiceClient::proxyLock_;
38 sptr<AbilityEcologicalRuleMgrServiceClient> AbilityEcologicalRuleMgrServiceClient::instance_;
39 sptr<IAbilityEcologicalRuleMgrService> AbilityEcologicalRuleMgrServiceClient::ecologicalRuleMgrServiceProxy_;
40 sptr<IRemoteObject::DeathRecipient> AbilityEcologicalRuleMgrServiceClient::deathRecipient_;
41
42 std::string AbilityEcologicalRuleMgrServiceClient::ERMS_ORIGINAL_TARGET = "ecological_experience_original_target";
43
GetCurrentTimeMicro()44 inline int64_t GetCurrentTimeMicro()
45 {
46 return duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
47 }
48
~AbilityEcologicalRuleMgrServiceClient()49 AbilityEcologicalRuleMgrServiceClient::~AbilityEcologicalRuleMgrServiceClient()
50 {
51 std::lock_guard<std::mutex> autoLock(proxyLock_);
52 if (ecologicalRuleMgrServiceProxy_ != nullptr) {
53 auto remoteObj = ecologicalRuleMgrServiceProxy_->AsObject();
54 if (remoteObj != nullptr) {
55 remoteObj->RemoveDeathRecipient(deathRecipient_);
56 }
57 }
58 }
59
GetInstance()60 sptr<AbilityEcologicalRuleMgrServiceClient> AbilityEcologicalRuleMgrServiceClient::GetInstance()
61 {
62 if (instance_ == nullptr) {
63 std::lock_guard<std::mutex> autoLock(instanceLock_);
64 if (instance_ == nullptr) {
65 instance_ = new AbilityEcologicalRuleMgrServiceClient;
66 }
67 }
68 return instance_;
69 }
70
ConnectService()71 sptr<IAbilityEcologicalRuleMgrService> AbilityEcologicalRuleMgrServiceClient::ConnectService()
72 {
73 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
74 if (samgr == nullptr) {
75 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null samgr");
76 return nullptr;
77 }
78
79 auto systemAbility = samgr->CheckSystemAbility(ECOLOGICALRULEMANAGERSERVICE_ID);
80 if (systemAbility == nullptr) {
81 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null systemAbility");
82 return nullptr;
83 }
84
85 deathRecipient_ = new AbilityEcologicalRuleMgrServiceDeathRecipient();
86 systemAbility->AddDeathRecipient(deathRecipient_);
87
88 sptr<IAbilityEcologicalRuleMgrService> service = iface_cast<IAbilityEcologicalRuleMgrService>(systemAbility);
89 if (service == nullptr) {
90 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "erms transfered to foundation");
91 service = new AbilityEcologicalRuleMgrServiceProxy(systemAbility);
92 }
93 return service;
94 }
95
CheckConnectService()96 bool AbilityEcologicalRuleMgrServiceClient::CheckConnectService()
97 {
98 std::lock_guard<std::mutex> autoLock(proxyLock_);
99 if (ecologicalRuleMgrServiceProxy_ == nullptr) {
100 TAG_LOGW(AAFwkTag::ECOLOGICAL_RULE, "redo ConnectService");
101 ecologicalRuleMgrServiceProxy_ = ConnectService();
102 }
103 if (ecologicalRuleMgrServiceProxy_ == nullptr) {
104 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "Connect SA Failed");
105 return false;
106 }
107 return true;
108 }
109
OnRemoteSaDied(const wptr<IRemoteObject> & object)110 void AbilityEcologicalRuleMgrServiceClient::OnRemoteSaDied(const wptr<IRemoteObject> &object)
111 {
112 std::lock_guard<std::mutex> autoLock(proxyLock_);
113 ecologicalRuleMgrServiceProxy_ = ConnectService();
114 }
115
EvaluateResolveInfos(const AAFwk::Want & want,const AbilityCallerInfo & callerInfo,int32_t type,vector<AbilityInfo> & abilityInfos,const vector<AppExecFwk::ExtensionAbilityInfo> & extInfos)116 int32_t AbilityEcologicalRuleMgrServiceClient::EvaluateResolveInfos(const AAFwk::Want &want,
117 const AbilityCallerInfo &callerInfo, int32_t type, vector<AbilityInfo> &abilityInfos,
118 const vector<AppExecFwk::ExtensionAbilityInfo> &extInfos)
119 {
120 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
121 RecordCostTimeUtil("EvaluateResolveInfos");
122 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "want: %{private}s, callerInfo: %{public}s, type: %{public}d",
123 want.ToString().c_str(), callerInfo.ToString().c_str(), type);
124 if (!CheckConnectService()) {
125 return AAFwk::ERR_CONNECT_ERMS_FAILED;
126 }
127 return ecologicalRuleMgrServiceProxy_->EvaluateResolveInfos(want, callerInfo, type, abilityInfos);
128 }
129
QueryStartExperience(const OHOS::AAFwk::Want & want,const AbilityCallerInfo & callerInfo,AbilityExperienceRule & rule)130 int32_t AbilityEcologicalRuleMgrServiceClient::QueryStartExperience(const OHOS::AAFwk::Want &want,
131 const AbilityCallerInfo &callerInfo, AbilityExperienceRule &rule)
132 {
133 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
134 RecordCostTimeUtil("QueryStartExperience");
135 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "callerInfo: %{public}s, want: %{private}s", callerInfo.ToString().c_str(),
136 want.ToString().c_str());
137
138 if (!CheckConnectService()) {
139 return AAFwk::ERR_CONNECT_ERMS_FAILED;
140 }
141 int32_t res = ecologicalRuleMgrServiceProxy_->QueryStartExperience(want, callerInfo, rule);
142 if (rule.replaceWant != nullptr) {
143 rule.replaceWant->SetParam(ERMS_ORIGINAL_TARGET, want.ToString());
144 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE,
145 "queryStart finish: resultCode = %{public}d, sceneCode = %{public}s, replaceWant = %{private}s",
146 rule.resultCode, rule.sceneCode.c_str(), (*(rule.replaceWant)).ToString().c_str());
147 }
148 return res;
149 }
150
OnRemoteDied(const wptr<IRemoteObject> & object)151 void AbilityEcologicalRuleMgrServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
152 {
153 if (AbilityEcologicalRuleMgrServiceClient::GetInstance()) {
154 AbilityEcologicalRuleMgrServiceClient::GetInstance()->OnRemoteSaDied(object);
155 }
156 }
157
AbilityEcologicalRuleMgrServiceProxy(const sptr<IRemoteObject> & impl)158 AbilityEcologicalRuleMgrServiceProxy::AbilityEcologicalRuleMgrServiceProxy(
159 const sptr<IRemoteObject>& impl) : IRemoteProxy<IAbilityEcologicalRuleMgrService>(impl)
160 {}
161
EvaluateResolveInfos(const Want & want,const AbilityCallerInfo & callerInfo,int32_t type,std::vector<AbilityInfo> & abilityInfos)162 int32_t AbilityEcologicalRuleMgrServiceProxy::EvaluateResolveInfos(const Want &want,
163 const AbilityCallerInfo &callerInfo, int32_t type, std::vector<AbilityInfo> &abilityInfos)
164 {
165 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "called");
166 MessageParcel data;
167 AAFwk::ExtendMaxIpcCapacityForInnerWant(data);
168
169 if (!data.WriteInterfaceToken(ERMS_INTERFACE_TOKEN)) {
170 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write token failed");
171 return ERR_FAILED;
172 }
173
174 if (!data.WriteParcelable(&want)) {
175 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write want failed");
176 return ERR_FAILED;
177 }
178
179 if (!data.WriteInt32(type)) {
180 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write type failed");
181 return ERR_FAILED;
182 }
183
184 if (!data.WriteInt32(abilityInfos.size())) {
185 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write abilityInfos size failed");
186 return ERR_FAILED;
187 }
188
189 for (auto &abilityInfo : abilityInfos) {
190 if (!data.WriteParcelable(&abilityInfo)) {
191 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write abilityInfo failed");
192 return ERR_FAILED;
193 }
194 }
195
196 if (!data.WriteParcelable(&callerInfo)) {
197 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write callerInfo failed");
198 return ERR_FAILED;
199 }
200
201 MessageOption option = { MessageOption::TF_SYNC };
202 MessageParcel reply;
203
204 auto remote = Remote();
205 if (remote == nullptr) {
206 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null remote");
207 return ERR_FAILED;
208 }
209
210 int32_t ret = remote->SendRequest(EVALUATE_RESOLVE_INFO_CMD, data, reply, option);
211 if (ret != ERR_NONE) {
212 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "SendRequest error:%{public}d", ret);
213 return ERR_FAILED;
214 }
215
216 if (!ReadParcelableVector(abilityInfos, reply)) {
217 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "GetParcelableInfos fail");
218 }
219 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "end");
220 return ERR_OK;
221 }
222
223 template <typename T>
ReadParcelableVector(std::vector<T> & parcelableVector,MessageParcel & reply)224 bool AbilityEcologicalRuleMgrServiceProxy::ReadParcelableVector(std::vector<T> &parcelableVector, MessageParcel &reply)
225 {
226 int32_t infoSize = reply.ReadInt32();
227 if (infoSize > CYCLE_LIMIT) {
228 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "size too large");
229 return false;
230 }
231 parcelableVector.clear();
232 for (int32_t i = 0; i < infoSize; i++) {
233 sptr<T> info = reply.ReadParcelable<T>();
234 if (info == nullptr) {
235 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null info");
236 return false;
237 }
238 parcelableVector.emplace_back(*info);
239 }
240 return true;
241 }
242
QueryStartExperience(const Want & want,const AbilityCallerInfo & callerInfo,AbilityExperienceRule & rule)243 int32_t AbilityEcologicalRuleMgrServiceProxy::QueryStartExperience(const Want &want,
244 const AbilityCallerInfo &callerInfo, AbilityExperienceRule &rule)
245 {
246 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "called");
247 MessageParcel data;
248 AAFwk::ExtendMaxIpcCapacityForInnerWant(data);
249 if (!data.WriteInterfaceToken(ERMS_INTERFACE_TOKEN)) {
250 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write token failed");
251 return ERR_FAILED;
252 }
253
254 if (!data.WriteParcelable(&want)) {
255 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write want failed");
256 return ERR_FAILED;
257 }
258
259 if (!data.WriteParcelable(&callerInfo)) {
260 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "write callerInfo failed");
261 return ERR_FAILED;
262 }
263
264 MessageOption option = { MessageOption::TF_SYNC };
265 MessageParcel reply;
266
267 auto remote = Remote();
268 if (remote == nullptr) {
269 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null remote");
270 return ERR_FAILED;
271 }
272
273 int32_t ret = remote->SendRequest(QUERY_START_EXPERIENCE_CMD, data, reply, option);
274 if (ret != ERR_NONE) {
275 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "SendRequest error: %{public}d", ret);
276 return ERR_FAILED;
277 }
278
279 sptr<AbilityExperienceRule> sptrRule = reply.ReadParcelable<AbilityExperienceRule>();
280 if (sptrRule == nullptr) {
281 TAG_LOGE(AAFwkTag::ECOLOGICAL_RULE, "null sptrRule");
282 return ERR_FAILED;
283 }
284
285 rule = *sptrRule;
286 TAG_LOGD(AAFwkTag::ECOLOGICAL_RULE, "end");
287 return ERR_OK;
288 }
289 } // namespace EcologicalRuleMgrService
290 } // namespace OHOS
291