• 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 "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