• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "rs_render_service_connect_hub.h"
17 
18 #include <if_system_ability_manager.h>
19 #include <iremote_stub.h>
20 #include <iservice_registry.h>
21 #include <mutex>
22 #include <system_ability_definition.h>
23 #include <unistd.h>
24 
25 #include "message_parcel.h"
26 #include "pipeline/rs_render_thread.h"
27 #include "platform/common/rs_log.h"
28 #include "rs_render_service_connection_proxy.h"
29 #include "rs_render_service_proxy.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 std::once_flag RSRenderServiceConnectHub::flag_;
34 sptr<RSRenderServiceConnectHub> RSRenderServiceConnectHub::instance_ = nullptr;
35 OnConnectCallback RSRenderServiceConnectHub::onConnectCallback_ = nullptr;
36 
DeleteIPCConnectToken()37 extern "C" __attribute__((destructor)) void DeleteIPCConnectToken()
38 {
39     auto connHub = OHOS::Rosen::RSRenderServiceConnectHub::GetConnectHubInstance();
40     if (connHub != nullptr) {
41         auto token = connHub->GetToken();
42         if (token != nullptr) {
43             delete token;
44         }
45     }
46 }
47 
GetInstance()48 sptr<RSRenderServiceConnectHub> RSRenderServiceConnectHub::GetInstance()
49 {
50     std::call_once(flag_, &RSRenderServiceConnectHub::Init);
51     return instance_;
52 }
53 
Init()54 void RSRenderServiceConnectHub::Init()
55 {
56     instance_ = new RSRenderServiceConnectHub();
57     ::atexit(&RSRenderServiceConnectHub::Destroy);
58 }
59 
Destroy()60 void RSRenderServiceConnectHub::Destroy()
61 {
62     instance_ = nullptr;
63 }
64 
RSRenderServiceConnectHub()65 RSRenderServiceConnectHub::RSRenderServiceConnectHub()
66 {
67 }
68 
~RSRenderServiceConnectHub()69 RSRenderServiceConnectHub::~RSRenderServiceConnectHub() noexcept
70 {
71     if (renderService_ && renderService_->AsObject() && deathRecipient_) {
72         renderService_->AsObject()->RemoveDeathRecipient(deathRecipient_);
73     }
74 }
75 
GetRenderService()76 sptr<RSIRenderServiceConnection> RSRenderServiceConnectHub::GetRenderService()
77 {
78     auto connHub = RSRenderServiceConnectHub::GetInstance();
79     return connHub == nullptr ? nullptr : connHub->GetRenderServiceConnection();
80 }
81 
GetRenderServiceConnection()82 sptr<RSIRenderServiceConnection> RSRenderServiceConnectHub::GetRenderServiceConnection()
83 {
84     std::lock_guard<std::mutex> lock(mutex_);
85     if (conn_ != nullptr && renderService_ != nullptr) {
86         return conn_;
87     }
88 
89     if (!Connect()) {
90         ROSEN_LOGE("RenderService connect fail");
91         return nullptr;
92     }
93 
94     return conn_;
95 }
96 
Connect()97 bool RSRenderServiceConnectHub::Connect()
98 {
99     RS_LOGD("RSRenderServiceConnectHub::Connect");
100     int tryCnt = 0;
101     sptr<RSIRenderService> renderService = nullptr;
102     do {
103         // sleep move time (1000us * tryCnt) when tryCnt++
104         usleep(1000 * tryCnt);
105         ++tryCnt;
106         // try most 5 times to get render service.
107         if (tryCnt == 5) {
108             ROSEN_LOGD("RSRenderServiceConnectHub::Connect failed, tried %{public}d times.", tryCnt);
109             break;
110         }
111 
112         auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
113         if (samgr == nullptr) {
114             continue;
115         }
116         auto remoteObject = samgr->GetSystemAbility(RENDER_SERVICE);
117         if (remoteObject == nullptr || !remoteObject->IsProxyObject()) {
118             continue;
119         }
120         renderService = iface_cast<RSRenderServiceProxy>(remoteObject);
121         if (renderService != nullptr) {
122             break;
123         }
124     } while (true);
125 
126     if (renderService == nullptr) {
127         ROSEN_LOGD("RSRenderServiceConnectHub::Connect, failed to get render service proxy.");
128         return false;
129     }
130     wptr<RSRenderServiceConnectHub> rsConnhub = this;
131     deathRecipient_ = new RenderServiceDeathRecipient(rsConnhub);
132     if (!renderService->AsObject()->AddDeathRecipient(deathRecipient_)) {
133         ROSEN_LOGW("RSRenderServiceConnectHub::Connect, failed to AddDeathRecipient of render service.");
134     }
135 
136     if (token_ == nullptr) {
137         token_ = new IRemoteStub<RSIConnectionToken>();
138     }
139     sptr<RSIRenderServiceConnection> conn = renderService->CreateConnection(token_);
140 
141     if (conn == nullptr) {
142         ROSEN_LOGD("RSRenderServiceConnectHub::Connect, failed to CreateConnection to render service.");
143         return false;
144     }
145 
146     renderService_ = renderService;
147     conn_ = conn;
148 
149     if (onConnectCallback_) {
150         onConnectCallback_(conn_);
151     }
152 
153     return true;
154 }
155 
ConnectDied()156 void RSRenderServiceConnectHub::ConnectDied()
157 {
158     mutex_.lock();
159     renderService_ = nullptr;
160     if (conn_) {
161         conn_->RunOnRemoteDiedCallback();
162     }
163     conn_ = nullptr;
164     deathRecipient_ = nullptr;
165     token_ = nullptr;
166     mutex_.unlock();
167 }
168 
OnRemoteDied(const wptr<IRemoteObject> & remote)169 void RSRenderServiceConnectHub::RenderServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
170 {
171     auto remoteSptr = remote.promote();
172     if (remoteSptr == nullptr) {
173         ROSEN_LOGW("RSRenderServiceConnectHub::RenderServiceDeathRecipient::OnRemoteDied: can't promote.");
174         return;
175     }
176 
177     auto rsConnHub = rsConnHub_.promote();
178     if (rsConnHub == nullptr) {
179         ROSEN_LOGW("RSRenderServiceConnectHub::RenderServiceDeathRecipient::OnRemoteDied: connHub was dead.");
180         return;
181     }
182 
183     rsConnHub->ConnectDied();
184 }
185 } // namespace Rosen
186 } // namespace OHOS
187