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>> &params)
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