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