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