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