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 "window_manager_hilog.h"
25 #include "ipc_skeleton.h"
26 #include "extension_manager_client.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 if (!isConnected_) {
125 connectedCv_.wait_for(lock, std::chrono::milliseconds(SEND_MESSAGE_SYNC_OUT_TIME));
126 }
127 return IsAbilityConnected();
128 }
129
SendMessageSync(int32_t transCode,MessageParcel & data,MessageParcel & reply)130 int32_t ScreenSessionAbilityConnectionStub::SendMessageSync(int32_t transCode,
131 MessageParcel &data, MessageParcel &reply)
132 {
133 std::unique_lock<std::mutex> lock(connectedMutex_);
134 if (!isConnected_) {
135 connectedCv_.wait_for(lock, std::chrono::milliseconds(SEND_MESSAGE_SYNC_OUT_TIME));
136 }
137 if (!IsAbilityConnected()) {
138 TLOGE(WmsLogTag::DMS, "ability connection is not established");
139 lock.unlock();
140 return RES_FAILURE;
141 }
142 lock.unlock();
143 MessageOption option;
144 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
145 if (remoteObject_ == nullptr) {
146 TLOGE(WmsLogTag::DMS, "remoteObject is nullptr");
147 return RES_FAILURE;
148 }
149 int32_t ret = remoteObject_->SendRequest(transCode, data, reply, option);
150 if (ret != ERR_OK) {
151 TLOGE(WmsLogTag::DMS, "remoteObject send request failed");
152 return RES_FAILURE;
153 }
154 return RES_SUCCESS;
155 }
156
SendMessageSyncBlock(int32_t transCode,MessageParcel & data,MessageParcel & reply)157 int32_t ScreenSessionAbilityConnectionStub::SendMessageSyncBlock(int32_t transCode,
158 MessageParcel &data, MessageParcel &reply)
159 {
160 std::unique_lock<std::mutex> lock(connectedMutex_);
161 if (!isConnected_) {
162 connectedCv_.wait_for(lock, std::chrono::milliseconds(SEND_MESSAGE_SYNC_OUT_TIME));
163 }
164 if (!IsAbilityConnected()) {
165 TLOGE(WmsLogTag::DMS, "ability connection is not established");
166 lock.unlock();
167 return RES_FAILURE;
168 }
169 lock.unlock();
170 MessageOption option;
171 {
172 std::lock_guard<std::mutex> remoteObjLock(remoteObjectMutex_);
173 if (remoteObject_ == nullptr) {
174 TLOGE(WmsLogTag::DMS, "remoteObject is nullptr");
175 return RES_FAILURE;
176 }
177 int32_t ret = remoteObject_->SendRequest(transCode, data, reply, option);
178 if (ret != ERR_OK) {
179 TLOGE(WmsLogTag::DMS, "remoteObject send request failed");
180 return RES_FAILURE;
181 }
182 }
183
184 std::unique_lock<std::mutex> lockSendMessage(sendMessageMutex_);
185 TLOGI(WmsLogTag::DMS, "LockSendMessage wait");
186 sendMessageWaitFlag_ = false;
187 while (!sendMessageWaitFlag_) {
188 blockSendMessageCV_.wait(lockSendMessage);
189 }
190
191 return RES_SUCCESS;
192 }
193
OnRemoteDied(const wptr<IRemoteObject> & remoteObject)194 void ScreenSessionAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remoteObject)
195 {
196 if (remoteObject == nullptr) {
197 TLOGE(WmsLogTag::DMS, "remoteObject is null");
198 return;
199 }
200
201 sptr<IRemoteObject> object = remoteObject.promote();
202 if (!object) {
203 TLOGE(WmsLogTag::DMS, "object is null");
204 return;
205 }
206 TLOGI(WmsLogTag::DMS, "OnRemoteDied entry");
207 if (deathHandler_ == nullptr) {
208 TLOGE(WmsLogTag::DMS, "death handler is nullptr");
209 return;
210 }
211 deathHandler_();
212 }
213
ScreenSessionConnectExtension(const std::string & bundleName,const std::string & abilityName)214 bool ScreenSessionAbilityConnection::ScreenSessionConnectExtension(
215 const std::string &bundleName, const std::string &abilityName)
216 {
217 return ScreenSessionConnectExtension(bundleName, abilityName, {});
218 }
219
ScreenSessionConnectExtension(const std::string & bundleName,const std::string & abilityName,const std::vector<std::pair<std::string,std::string>> & params)220 bool ScreenSessionAbilityConnection::ScreenSessionConnectExtension(const std::string &bundleName,
221 const std::string &abilityName, const std::vector<std::pair<std::string, std::string>> ¶ms)
222 {
223 TLOGI(WmsLogTag::DMS, "bundleName:%{public}s, abilityName:%{public}s", bundleName.c_str(), abilityName.c_str());
224 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
225 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
226 OHOS::sptr<OHOS::IRemoteObject> remoteObject =
227 systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
228 if (remoteObject == nullptr) {
229 TLOGE(WmsLogTag::DMS, "GetSystemAbility BMS failed");
230 return false;
231 }
232 if (abilityConnectionStub_ != nullptr) {
233 TLOGI(WmsLogTag::DMS, "screen session ability extension is already connected");
234 return true;
235 }
236 AAFwk::Want want;
237 want.SetElementName(bundleName, abilityName);
238 for (auto param : params) {
239 std::string paramKey = param.first;
240 std::string paramValue = param.second;
241 if (!paramKey.empty() && !paramValue.empty()) {
242 want.SetParam(paramKey, paramValue);
243 TLOGI(WmsLogTag::DMS, "add want param. paramKey=%{public}s, paramValue=%{public}s",
244 paramKey.c_str(), paramValue.c_str());
245 }
246 }
247 abilityConnectionStub_ = sptr<ScreenSessionAbilityConnectionStub>(new (std::nothrow)
248 ScreenSessionAbilityConnectionStub());
249 if (abilityConnectionStub_ == nullptr) {
250 TLOGE(WmsLogTag::DMS, "screen session aibility connection is nullptr");
251 return false;
252 }
253
254 // reset current callingIdentity for screen session
255 std::string identity = IPCSkeleton::ResetCallingIdentity();
256 auto ret = AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(
257 want, abilityConnectionStub_, nullptr, DEFAULT_VALUE);
258 if (ret != ERR_OK) {
259 TLOGE(WmsLogTag::DMS, "ConnectServiceExtensionAbility failed, result: %{public}d", ret);
260 // set current callingIdentity back
261 IPCSkeleton::SetCallingIdentity(identity);
262 return false;
263 }
264 TLOGI(WmsLogTag::DMS, "ConnectServiceExtensionAbility succeed");
265 // set current callingIdentity back
266 IPCSkeleton::SetCallingIdentity(identity);
267 return true;
268 }
269
ScreenSessionDisconnectExtension()270 void ScreenSessionAbilityConnection::ScreenSessionDisconnectExtension()
271 {
272 if (abilityConnectionStub_ == nullptr) {
273 TLOGE(WmsLogTag::DMS, "ability connect failed");
274 return;
275 }
276 auto ret = AAFwk::ExtensionManagerClient::GetInstance().DisconnectAbility(abilityConnectionStub_);
277 if (ret == NO_ERROR) {
278 abilityConnectionStub_.clear();
279 abilityConnectionStub_ = nullptr;
280 }
281 TLOGI(WmsLogTag::DMS, "screen session ability disconnected, ret: %{public}d", ret);
282 }
283
SendMessage(const int32_t & transCode,MessageParcel & data,MessageParcel & reply)284 int32_t ScreenSessionAbilityConnection::SendMessage(
285 const int32_t &transCode, MessageParcel &data, MessageParcel &reply)
286 {
287 if (abilityConnectionStub_ == nullptr) {
288 TLOGE(WmsLogTag::DMS, "ability connection is nullptr");
289 return RES_FAILURE;
290 }
291 int32_t ret = abilityConnectionStub_->SendMessageSync(transCode, data, reply);
292 if (ret != ERR_OK) {
293 TLOGE(WmsLogTag::DMS, "send message failed");
294 return RES_FAILURE;
295 }
296 return RES_SUCCESS;
297 }
298
SendMessageBlock(const int32_t & transCode,MessageParcel & data,MessageParcel & reply)299 int32_t ScreenSessionAbilityConnection::SendMessageBlock(
300 const int32_t &transCode, MessageParcel &data, MessageParcel &reply)
301 {
302 if (abilityConnectionStub_ == nullptr) {
303 TLOGE(WmsLogTag::DMS, "ability connection is nullptr");
304 return RES_FAILURE;
305 }
306 int32_t ret = abilityConnectionStub_->SendMessageSyncBlock(transCode, data, reply);
307 if (ret != ERR_OK) {
308 TLOGE(WmsLogTag::DMS, "send message failed");
309 return RES_FAILURE;
310 }
311 return RES_SUCCESS;
312 }
313
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)314 int32_t ScreenSessionAbilityConnectionStub::OnRemoteRequest(uint32_t code, MessageParcel& data,
315 [[maybe_unused]]MessageParcel& reply, [[maybe_unused]]MessageOption& option)
316 {
317 TLOGI(WmsLogTag::DMS, "OnRemoteRequest code is %{public}u", code);
318 if (data.ReadInterfaceToken() != GetDescriptor()) {
319 TLOGE(WmsLogTag::DMS, "InterfaceToken check failed");
320 return ERR_INVALID_DATA;
321 }
322 uint32_t msgId = code;
323 switch (msgId) {
324 case TRANS_RELEASE_BLOCK: {
325 screenId_ = data.ReadInt32();
326 left_ = data.ReadInt32();
327 top_ = data.ReadInt32();
328 width_ = data.ReadInt32();
329 height_ = data.ReadInt32();
330 break;
331 }
332 case TRANS_FAILED_FOR_PRIVACY: {
333 errCode_ = msgId;
334 break;
335 }
336 default:
337 TLOGI(WmsLogTag::DMS, "unknown transaction code");
338 }
339 sendMessageWaitFlag_ = true;
340 blockSendMessageCV_.notify_all();
341 TLOGI(WmsLogTag::DMS, "blockSendMessageCV_ notify");
342 return msgId;
343 }
344
GetScreenId()345 int32_t ScreenSessionAbilityConnectionStub::GetScreenId()
346 {
347 return screenId_;
348 }
349
GetLeft()350 int32_t ScreenSessionAbilityConnectionStub::GetLeft()
351 {
352 return left_;
353 }
354
GetTop()355 int32_t ScreenSessionAbilityConnectionStub::GetTop()
356 {
357 return top_;
358 }
359
GetWidth()360 int32_t ScreenSessionAbilityConnectionStub::GetWidth()
361 {
362 return width_;
363 }
364
GetHeight()365 int32_t ScreenSessionAbilityConnectionStub::GetHeight()
366 {
367 return height_;
368 }
369
GetErrCode()370 int32_t ScreenSessionAbilityConnectionStub::GetErrCode()
371 {
372 return errCode_;
373 }
374
EraseErrCode()375 void ScreenSessionAbilityConnectionStub::EraseErrCode()
376 {
377 errCode_ = 0;
378 }
379
IsConnected()380 bool ScreenSessionAbilityConnection::IsConnected()
381 {
382 if (abilityConnectionStub_ == nullptr) {
383 TLOGE(WmsLogTag::DMS, "ability connect failed");
384 return false;
385 }
386 return abilityConnectionStub_->IsAbilityConnected();
387 }
388
IsConnectedSync()389 bool ScreenSessionAbilityConnection::IsConnectedSync()
390 {
391 if (abilityConnectionStub_ == nullptr) {
392 TLOGE(WmsLogTag::DMS, "ability connect failed");
393 return false;
394 }
395 return abilityConnectionStub_->IsAbilityConnectedSync();
396 }
397
GetScreenSessionAbilityConnectionStub()398 sptr<ScreenSessionAbilityConnectionStub> ScreenSessionAbilityConnection::GetScreenSessionAbilityConnectionStub()
399 {
400 return abilityConnectionStub_;
401 }
402
403 } // namespace OHOS::Rosen