1/*
2 * Copyright (c) 2022-2023 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 "devicestatus_client.h"
17
18#include <if_system_ability_manager.h>
19#include <iservice_registry.h>
20#include <system_ability_definition.h>
21
22#include "iremote_broker.h"
23#include "iremote_object.h"
24
25#include "include/util.h"
26
27#include "coordination_manager_impl.h"
28#include "devicestatus_common.h"
29#include "devicestatus_define.h"
30#include "drag_manager_impl.h"
31#ifdef OHOS_BUILD_ENABLE_RUST_IMPL
32#include "fusion_data_binding_internal.h"
33#include "fusion_frameworks_binding.h"
34#endif // OHOS_BUILD_ENABLE_RUST_IMPL
35
36#undef LOG_TAG
37#define LOG_TAG "DeviceStatusClient"
38
39namespace OHOS {
40namespace Msdp {
41namespace DeviceStatus {
42
43DeviceStatusClient::DeviceStatusClient() {}
44DeviceStatusClient::~DeviceStatusClient()
45{
46    if (devicestatusProxy_ != nullptr) {
47        auto remoteObject = devicestatusProxy_->AsObject();
48        if (remoteObject != nullptr) {
49            remoteObject->RemoveDeathRecipient(deathRecipient_);
50        }
51    }
52}
53
54ErrCode DeviceStatusClient::Connect()
55{
56    std::lock_guard<std::mutex> lock(mutex_);
57    if (devicestatusProxy_ != nullptr) {
58        return RET_OK;
59    }
60
61    sptr<ISystemAbilityManager> sa = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
62    CHKPR(sa, E_DEVICESTATUS_GET_SYSTEM_ABILITY_MANAGER_FAILED);
63
64    sptr<IRemoteObject> remoteObject = sa->CheckSystemAbility(MSDP_DEVICESTATUS_SERVICE_ID);
65    CHKPR(remoteObject, E_DEVICESTATUS_GET_SERVICE_FAILED);
66
67    deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new (std::nothrow) DeviceStatusDeathRecipient());
68    CHKPR(deathRecipient_, ERR_NO_MEMORY);
69
70    if (remoteObject->IsProxyObject()) {
71        if (!remoteObject->AddDeathRecipient(deathRecipient_)) {
72            FI_HILOGE("Add death recipient to DeviceStatus service failed");
73            return E_DEVICESTATUS_ADD_DEATH_RECIPIENT_FAILED;
74        }
75    }
76
77    devicestatusProxy_ = iface_cast<Idevicestatus>(remoteObject);
78    FI_HILOGD("Connecting DeviceStatusService success");
79    return RET_OK;
80}
81
82void DeviceStatusClient::ResetProxy(const wptr<IRemoteObject> &remote)
83{
84    std::lock_guard<std::mutex> lock(mutex_);
85    CHKPV(devicestatusProxy_);
86    auto serviceRemote = devicestatusProxy_->AsObject();
87    if ((serviceRemote != nullptr) && (serviceRemote == remote.promote())) {
88        serviceRemote->RemoveDeathRecipient(deathRecipient_);
89        devicestatusProxy_ = nullptr;
90    }
91    if (deathListener_ != nullptr) {
92        FI_HILOGI("Notify service death to listener");
93        deathListener_();
94    }
95}
96
97void DeviceStatusClient::DeviceStatusDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
98{
99    CHKPV(remote);
100    DeviceStatusClient::GetInstance().ResetProxy(remote);
101    FI_HILOGD("Recv death notice");
102}
103
104int32_t DeviceStatusClient::SubscribeCallback(Type type, ActivityEvent event, ReportLatencyNs latency,
105    sptr<IRemoteDevStaCallback> callback)
106{
107    FI_HILOGI("Enter event:%{public}d, latency:%{public}d", event, latency);
108    auto [_, ret] = typeMap_.insert(std::make_pair(type, 1));
109    if (!ret) {
110        FI_HILOGW("Insert pair to typeMap_ failed");
111    }
112    FI_HILOGD("typeMap_:%{public}d, type:%{public}d", typeMap_[type], type);
113    CHKPR(callback, RET_ERR);
114
115    if (Connect() != RET_OK) {
116        FI_HILOGE("Connect failed");
117        return RET_ERR;
118    }
119    CHKPR(devicestatusProxy_, RET_ERR);
120
121    if (type > Type::TYPE_INVALID && type <= Type::TYPE_LID_OPEN) {
122        devicestatusProxy_->Subscribe(type, event, latency, callback);
123    }
124    return RET_OK;
125}
126
127int32_t DeviceStatusClient::UnsubscribeCallback(Type type, ActivityEvent event, sptr<IRemoteDevStaCallback> callback)
128{
129    CALL_DEBUG_ENTER;
130    FI_HILOGI("UNevent:%{public}d", event);
131    typeMap_.erase(type);
132    FI_HILOGD("typeMap_ %{public}d", typeMap_[type]);
133    CHKPR(callback, RET_ERR);
134
135    if (Connect() != RET_OK) {
136        FI_HILOGE("Connect failed");
137        return RET_ERR;
138    }
139    CHKPR(devicestatusProxy_, RET_ERR);
140
141    if ((type < TYPE_INVALID) || (type > TYPE_MAX)) {
142        FI_HILOGE("type out of range");
143        return RET_ERR;
144    }
145    if (event < ActivityEvent::EVENT_INVALID || event > ActivityEvent::ENTER_EXIT) {
146        FI_HILOGE("event out of range");
147        return RET_ERR;
148    }
149    devicestatusProxy_->Unsubscribe(type, event, callback);
150    return RET_OK;
151}
152
153Data DeviceStatusClient::GetDeviceStatusData(Type type)
154{
155    CALL_DEBUG_ENTER;
156    Data devicestatusData;
157    devicestatusData.type = type;
158    devicestatusData.value = OnChangedValue::VALUE_INVALID;
159    if (Connect() != RET_OK) {
160        FI_HILOGE("Connect failed");
161        return devicestatusData;
162    }
163    if (devicestatusProxy_ == nullptr) {
164        FI_HILOGE("devicestatusProxy_ is nullptr");
165        return devicestatusData;
166    }
167    if (type > Type::TYPE_INVALID
168        && type <= Type::TYPE_LID_OPEN) {
169        devicestatusData = devicestatusProxy_->GetCache(type);
170    }
171    return devicestatusData;
172}
173
174#ifdef OHOS_BUILD_ENABLE_RUST_IMPL
175
176int32_t DeviceStatusClient::RegisterCoordinationListener()
177{
178    CALL_DEBUG_ENTER;
179    return fusion_register_coordination_listener();
180}
181
182int32_t DeviceStatusClient::UnregisterCoordinationListener()
183{
184    CALL_DEBUG_ENTER;
185    return fusion_unregister_coordination_listener();
186}
187
188int32_t DeviceStatusClient::PrepareCoordination(int32_t userData)
189{
190    CALL_DEBUG_ENTER;
191    return fusion_enable_coordination(userData);
192}
193
194int32_t DeviceStatusClient::UnprepareCoordination(int32_t userData)
195{
196    CALL_DEBUG_ENTER;
197    return fusion_disable_coordination(userData);
198}
199
200int32_t DeviceStatusClient::ActivateCoordination(int32_t userData,
201    const std::string &remoteNetworkId, int32_t startDeviceId)
202{
203    CALL_DEBUG_ENTER;
204    return fusion_start_coordination(userData, remoteNetworkId.c_str(), startDeviceId);
205}
206
207int32_t DeviceStatusClient::DeactivateCoordination(int32_t userData, bool isUnchained)
208{
209    CALL_DEBUG_ENTER;
210    return fusion_stop_coordination(userData, isUnchained);
211}
212
213int32_t DeviceStatusClient::GetCoordinationState(int32_t userData, const std::string &networkId)
214{
215    CALL_DEBUG_ENTER;
216    return fusion_get_coordination_state(userData, networkId.c_str());
217}
218
219#else // OHOS_BUILD_ENABLE_RUST_IMPL
220
221int32_t DeviceStatusClient::RegisterCoordinationListener(bool isCompatible)
222{
223    CALL_DEBUG_ENTER;
224    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
225    return devicestatusProxy_->RegisterCoordinationListener(isCompatible);
226}
227
228int32_t DeviceStatusClient::UnregisterCoordinationListener(bool isCompatible)
229{
230    CALL_DEBUG_ENTER;
231    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
232    return devicestatusProxy_->UnregisterCoordinationListener(isCompatible);
233}
234
235int32_t DeviceStatusClient::PrepareCoordination(int32_t userData, bool isCompatible)
236{
237    CALL_DEBUG_ENTER;
238    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
239    return devicestatusProxy_->PrepareCoordination(userData, isCompatible);
240}
241
242int32_t DeviceStatusClient::UnprepareCoordination(int32_t userData, bool isCompatible)
243{
244    CALL_DEBUG_ENTER;
245    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
246    return devicestatusProxy_->UnprepareCoordination(userData, isCompatible);
247}
248
249int32_t DeviceStatusClient::ActivateCoordination(int32_t userData,
250    const std::string &remoteNetworkId, int32_t startDeviceId, bool isCompatible)
251{
252    CALL_DEBUG_ENTER;
253    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
254    return devicestatusProxy_->ActivateCoordination(userData, remoteNetworkId, startDeviceId, isCompatible);
255}
256
257int32_t DeviceStatusClient::DeactivateCoordination(int32_t userData, bool isUnchained, bool isCompatible)
258{
259    CALL_DEBUG_ENTER;
260    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
261    return devicestatusProxy_->DeactivateCoordination(userData, isUnchained, isCompatible);
262}
263
264int32_t DeviceStatusClient::GetCoordinationState(int32_t userData, const std::string &networkId, bool isCompatible)
265{
266    CALL_DEBUG_ENTER;
267    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
268    return devicestatusProxy_->GetCoordinationState(userData, networkId, isCompatible);
269}
270
271int32_t DeviceStatusClient::GetCoordinationState(const std::string &udId, bool &state)
272{
273    CALL_DEBUG_ENTER;
274    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
275    return devicestatusProxy_->GetCoordinationState(udId, state);
276}
277
278#endif // OHOS_BUILD_ENABLE_RUST_IMPL
279
280int32_t DeviceStatusClient::UpdateDragStyle(DragCursorStyle style)
281{
282    CALL_DEBUG_ENTER;
283    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
284    return devicestatusProxy_->UpdateDragStyle(style);
285}
286
287int32_t DeviceStatusClient::GetDragTargetPid()
288{
289    CALL_DEBUG_ENTER;
290    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
291    return devicestatusProxy_->GetDragTargetPid();
292}
293
294int32_t DeviceStatusClient::GetUdKey(std::string &udKey)
295{
296    CALL_DEBUG_ENTER;
297    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
298    return devicestatusProxy_->GetUdKey(udKey);
299}
300
301#ifdef OHOS_BUILD_ENABLE_RUST_IMPL
302
303int32_t DeviceStatusClient::AllocSocketPair(int32_t moduleType)
304{
305    const std::string programName(GetProgramName());
306    int32_t ret = fusion_alloc_socket_fd(programName.c_str(), moduleType, &socketFd_, &tokenType_);
307    if (ret != RET_OK) {
308        FI_HILOGE("Failed to connect to server via socket:%{public}d", ret);
309        return RET_ERR;
310    }
311    FI_HILOGI("Connected successfully to server via socket, "
312        "socketFd_:%{public}d tokenType_:%{public}d",
313        socketFd_, tokenType_);
314    return RET_OK;
315}
316
317#else // OHOS_BUILD_ENABLE_RUST_IMPL
318
319int32_t DeviceStatusClient::AllocSocketPair(int32_t moduleType)
320{
321    CALL_DEBUG_ENTER;
322    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
323    std::lock_guard<std::mutex> guard(mutex_);
324    CHKPR(devicestatusProxy_, RET_ERR);
325    const std::string programName(GetProgramName());
326    int32_t result = devicestatusProxy_->AllocSocketFd(programName, moduleType, socketFd_, tokenType_);
327    if (result != RET_OK) {
328        FI_HILOGE("AllocSocketFd has error:%{public}d", result);
329        return RET_ERR;
330    }
331
332    FI_HILOGI("AllocSocketPair success, socketFd_:%{public}d, tokenType_:%{public}d", socketFd_, tokenType_);
333    return RET_OK;
334}
335
336#endif // OHOS_BUILD_ENABLE_RUST_IMPL
337
338int32_t DeviceStatusClient::GetClientSocketFdOfAllocedSocketPair() const
339{
340    CALL_DEBUG_ENTER;
341    return socketFd_;
342}
343
344void DeviceStatusClient::RegisterDeathListener(std::function<void()> deathListener)
345{
346    deathListener_ = deathListener;
347}
348
349#ifdef OHOS_BUILD_ENABLE_RUST_IMPL
350
351int32_t DeviceStatusClient::StartDrag(const DragData &dragData)
352{
353    CALL_DEBUG_ENTER;
354    CDragData cDragData;
355    if (CDragDataFrom(&dragData, &cDragData) != RET_OK) {
356        FI_HILOGE("Conversion of DragData to CDragData failed");
357        return RET_ERR;
358    }
359    int32_t ret = fusion_start_drag(&cDragData);
360    CDragDataFree(&cDragData);
361    return ret;
362}
363
364#else // OHOS_BUILD_ENABLE_RUST_IMPL
365
366int32_t DeviceStatusClient::StartDrag(const DragData &dragData)
367{
368    CALL_DEBUG_ENTER;
369    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
370    CHKPR(devicestatusProxy_, RET_ERR);
371    return devicestatusProxy_->StartDrag(dragData);
372}
373
374#endif // OHOS_BUILD_ENABLE_RUST_IMPL
375
376int32_t DeviceStatusClient::StopDrag(const DragDropResult &dropResult)
377{
378    CALL_DEBUG_ENTER;
379    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
380    CHKPR(devicestatusProxy_, RET_ERR);
381    return devicestatusProxy_->StopDrag(dropResult);
382}
383
384int32_t DeviceStatusClient::AddDraglistener()
385{
386    CALL_DEBUG_ENTER;
387    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
388    return devicestatusProxy_->AddDraglistener();
389}
390
391int32_t DeviceStatusClient::RemoveDraglistener()
392{
393    CALL_DEBUG_ENTER;
394    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
395    return devicestatusProxy_->RemoveDraglistener();
396}
397
398int32_t DeviceStatusClient::AddSubscriptListener()
399{
400    CALL_DEBUG_ENTER;
401    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
402    return devicestatusProxy_->AddSubscriptListener();
403}
404
405int32_t DeviceStatusClient::RemoveSubscriptListener()
406{
407    CALL_DEBUG_ENTER;
408    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
409    return devicestatusProxy_->RemoveSubscriptListener();
410}
411
412int32_t DeviceStatusClient::SetDragWindowVisible(bool visible, bool isForce)
413{
414    CALL_DEBUG_ENTER;
415    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
416    return devicestatusProxy_->SetDragWindowVisible(visible, isForce);
417}
418
419int32_t DeviceStatusClient::GetShadowOffset(ShadowOffset &shadowOffset)
420{
421    CALL_DEBUG_ENTER;
422    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
423    return devicestatusProxy_->GetShadowOffset(shadowOffset);
424}
425
426int32_t DeviceStatusClient::UpdateShadowPic(const ShadowInfo &shadowInfo)
427{
428    CALL_DEBUG_ENTER;
429    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
430    return devicestatusProxy_->UpdateShadowPic(shadowInfo);
431}
432
433int32_t DeviceStatusClient::GetDragData(DragData &dragData)
434{
435    CALL_DEBUG_ENTER;
436    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
437    return devicestatusProxy_->GetDragData(dragData);
438}
439
440int32_t DeviceStatusClient::GetDragState(DragState &dragState)
441{
442    CALL_DEBUG_ENTER;
443    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
444    return devicestatusProxy_->GetDragState(dragState);
445}
446
447int32_t DeviceStatusClient::GetDragAction(DragAction& dragAction)
448{
449    CALL_DEBUG_ENTER;
450    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
451    return devicestatusProxy_->GetDragAction(dragAction);
452}
453
454int32_t DeviceStatusClient::GetExtraInfo(std::string &extraInfo)
455{
456    CALL_DEBUG_ENTER;
457    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
458    return devicestatusProxy_->GetExtraInfo(extraInfo);
459}
460
461int32_t DeviceStatusClient::AddHotAreaListener()
462{
463    CALL_DEBUG_ENTER;
464    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
465    return devicestatusProxy_->AddHotAreaListener();
466}
467
468int32_t DeviceStatusClient::RemoveHotAreaListener()
469{
470    CALL_DEBUG_ENTER;
471    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
472    return devicestatusProxy_->RemoveHotAreaListener();
473}
474
475int32_t DeviceStatusClient::UpdatePreviewStyle(const PreviewStyle &previewStyle)
476{
477    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
478    return devicestatusProxy_->UpdatePreviewStyle(previewStyle);
479}
480
481int32_t DeviceStatusClient::UpdatePreviewStyleWithAnimation(const PreviewStyle &previewStyle,
482    const PreviewAnimation &animation)
483{
484    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
485    return devicestatusProxy_->UpdatePreviewStyleWithAnimation(previewStyle, animation);
486}
487
488int32_t DeviceStatusClient::GetDragSummary(std::map<std::string, int64_t> &summarys)
489{
490    CALL_DEBUG_ENTER;
491    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
492    return devicestatusProxy_->GetDragSummary(summarys);
493}
494
495int32_t DeviceStatusClient::EnterTextEditorArea(bool enable)
496{
497    CALL_DEBUG_ENTER;
498    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
499    return devicestatusProxy_->EnterTextEditorArea(enable);
500}
501
502int32_t DeviceStatusClient::AddPrivilege()
503{
504    CALL_DEBUG_ENTER;
505    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
506    return devicestatusProxy_->AddPrivilege();
507}
508
509int32_t DeviceStatusClient::EraseMouseIcon()
510{
511    CALL_DEBUG_ENTER;
512    DEV_RET_IF_NULL_WITH_RET((Connect() != RET_OK), RET_ERR);
513    return devicestatusProxy_->EraseMouseIcon();
514}
515} // namespace DeviceStatus
516} // namespace Msdp
517} // namespace OHOS
518