1 /*
2 * Copyright (c) 2023 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 "connection/screen_session_ability_connection.h"
17
18 #include <chrono>
19 #include <want.h>
20 #include <iservice_registry.h>
21 #include <system_ability_definition.h>
22
23 #include "ability_connection.h"
24 #include "extension_manager_client.h"
25 #include "ipc_skeleton.h"
26 #include "window_manager_hilog.h"
27
28 namespace OHOS::Rosen {
29 constexpr int32_t DEFAULT_VALUE = -1;
30 constexpr int32_t RES_FAILURE = -1;
31 constexpr int32_t RES_SUCCESS = 0;
32 constexpr uint32_t SEND_MESSAGE_SYNC_OUT_TIME = 800; // ms
33 constexpr uint32_t TRANS_RELEASE_BLOCK = 0;
34 constexpr uint32_t TRANS_FAILED_FOR_PRIVACY = 1;
35
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t resultCode)36 void ScreenSessionAbilityConnectionStub::OnAbilityConnectDone(
37 const AppExecFwk::ElementName &element,
38 const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
39 {
40 TLOGI(WmsLogTag::DMS, "OnAbilityConnectDone entry");
41 if (resultCode != ERR_OK) {
42 TLOGE(WmsLogTag::DMS, "ability connect failed, error code:%{public}d", resultCode);
43 return;
44 }
45 TLOGI(WmsLogTag::DMS, "ability connect success, ability name %{public}s", element.GetAbilityName().c_str());
46 if (remoteObject == nullptr) {
47 TLOGE(WmsLogTag::DMS, "get remoteObject failed");
48 return;
49 }
50 {
51 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
52 remoteObject_ = remoteObject;
53 }
54 if (!AddObjectDeathRecipient()) {
55 TLOGE(WmsLogTag::DMS, "AddObjectDeathRecipient failed");
56 return;
57 }
58
59 isConnected_.store(true);
60 connectedCv_.notify_all();
61 TLOGI(WmsLogTag::DMS, "OnAbilityConnectDone exit");
62 }
63
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int32_t resultCode)64 void ScreenSessionAbilityConnectionStub::OnAbilityDisconnectDone(
65 const AppExecFwk::ElementName &element, int32_t resultCode)
66 {
67 TLOGI(WmsLogTag::DMS, "OnAbilityDisconnectDone entry");
68 if (resultCode != ERR_OK) {
69 TLOGE(WmsLogTag::DMS, "ability disconnect failed, error code:%{public}d", resultCode);
70 }
71
72 TLOGI(WmsLogTag::DMS, "bundleName:%{public}s, abilityName:%{public}s, resultCode:%{public}d",
73 element.GetBundleName().c_str(), element.GetAbilityName().c_str(), resultCode);
74
75 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
76 if (remoteObject_ == nullptr) {
77 TLOGE(WmsLogTag::DMS, "remoteObject member is nullptr");
78 return;
79 }
80 remoteObject_->RemoveDeathRecipient(deathRecipient_);
81 remoteObject_ = nullptr;
82 isConnected_.store(false);
83 TLOGI(WmsLogTag::DMS, "OnAbilityDisconnectDone exit");
84 }
85
AddObjectDeathRecipient()86 bool ScreenSessionAbilityConnectionStub::AddObjectDeathRecipient()
87 {
88 sptr<ScreenSessionAbilityDeathRecipient> deathRecipient(
89 new(std::nothrow) ScreenSessionAbilityDeathRecipient([this] {
90 TLOGI(WmsLogTag::DMS, "add death recipient handler");
91 sendMessageWaitFlag_ = true;
92 blockSendMessageCV_.notify_all();
93 TLOGI(WmsLogTag::DMS, "blockSendMessageCV_ notify");
94 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
95 remoteObject_ = nullptr;
96 isConnected_.store(false);
97 }));
98
99 if (deathRecipient == nullptr) {
100 TLOGE(WmsLogTag::DMS, "create ScreenSessionAbilityDeathRecipient failed");
101 return false;
102 }
103 deathRecipient_ = deathRecipient;
104 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
105 if (remoteObject_ == nullptr) {
106 TLOGE(WmsLogTag::DMS, "get the remoteObject failed");
107 return false;
108 }
109 if (!remoteObject_->AddDeathRecipient(deathRecipient_)) {
110 TLOGE(WmsLogTag::DMS, "AddDeathRecipient failed");
111 return false;
112 }
113 return true;
114 }
115
IsAbilityConnected()116 bool ScreenSessionAbilityConnectionStub::IsAbilityConnected()
117 {
118 return isConnected_.load();
119 }
120
IsAbilityConnectedSync()121 bool ScreenSessionAbilityConnectionStub::IsAbilityConnectedSync()
122 {
123 std::unique_lock<std::mutex> lock(connectedMutex_);
124 connectedCv_.wait_for(lock, std::chrono::milliseconds(SEND_MESSAGE_SYNC_OUT_TIME));
125 return IsAbilityConnected();
126 }
127
SendMessageSync(int32_t transCode,MessageParcel & data,MessageParcel & reply)128 int32_t ScreenSessionAbilityConnectionStub::SendMessageSync(int32_t transCode,
129 MessageParcel &data, MessageParcel &reply)
130 {
131 std::unique_lock<std::mutex> lock(connectedMutex_);
132 connectedCv_.wait_for(lock, std::chrono::milliseconds(SEND_MESSAGE_SYNC_OUT_TIME));
133 if (!IsAbilityConnected()) {
134 TLOGE(WmsLogTag::DMS, "ability connection is not established");
135 lock.unlock();
136 return RES_FAILURE;
137 }
138 lock.unlock();
139 MessageOption option;
140 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
141 if (remoteObject_ == nullptr) {
142 TLOGE(WmsLogTag::DMS, "remoteObject is nullptr");
143 return RES_FAILURE;
144 }
145 int32_t ret = remoteObject_->SendRequest(transCode, data, reply, option);
146 if (ret != ERR_OK) {
147 TLOGE(WmsLogTag::DMS, "remoteObject send request failed");
148 return RES_FAILURE;
149 }
150 return RES_SUCCESS;
151 }
152
SendMessageSyncBlock(int32_t transCode,MessageParcel & data,MessageParcel & reply)153 int32_t ScreenSessionAbilityConnectionStub::SendMessageSyncBlock(int32_t transCode,
154 MessageParcel &data, MessageParcel &reply)
155 {
156 std::unique_lock<std::mutex> lock(connectedMutex_);
157 connectedCv_.wait_for(lock, std::chrono::milliseconds(SEND_MESSAGE_SYNC_OUT_TIME));
158 if (!IsAbilityConnected()) {
159 TLOGE(WmsLogTag::DMS, "ability connection is not established");
160 lock.unlock();
161 return RES_FAILURE;
162 }
163 lock.unlock();
164 MessageOption option;
165 {
166 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
167 if (remoteObject_ == nullptr) {
168 TLOGE(WmsLogTag::DMS, "remoteObject is nullptr");
169 return RES_FAILURE;
170 }
171 int32_t ret = remoteObject_->SendRequest(transCode, data, reply, option);
172 if (ret != ERR_OK) {
173 TLOGE(WmsLogTag::DMS, "remoteObject send request failed");
174 return RES_FAILURE;
175 }
176 }
177 std::unique_lock<std::mutex> lockSendMessage(sendMessageMutex_);
178 TLOGI(WmsLogTag::DMS, "LockSendMessage wait");
179 sendMessageWaitFlag_ = false;
180 while (!sendMessageWaitFlag_) {
181 blockSendMessageCV_.wait(lockSendMessage);
182 }
183
184 return RES_SUCCESS;
185 }
186
OnRemoteDied(const wptr<IRemoteObject> & remoteObject)187 void ScreenSessionAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remoteObject)
188 {
189 TLOGI(WmsLogTag::DMS, "OnRemoteDied entry");
190 if (deathHandler_ == nullptr) {
191 TLOGE(WmsLogTag::DMS, "death handler is nullptr");
192 return;
193 }
194 deathHandler_();
195 }
196
ScreenSessionConnectExtension(const std::string & bundleName,const std::string & abilityName)197 bool ScreenSessionAbilityConnection::ScreenSessionConnectExtension(
198 const std::string &bundleName, const std::string &abilityName)
199 {
200 return ScreenSessionConnectExtension(bundleName, abilityName, {});
201 }
202
ScreenSessionConnectExtension(const std::string & bundleName,const std::string & abilityName,const std::vector<std::pair<std::string,std::string>> & params)203 bool ScreenSessionAbilityConnection::ScreenSessionConnectExtension(const std::string &bundleName,
204 const std::string &abilityName, const std::vector<std::pair<std::string, std::string>> ¶ms)
205 {
206 TLOGI(WmsLogTag::DMS, "bundleName:%{public}s, abilityName:%{public}s", bundleName.c_str(), abilityName.c_str());
207 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
208 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
209 OHOS::sptr<OHOS::IRemoteObject> remoteObject =
210 systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
211 if (remoteObject == nullptr) {
212 TLOGE(WmsLogTag::DMS, "GetSystemAbility BMS failed");
213 return false;
214 }
215 if (abilityConnectionStub_ != nullptr) {
216 TLOGI(WmsLogTag::DMS, "screen session ability extension is already connected");
217 return true;
218 }
219 AAFwk::Want want;
220 want.SetElementName(bundleName, abilityName);
221 for (auto param : params) {
222 std::string paramKey = param.first;
223 std::string paramValue = param.second;
224 if (!paramKey.empty() && !paramValue.empty()) {
225 want.SetParam(paramKey, paramValue);
226 TLOGI(WmsLogTag::DMS, "add want param. paramKey=%{public}s, paramValue=%{public}s",
227 paramKey.c_str(), paramValue.c_str());
228 }
229 }
230 abilityConnectionStub_ = sptr<ScreenSessionAbilityConnectionStub>(new (std::nothrow)
231 ScreenSessionAbilityConnectionStub());
232 if (abilityConnectionStub_ == nullptr) {
233 TLOGE(WmsLogTag::DMS, "screen session aibility connection is nullptr");
234 return false;
235 }
236
237 // reset current callingIdentity for screen session
238 std::string identity = IPCSkeleton::ResetCallingIdentity();
239 auto ret = AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(
240 want, abilityConnectionStub_, nullptr, DEFAULT_VALUE);
241 if (ret != ERR_OK) {
242 TLOGE(WmsLogTag::DMS, "ConnectServiceExtensionAbility failed, result: %{public}d", ret);
243 // set current callingIdentity back
244 IPCSkeleton::SetCallingIdentity(identity);
245 return false;
246 }
247 TLOGI(WmsLogTag::DMS, "ConnectServiceExtensionAbility result: %{public}d", ret);
248 // set current callingIdentity back
249 IPCSkeleton::SetCallingIdentity(identity);
250 return true;
251 }
252
ScreenSessionDisconnectExtension()253 void ScreenSessionAbilityConnection::ScreenSessionDisconnectExtension()
254 {
255 if (abilityConnectionStub_ == nullptr) {
256 TLOGE(WmsLogTag::DMS, "ability connect failed");
257 return;
258 }
259 auto ret = AAFwk::ExtensionManagerClient::GetInstance().DisconnectAbility(abilityConnectionStub_);
260 if (ret == NO_ERROR) {
261 abilityConnectionStub_.clear();
262 abilityConnectionStub_ = nullptr;
263 }
264 TLOGI(WmsLogTag::DMS, "screen session ability disconnected, ret: %{public}d", ret);
265 }
266
SendMessage(const int32_t & transCode,MessageParcel & data,MessageParcel & reply)267 int32_t ScreenSessionAbilityConnection::SendMessage(
268 const int32_t &transCode, MessageParcel &data, MessageParcel &reply)
269 {
270 if (abilityConnectionStub_ == nullptr) {
271 TLOGE(WmsLogTag::DMS, "ability connection is nullptr");
272 return RES_FAILURE;
273 }
274 int32_t ret = abilityConnectionStub_->SendMessageSync(transCode, data, reply);
275 if (ret != ERR_OK) {
276 TLOGE(WmsLogTag::DMS, "send message failed");
277 return RES_FAILURE;
278 }
279 return RES_SUCCESS;
280 }
281
SendMessageBlock(const int32_t & transCode,MessageParcel & data,MessageParcel & reply)282 int32_t ScreenSessionAbilityConnection::SendMessageBlock(
283 const int32_t &transCode, MessageParcel &data, MessageParcel &reply)
284 {
285 if (abilityConnectionStub_ == nullptr) {
286 TLOGE(WmsLogTag::DMS, "ability connection is nullptr");
287 return RES_FAILURE;
288 }
289 int32_t ret = abilityConnectionStub_->SendMessageSyncBlock(transCode, data, reply);
290 if (ret != ERR_OK) {
291 TLOGE(WmsLogTag::DMS, "send message failed");
292 return RES_FAILURE;
293 }
294 return RES_SUCCESS;
295 }
296
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)297 int32_t ScreenSessionAbilityConnectionStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply,
298 MessageOption& option)
299 {
300 TLOGI(WmsLogTag::DMS, "OnRemoteRequest code is %{public}u", code);
301 if (data.ReadInterfaceToken() != GetDescriptor()) {
302 TLOGE(WmsLogTag::DMS, "InterfaceToken check failed");
303 return ERR_INVALID_DATA;
304 }
305 uint32_t msgId = code;
306 switch (msgId) {
307 case TRANS_RELEASE_BLOCK: {
308 screenId_ = data.ReadInt32();
309 left_ = data.ReadInt32();
310 top_ = data.ReadInt32();
311 width_ = data.ReadInt32();
312 height_ = data.ReadInt32();
313 break;
314 }
315 case TRANS_FAILED_FOR_PRIVACY: {
316 errCode_ = msgId;
317 break;
318 }
319 default:
320 TLOGI(WmsLogTag::DMS, "unknown transaction code");
321 }
322 sendMessageWaitFlag_ = true;
323 blockSendMessageCV_.notify_all();
324 TLOGI(WmsLogTag::DMS, "blockSendMessageCV_ notify");
325 return msgId;
326 }
327
GetScreenId()328 int32_t ScreenSessionAbilityConnectionStub::GetScreenId()
329 {
330 return screenId_;
331 }
332
GetLeft()333 int32_t ScreenSessionAbilityConnectionStub::GetLeft()
334 {
335 return left_;
336 }
337
GetTop()338 int32_t ScreenSessionAbilityConnectionStub::GetTop()
339 {
340 return top_;
341 }
342
GetWidth()343 int32_t ScreenSessionAbilityConnectionStub::GetWidth()
344 {
345 return width_;
346 }
347
GetHeight()348 int32_t ScreenSessionAbilityConnectionStub::GetHeight()
349 {
350 return height_;
351 }
352
GetErrCode()353 int32_t ScreenSessionAbilityConnectionStub::GetErrCode()
354 {
355 return errCode_;
356 }
357
EraseErrCode()358 void ScreenSessionAbilityConnectionStub::EraseErrCode()
359 {
360 errCode_ = 0;
361 }
362
IsConnected()363 bool ScreenSessionAbilityConnection::IsConnected()
364 {
365 if (abilityConnectionStub_ == nullptr) {
366 TLOGE(WmsLogTag::DMS, "ability connect failed");
367 return false;
368 }
369 return abilityConnectionStub_->IsAbilityConnected();
370 }
371
IsConnectedSync()372 bool ScreenSessionAbilityConnection::IsConnectedSync()
373 {
374 if (abilityConnectionStub_ == nullptr) {
375 TLOGE(WmsLogTag::DMS, "ability connect failed");
376 return false;
377 }
378 return abilityConnectionStub_->IsAbilityConnectedSync();
379 }
380
GetScreenSessionAbilityConnectionStub()381 sptr<ScreenSessionAbilityConnectionStub> ScreenSessionAbilityConnection::GetScreenSessionAbilityConnectionStub()
382 {
383 return abilityConnectionStub_;
384 }
385
386 } // namespace OHOS::Rosen