1 /*
2  * Copyright (c) 2022-2024 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 "dscreen_source_handler.h"
17 
18 #include <chrono>
19 #include <new>
20 #include <string>
21 
22 #include "errors.h"
23 #include "hitrace_meter.h"
24 #include "idscreen_source_callback.h"
25 #include "if_system_ability_manager.h"
26 #include "iremote_broker.h"
27 #include "isystem_ability_load_callback.h"
28 #include "iservice_registry.h"
29 
30 #include "dscreen_constants.h"
31 #include "dscreen_errcode.h"
32 #include "dscreen_hitrace.h"
33 #include "dscreen_hisysevent.h"
34 #include "dscreen_log.h"
35 #include "dscreen_source_load_callback.h"
36 #include "dscreen_util.h"
37 
38 namespace OHOS {
39 namespace DistributedHardware {
40 IMPLEMENT_SINGLE_INSTANCE(DScreenSourceHandler);
41 
DScreenSourceHandler()42 DScreenSourceHandler::DScreenSourceHandler()
43 {
44     DHLOGI("DScreenSourceHandler construct.");
45     std::lock_guard<std::mutex> lock(proxyMutex_);
46     if (sourceSvrRecipient_ == nullptr) {
47         sourceSvrRecipient_ = new (std::nothrow) DScreenSourceSvrRecipient();
48     }
49 
50     if (dScreenSourceCallback_ == nullptr) {
51         dScreenSourceCallback_ = new (std::nothrow) DScreenSourceCallback();
52     }
53 }
54 
InitSource(const std::string & params)55 int32_t DScreenSourceHandler::InitSource(const std::string &params)
56 {
57     if (params.empty()) {
58         DHLOGE("InitSource params is invalid.");
59         return ERR_DH_SCREEN_INPUT_PARAM_INVALID;
60     }
61     DHLOGI("DScreenSourceHandler InitSource");
62     std::unique_lock<std::mutex> lock(proxyMutex_);
63     if (dScreenSourceProxy_ == nullptr) {
64         sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
65         if (samgr == nullptr) {
66             DHLOGE("Failed to get system ability mgr.");
67             ReportSaFail(DSCREEN_INIT_FAIL, ERR_DH_SCREEN_SA_GET_SAMGR_FAIL, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
68                 "dscreen source get samgr failed.");
69             return ERR_DH_SCREEN_SA_GET_SAMGR_FAIL;
70         }
71         sptr<DScreenSourceLoadCallback> loadCallback(new DScreenSourceLoadCallback(params));
72         StartTrace(DSCREEN_HITRACE_LABEL, DSCREEN_SOURCE_LOAD_SYSTEM_ABILITY_START);
73         int32_t ret = samgr->LoadSystemAbility(DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID, loadCallback);
74         if (ret != ERR_OK) {
75             DHLOGE("Failed to Load systemAbility, systemAbilityId:%{public}" PRId32 ", ret code:%{public}" PRId32,
76                 DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID, ret);
77             ReportSaFail(DSCREEN_INIT_FAIL, ret, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
78                 "dscreen source LoadSystemAbility call failed.");
79             return ERR_DH_SCREEN_SA_GET_SOURCEPROXY_FAIL;
80         }
81     }
82 
83     auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(SCREEN_LOADSA_TIMEOUT_MS),
84         [this]() { return (dScreenSourceProxy_ != nullptr); });
85     if (!waitStatus) {
86         DHLOGE("screen load sa timeout.");
87         ReportSaFail(DSCREEN_INIT_FAIL, ERR_DH_SCREEN_SA_LOAD_TIMEOUT, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
88             "dscreen source sa load timeout.");
89         return ERR_DH_SCREEN_SA_LOAD_TIMEOUT;
90     }
91 
92     FinishTrace(DSCREEN_HITRACE_LABEL);
93     return DH_SUCCESS;
94 }
95 
FinishStartSA(const std::string & params,const sptr<IRemoteObject> & remoteObject)96 void DScreenSourceHandler::FinishStartSA(const std::string &params, const sptr<IRemoteObject> &remoteObject)
97 {
98     DHLOGI("DScreenSourceHandler FinishStartSA");
99     std::lock_guard<std::mutex> lock(proxyMutex_);
100     if (remoteObject == nullptr) {
101         DHLOGE("remoteObject is nullptr.");
102         ReportSaFail(DSCREEN_INIT_FAIL, ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
103             "remoteObject is nullptr.");
104         return;
105     }
106     if (sourceSvrRecipient_ == nullptr) {
107         DHLOGE("sourceSvrRecipient is nullptr.");
108         ReportSaFail(DSCREEN_INIT_FAIL, ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
109             "sourceSvrRecipient is nullptr.");
110         return;
111     }
112     remoteObject->AddDeathRecipient(sourceSvrRecipient_);
113     dScreenSourceProxy_ = iface_cast<IDScreenSource>(remoteObject);
114     if ((dScreenSourceProxy_ == nullptr) || (dScreenSourceProxy_->AsObject() == nullptr)) {
115         DHLOGE("Failed to get dscreen source proxy.");
116         ReportSaFail(DSCREEN_INIT_FAIL, ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
117             "dscreen source get proxy failed.");
118         return;
119     }
120     if (dScreenSourceCallback_ == nullptr) {
121         DHLOGE("dScreenSourceCallback is nullptr.");
122         ReportSaFail(DSCREEN_INIT_FAIL, ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
123             "dScreenSourceCallback is nullptr.");
124         return;
125     }
126     dScreenSourceProxy_->InitSource(params, dScreenSourceCallback_);
127     proxyConVar_.notify_one();
128     ReportSaEvent(DSCREEN_INIT, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID, "dscreen source sa load success.");
129 }
130 
ReleaseSource()131 int32_t DScreenSourceHandler::ReleaseSource()
132 {
133     DHLOGI("DScreenSourceHandler ReleaseSource");
134     std::lock_guard<std::mutex> lock(proxyMutex_);
135     if (dScreenSourceProxy_ == nullptr) {
136         DHLOGE("screen source proxy not init.");
137         ReportSaFail(DSCREEN_INIT_FAIL, ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT, DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID,
138             "dscreen source proxy not init.");
139         return ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT;
140     }
141     int32_t ret = dScreenSourceProxy_->ReleaseSource();
142     dScreenSourceProxy_ = nullptr;
143     return ret;
144 }
145 
RegisterDistributedHardware(const std::string & devId,const std::string & dhId,const EnableParam & param,std::shared_ptr<RegisterCallback> callback)146 int32_t DScreenSourceHandler::RegisterDistributedHardware(const std::string &devId,
147     const std::string &dhId, const EnableParam &param, std::shared_ptr<RegisterCallback> callback)
148 {
149     if (devId.empty() || dhId.empty()) {
150         DHLOGE("device id or dh id empty.");
151         return ERR_DH_SCREEN_STRING_PARAM_EMPTY;
152     }
153     if (callback == nullptr) {
154         DHLOGE("callback is nullptr.");
155         return ERR_DH_SCREEN_REGISTER_CALLBACK_NOT_INIT;
156     }
157     DHLOGI("RegisterDistributedHardware, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId).c_str(),
158         GetAnonyString(dhId).c_str());
159     std::lock_guard<std::mutex> lock(proxyMutex_);
160     if (dScreenSourceProxy_ == nullptr) {
161         DHLOGE("screen source proxy not init");
162         return ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT;
163     }
164     if (dScreenSourceCallback_ == nullptr) {
165         DHLOGE("screen source callback is null.");
166         return ERR_DH_SCREEN_SA_SOURCEPCALLBACK_NOT_INIT;
167     }
168 
169     std::string reqId = GetRandomID();
170     dScreenSourceCallback_->PushRegRegisterCallback(reqId, callback);
171     return dScreenSourceProxy_->RegisterDistributedHardware(devId, dhId, param, reqId);
172 }
173 
UnregisterDistributedHardware(const std::string & devId,const std::string & dhId,std::shared_ptr<UnregisterCallback> callback)174 int32_t DScreenSourceHandler::UnregisterDistributedHardware(const std::string &devId,
175     const std::string &dhId, std::shared_ptr<UnregisterCallback> callback)
176 {
177     if (devId.empty() || dhId.empty()) {
178         DHLOGE("device id or dh id empty.");
179         return ERR_DH_SCREEN_STRING_PARAM_EMPTY;
180     }
181     if (callback == nullptr) {
182         DHLOGE("callback is nullptr.");
183         return ERR_DH_SCREEN_REGISTER_CALLBACK_NOT_INIT;
184     }
185     DHLOGI("UnregisterDistributedHardware, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId).c_str(),
186         GetAnonyString(dhId).c_str());
187     std::lock_guard<std::mutex> lock(proxyMutex_);
188     if (dScreenSourceProxy_ == nullptr) {
189         DHLOGE("screen source proxy not init.");
190         return ERR_DH_SCREEN_SA_SOURCEPROXY_NOT_INIT;
191     }
192     if (dScreenSourceCallback_ == nullptr) {
193         DHLOGE("screen source callback is null.");
194         return ERR_DH_SCREEN_SA_SOURCEPCALLBACK_NOT_INIT;
195     }
196 
197     std::string reqId = GetRandomID();
198     dScreenSourceCallback_->PushUnregisterCallback(reqId, callback);
199     return dScreenSourceProxy_->UnregisterDistributedHardware(devId, dhId, reqId);
200 }
201 
ConfigDistributedHardware(const std::string & devId,const std::string & dhId,const std::string & key,const std::string & value)202 int32_t DScreenSourceHandler::ConfigDistributedHardware(const std::string &devId,
203     const std::string &dhId, const std::string &key, const std::string &value)
204 {
205     DHLOGI("ConfigDistributedHardware");
206     return DH_SUCCESS;
207 }
208 
RegisterDistributedHardwareStateListener(std::shared_ptr<DistributedHardwareStateListener> listener)209 void DScreenSourceHandler::RegisterDistributedHardwareStateListener(
210     std::shared_ptr<DistributedHardwareStateListener> listener)
211 {
212     (void)listener;
213 }
214 
UnregisterDistributedHardwareStateListener()215 void DScreenSourceHandler::UnregisterDistributedHardwareStateListener()
216 {
217 }
218 
RegisterDataSyncTriggerListener(std::shared_ptr<DataSyncTriggerListener> listener)219 void DScreenSourceHandler::RegisterDataSyncTriggerListener(std::shared_ptr<DataSyncTriggerListener> listener)
220 {
221     (void)listener;
222 }
223 
UnregisterDataSyncTriggerListener()224 void DScreenSourceHandler::UnregisterDataSyncTriggerListener()
225 {
226 }
227 
OnRemoteDied(const wptr<IRemoteObject> & remote)228 void DScreenSourceHandler::DScreenSourceSvrRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
229 {
230     if (remote == nullptr) {
231         DHLOGI("OnRemoteDied remote is nullptr.");
232         return;
233     }
234     DHLOGI("DScreenSourceSvrRecipient OnRemoteDied");
235     DScreenSourceHandler::GetInstance().OnRemoteSourceSvrDied(remote);
236 }
237 
OnRemoteSourceSvrDied(const wptr<IRemoteObject> & remote)238 void DScreenSourceHandler::OnRemoteSourceSvrDied(const wptr<IRemoteObject> &remote)
239 {
240     DHLOGI("OnRemoteSourceSvrDied");
241     std::lock_guard<std::mutex> lock(proxyMutex_);
242     if (dScreenSourceProxy_ == nullptr) {
243         DHLOGE("dScreenSourceProxy is nullptr.");
244         return;
245     }
246     sptr<IRemoteObject> remoteObject = remote.promote();
247     if (remoteObject == nullptr) {
248         DHLOGE("OnRemoteDied remote promoted failed");
249         return;
250     }
251 
252     if (dScreenSourceProxy_->AsObject() != remoteObject) {
253         DHLOGE("OnRemoteSourceSvrDied not found remote object.");
254         return;
255     }
256 
257     dScreenSourceProxy_->AsObject()->RemoveDeathRecipient(sourceSvrRecipient_);
258     dScreenSourceProxy_ = nullptr;
259 }
260 
GetSourceHardwareHandler()261 IDistributedHardwareSource *GetSourceHardwareHandler()
262 {
263     DHLOGI("GetSourceHardwareHandler");
264     return &DScreenSourceHandler::GetInstance();
265 }
266 }  // namespace DistributedHardware
267 }  // namespace OHOS
268