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 "dinput_sa_manager.h"
17
18#include "iservice_registry.h"
19#include "system_ability_definition.h"
20
21#include "constants_dinput.h"
22#include "dinput_errcode.h"
23#include "dinput_log.h"
24
25namespace OHOS {
26namespace DistributedHardware {
27namespace DistributedInput {
28IMPLEMENT_SINGLE_INSTANCE(DInputSAManager);
29const uint32_t DINPUT_CLIENT_HANDLER_MSG_DELAY_TIME = 100; // million seconds
30void DInputSAManager::SystemAbilityListener::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
31{
32    if (systemAbilityId == DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID) {
33        DInputSAManager::GetInstance().dInputSourceSAOnline_.store(false);
34        {
35            std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sourceMutex_);
36            DInputSAManager::GetInstance().dInputSourceProxy_ = nullptr;
37        }
38        {
39            std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().handlerMutex_);
40            if (DInputSAManager::GetInstance().eventHandler_ != nullptr) {
41                DHLOGI("SendEvent DINPUT_CLIENT_CLEAR_SOURCE_CALLBACK_REGISTER_MSG");
42                AppExecFwk::InnerEvent::Pointer msgEvent =
43                    AppExecFwk::InnerEvent::Get(DINPUT_CLIENT_CLEAR_SOURCE_CALLBACK_REGISTER_MSG, systemAbilityId);
44                DInputSAManager::GetInstance().eventHandler_->SendEvent(msgEvent, DINPUT_CLIENT_HANDLER_MSG_DELAY_TIME,
45                    AppExecFwk::EventQueue::Priority::IMMEDIATE);
46            }
47        }
48    }
49
50    if (systemAbilityId == DISTRIBUTED_HARDWARE_INPUT_SINK_SA_ID) {
51        DInputSAManager::GetInstance().dInputSinkSAOnline_.store(false);
52        {
53            std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sinkMutex_);
54            DInputSAManager::GetInstance().dInputSinkProxy_ = nullptr;
55        }
56        {
57            std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().handlerMutex_);
58            if (DInputSAManager::GetInstance().eventHandler_ != nullptr) {
59                DHLOGI("SendEvent DINPUT_CLIENT_CLEAR_SINK_CALLBACK_REGISTER_MSG");
60                AppExecFwk::InnerEvent::Pointer msgEvent =
61                    AppExecFwk::InnerEvent::Get(DINPUT_CLIENT_CLEAR_SINK_CALLBACK_REGISTER_MSG, systemAbilityId);
62                DInputSAManager::GetInstance().eventHandler_->SendEvent(msgEvent, DINPUT_CLIENT_HANDLER_MSG_DELAY_TIME,
63                    AppExecFwk::EventQueue::Priority::IMMEDIATE);
64            }
65        }
66    }
67    DHLOGI("sa %{public}d is removed.", systemAbilityId);
68}
69
70void DInputSAManager::SystemAbilityListener::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
71{
72    if (systemAbilityId == DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID) {
73        DInputSAManager::GetInstance().dInputSourceSAOnline_.store(true);
74        std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().handlerMutex_);
75        if (DInputSAManager::GetInstance().eventHandler_ != nullptr) {
76            DHLOGI("SendEvent DINPUT_CLIENT_CHECK_SOURCE_CALLBACK_REGISTER_MSG");
77            AppExecFwk::InnerEvent::Pointer msgEvent =
78                AppExecFwk::InnerEvent::Get(DINPUT_CLIENT_CHECK_SOURCE_CALLBACK_REGISTER_MSG, systemAbilityId);
79            DInputSAManager::GetInstance().eventHandler_->SendEvent(msgEvent,
80                DINPUT_CLIENT_HANDLER_MSG_DELAY_TIME, AppExecFwk::EventQueue::Priority::IMMEDIATE);
81        }
82    }
83
84    if (systemAbilityId == DISTRIBUTED_HARDWARE_INPUT_SINK_SA_ID) {
85        DInputSAManager::GetInstance().dInputSinkSAOnline_.store(true);
86        std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().handlerMutex_);
87        if (DInputSAManager::GetInstance().eventHandler_ != nullptr) {
88            DHLOGI("SendEvent DINPUT_CLIENT_CHECK_SINK_CALLBACK_REGISTER_MSG");
89            AppExecFwk::InnerEvent::Pointer msgEvent =
90                AppExecFwk::InnerEvent::Get(DINPUT_CLIENT_CHECK_SINK_CALLBACK_REGISTER_MSG, systemAbilityId);
91            DInputSAManager::GetInstance().eventHandler_->SendEvent(msgEvent,
92                DINPUT_CLIENT_HANDLER_MSG_DELAY_TIME, AppExecFwk::EventQueue::Priority::IMMEDIATE);
93        }
94    }
95    DHLOGI("sa %{public}d is added.", systemAbilityId);
96}
97
98void DInputSAManager::Init()
99{
100    saListenerCallback = new(std::nothrow) SystemAbilityListener();
101    sptr<ISystemAbilityManager> systemAbilityManager =
102        SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
103
104    if (!systemAbilityManager) {
105        DHLOGE("get system ability manager failed.");
106        return;
107    }
108
109    if (!isSubscribeSrcSAChangeListener_.load()) {
110        DHLOGI("try subscribe source sa change listener, saId:%{public}d", DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID);
111        int32_t ret = systemAbilityManager->SubscribeSystemAbility(DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID,
112            saListenerCallback);
113        if (ret != DH_SUCCESS) {
114            DHLOGE("subscribe source sa change failed: %{public}d", ret);
115            return;
116        }
117        isSubscribeSrcSAChangeListener_.store(true);
118    }
119
120    if (!isSubscribeSinkSAChangeListener_.load()) {
121        DHLOGI("try subscribe sink sa change listener, saId:%{public}d", DISTRIBUTED_HARDWARE_INPUT_SINK_SA_ID);
122        int32_t ret = systemAbilityManager->SubscribeSystemAbility(DISTRIBUTED_HARDWARE_INPUT_SINK_SA_ID,
123            saListenerCallback);
124        if (ret != DH_SUCCESS) {
125            DHLOGE("subscribe sink sa change failed: %{public}d", ret);
126            return;
127        }
128        isSubscribeSinkSAChangeListener_.store(true);
129    }
130}
131
132void DInputSAManager::RegisterEventHandler(std::shared_ptr<AppExecFwk::EventHandler> handler)
133{
134    std::lock_guard<std::mutex> lock(handlerMutex_);
135    eventHandler_ = handler;
136}
137
138bool DInputSAManager::GetDInputSourceProxy()
139{
140    if (!isSubscribeSrcSAChangeListener_.load()) {
141        std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sourceMutex_);
142        if (!isSubscribeSrcSAChangeListener_.load()) {
143            sptr<ISystemAbilityManager> systemAbilityManager =
144                SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
145            if (!systemAbilityManager) {
146                DHLOGE("get system ability manager failed.");
147                return false;
148            }
149
150            DHLOGI("try subscribe source sa change listener, saId:%{public}d", DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID);
151            int32_t ret = systemAbilityManager->SubscribeSystemAbility(DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID,
152                saListenerCallback);
153            if (ret != DH_SUCCESS) {
154                DHLOGE("subscribe source sa change failed: %{public}d", ret);
155                return false;
156            }
157            isSubscribeSrcSAChangeListener_.store(true);
158        }
159    }
160
161    if (dInputSourceSAOnline_.load() && !dInputSourceProxy_) {
162        std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sourceMutex_);
163        if (dInputSourceProxy_ != nullptr) {
164            DHLOGI("dinput source proxy has already got.");
165            return true;
166        }
167        sptr<ISystemAbilityManager> systemAbilityManager =
168            SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
169        if (!systemAbilityManager) {
170            DHLOGE("get system ability manager failed.");
171            return false;
172        }
173
174        DHLOGI("try get sa: %{public}d", DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID);
175        sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(
176            DISTRIBUTED_HARDWARE_INPUT_SOURCE_SA_ID);
177        if (!remoteObject) {
178            return false;
179        }
180
181        dInputSourceProxy_ = iface_cast<IDistributedSourceInput>(remoteObject);
182
183        if ((!dInputSourceProxy_) || (!dInputSourceProxy_->AsObject())) {
184            return false;
185        }
186    }
187    std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sourceMutex_);
188    return dInputSourceProxy_ != nullptr;
189}
190
191bool DInputSAManager::HasDInputSourceProxy()
192{
193    std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sourceMutex_);
194    return dInputSourceProxy_ != nullptr;
195}
196
197bool DInputSAManager::SetDInputSourceProxy(const sptr<IRemoteObject> &remoteObject)
198{
199    std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sourceMutex_);
200    dInputSourceProxy_ = iface_cast<IDistributedSourceInput>(remoteObject);
201
202    if ((!dInputSourceProxy_) || (!dInputSourceProxy_->AsObject())) {
203        DHLOGE("Failed to get dinput source proxy.");
204        return false;
205    }
206    return true;
207}
208
209bool DInputSAManager::GetDInputSinkProxy()
210{
211    if (!isSubscribeSinkSAChangeListener_.load()) {
212        std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sinkMutex_);
213        if (!isSubscribeSinkSAChangeListener_.load()) {
214            sptr<ISystemAbilityManager> systemAbilityManager =
215                SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
216            if (!systemAbilityManager) {
217                DHLOGE("get system ability manager failed.");
218                return false;
219            }
220
221            DHLOGI("try subscribe sink sa change listener, sa id: %{public}d", DISTRIBUTED_HARDWARE_INPUT_SINK_SA_ID);
222            int32_t ret = systemAbilityManager->SubscribeSystemAbility(DISTRIBUTED_HARDWARE_INPUT_SINK_SA_ID,
223                saListenerCallback);
224            if (ret != DH_SUCCESS) {
225                DHLOGE("subscribe sink sa change failed: %{public}d", ret);
226                return false;
227            }
228            isSubscribeSinkSAChangeListener_.store(true);
229        }
230    }
231
232    if (dInputSinkSAOnline_.load() && !dInputSinkProxy_) {
233        std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sinkMutex_);
234        if (dInputSinkProxy_ != nullptr) {
235            DHLOGI("dinput sink proxy has already got.");
236            return true;
237        }
238        sptr<ISystemAbilityManager> systemAbilityManager =
239            SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
240        if (!systemAbilityManager) {
241            DHLOGE("get system ability manager failed.");
242            return false;
243        }
244
245        sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(
246            DISTRIBUTED_HARDWARE_INPUT_SINK_SA_ID);
247        if (!remoteObject) {
248            return false;
249        }
250
251        dInputSinkProxy_ = iface_cast<IDistributedSinkInput>(remoteObject);
252
253        if ((!dInputSinkProxy_) || (!dInputSinkProxy_->AsObject())) {
254            return false;
255        }
256    }
257    std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sinkMutex_);
258    return dInputSinkProxy_ != nullptr;
259}
260
261bool DInputSAManager::HasDInputSinkProxy()
262{
263    std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sinkMutex_);
264    return dInputSinkProxy_ != nullptr;
265}
266
267bool DInputSAManager::SetDInputSinkProxy(const sptr<IRemoteObject> &remoteObject)
268{
269    std::lock_guard<std::mutex> lock(DInputSAManager::GetInstance().sinkMutex_);
270    dInputSinkProxy_ = iface_cast<IDistributedSinkInput>(remoteObject);
271
272    if ((!dInputSinkProxy_) || (!dInputSinkProxy_->AsObject())) {
273        DHLOGE("Failed to get dinput sink proxy.");
274        return false;
275    }
276    return true;
277}
278
279int32_t DInputSAManager::RestoreRegisterListenerAndCallback()
280{
281    DHLOGI("Restore RegisterPublisherListener");
282    if (!DInputSAManager::GetInstance().GetDInputSourceProxy()) {
283        DHLOGE("RestoreRegisterSimulationEventListener proxy error, client fail");
284        return ERR_DH_INPUT_CLIENT_GET_SOURCE_PROXY_FAIL;
285    }
286
287    int32_t result = DH_SUCCESS;
288    {
289        std::lock_guard<std::mutex> lock(simEventListenerCacheMtx_);
290        for (const auto& listener : simEventListenerCache_) {
291            if (listener == nullptr) {
292                DHLOGE("simEventListenerCache_ is nullptr");
293                continue;
294            }
295            int32_t ret = DInputSAManager::GetInstance().dInputSourceProxy_->RegisterSimulationEventListener(listener);
296            if (ret != DH_SUCCESS) {
297                result = ret;
298                DHLOGE("SA execute RegisterSimulationEventListener fail, ret = %{public}d", ret);
299            }
300        }
301    }
302    {
303        DHLOGI("Restore RegisterSessionStateCb");
304        std::lock_guard<std::mutex> lock(sessionStateCbCacheMtx_);
305        for (const auto& callback : sessionStateCbCache_) {
306            if (callback == nullptr) {
307                DHLOGE("sessionStateCbCache_ is nullptr");
308                continue;
309            }
310            int32_t ret = DInputSAManager::GetInstance().dInputSourceProxy_->RegisterSessionStateCb(callback);
311            if (ret != DH_SUCCESS) {
312                result = ret;
313                DHLOGE("SA execute RegisterSessionStateCb fail, ret = %{public}d", ret);
314            }
315        }
316    }
317    return result;
318}
319
320void DInputSAManager::AddSimEventListenerToCache(sptr<ISimulationEventListener> listener)
321{
322    std::lock_guard<std::mutex> simEventListenerLock(simEventListenerCacheMtx_);
323    if (listener != nullptr) {
324        simEventListenerCache_.insert(listener);
325    }
326}
327
328void DInputSAManager::RemoveSimEventListenerFromCache(sptr<ISimulationEventListener> listener)
329{
330    std::lock_guard<std::mutex> simEventListenerLock(simEventListenerCacheMtx_);
331    if (listener != nullptr) {
332        simEventListenerCache_.erase(listener);
333    }
334}
335
336void DInputSAManager::AddSessionStateCbToCache(sptr<ISessionStateCallback> callback)
337{
338    std::lock_guard<std::mutex> sessionStateCbLock(sessionStateCbCacheMtx_);
339    if (callback != nullptr) {
340        sessionStateCbCache_.insert(callback);
341    }
342}
343
344void DInputSAManager::RemoveSessionStateCbFromCache()
345{
346    std::lock_guard<std::mutex> sessionStateCbLock(sessionStateCbCacheMtx_);
347    sessionStateCbCache_.clear();
348}
349} // namespace DistributedInput
350} // namespace DistributedHardware
351} // namespace OHOS