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
GetInstance()37 sptr<RSRenderServiceConnectHub> RSRenderServiceConnectHub::GetInstance()
38 {
39 std::call_once(flag_, &RSRenderServiceConnectHub::Init);
40 return instance_;
41 }
42
Init()43 void RSRenderServiceConnectHub::Init()
44 {
45 RS_LOGD("RSRenderServiceConnectHub::Init");
46 instance_ = new RSRenderServiceConnectHub();
47 ::atexit(&RSRenderServiceConnectHub::Destroy);
48 }
49
Destroy()50 void RSRenderServiceConnectHub::Destroy()
51 {
52 RS_LOGI("RSRenderServiceConnectHub::Destroy");
53 instance_ = nullptr;
54 }
55
RSRenderServiceConnectHub()56 RSRenderServiceConnectHub::RSRenderServiceConnectHub()
57 {
58 RS_LOGD("RSRenderServiceConnectHub: ctor");
59 }
60
~RSRenderServiceConnectHub()61 RSRenderServiceConnectHub::~RSRenderServiceConnectHub() noexcept
62 {
63 if (renderService_ && renderService_->AsObject() && deathRecipient_) {
64 renderService_->AsObject()->RemoveDeathRecipient(deathRecipient_);
65 }
66 RS_LOGI("~RSRenderServiceConnectHub: dtor");
67 }
68
GetRenderService()69 sptr<RSIRenderServiceConnection> RSRenderServiceConnectHub::GetRenderService()
70 {
71 auto connHub = RSRenderServiceConnectHub::GetInstance();
72 return connHub == nullptr ? nullptr : connHub->GetRenderServiceConnection();
73 }
74
GetRenderServiceConnection()75 sptr<RSIRenderServiceConnection> RSRenderServiceConnectHub::GetRenderServiceConnection()
76 {
77 std::lock_guard<std::mutex> lock(mutex_);
78 if (conn_ != nullptr && renderService_ != nullptr) {
79 return conn_;
80 }
81
82 if (!Connect()) {
83 ROSEN_LOGE("RenderService connect fail");
84 return nullptr;
85 }
86
87 return conn_;
88 }
89
Connect()90 bool RSRenderServiceConnectHub::Connect()
91 {
92 RS_LOGD("RSRenderServiceConnectHub::Connect");
93 int tryCnt = 0;
94 sptr<RSIRenderService> renderService = nullptr;
95 do {
96 // sleep move time (1000us * tryCnt) when tryCnt++
97 usleep(1000 * tryCnt);
98 ++tryCnt;
99 // try most 5 times to get render service.
100 if (tryCnt == 5) {
101 ROSEN_LOGD("RSRenderServiceConnectHub::Connect failed, tried %{public}d times.", tryCnt);
102 break;
103 }
104
105 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
106 if (samgr == nullptr) {
107 continue;
108 }
109 auto remoteObject = samgr->GetSystemAbility(RENDER_SERVICE);
110 if (remoteObject == nullptr || !remoteObject->IsProxyObject()) {
111 continue;
112 }
113 renderService = iface_cast<RSRenderServiceProxy>(remoteObject);
114 if (renderService != nullptr) {
115 break;
116 }
117 } while (true);
118
119 if (renderService == nullptr) {
120 ROSEN_LOGD("RSRenderServiceConnectHub::Connect, failed to get render service proxy.");
121 return false;
122 }
123 wptr<RSRenderServiceConnectHub> rsConnhub = this;
124 deathRecipient_ = new RenderServiceDeathRecipient(rsConnhub);
125 if (!renderService->AsObject()->AddDeathRecipient(deathRecipient_)) {
126 ROSEN_LOGW("RSRenderServiceConnectHub::Connect, failed to AddDeathRecipient of render service.");
127 }
128
129 if (token_ == nullptr) {
130 token_ = new IRemoteStub<RSIConnectionToken>();
131 }
132 sptr<RSIRenderServiceConnection> conn = renderService->CreateConnection(token_);
133
134 if (conn == nullptr) {
135 ROSEN_LOGD("RSRenderServiceConnectHub::Connect, failed to CreateConnection to render service.");
136 return false;
137 }
138
139 renderService_ = renderService;
140 conn_ = conn;
141
142 if (onConnectCallback_) {
143 onConnectCallback_(conn_);
144 }
145
146 return true;
147 }
148
ConnectDied()149 void RSRenderServiceConnectHub::ConnectDied()
150 {
151 mutex_.lock();
152 RS_LOGI("RSRenderServiceConnectHub::ConnectDied lock pid: %{public}d", getpid());
153 renderService_ = nullptr;
154 if (conn_) {
155 conn_->RunOnRemoteDiedCallback();
156 }
157 conn_ = nullptr;
158 deathRecipient_ = nullptr;
159 token_ = nullptr;
160 mutex_.unlock();
161 RS_LOGI("RSRenderServiceConnectHub::ConnectDied unlock pid: %{public}d", getpid());
162 }
163
OnRemoteDied(const wptr<IRemoteObject> & remote)164 void RSRenderServiceConnectHub::RenderServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
165 {
166 auto remoteSptr = remote.promote();
167 if (remoteSptr == nullptr) {
168 ROSEN_LOGW("RSRenderServiceConnectHub::RenderServiceDeathRecipient::OnRemoteDied: can't promote.");
169 return;
170 }
171
172 auto rsConnHub = rsConnHub_.promote();
173 if (rsConnHub == nullptr) {
174 ROSEN_LOGW("RSRenderServiceConnectHub::RenderServiceDeathRecipient::OnRemoteDied: connHub was dead.");
175 return;
176 }
177
178 rsConnHub->ConnectDied();
179 }
180 } // namespace Rosen
181 } // namespace OHOS
182