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