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