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