• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>> &params)
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