1/*
2 * Copyright (c) 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 "tunnel_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 "devicestatus_define.h"
26
27#undef LOG_TAG
28#define LOG_TAG "TunnelClient"
29
30namespace OHOS {
31namespace Msdp {
32namespace DeviceStatus {
33
34TunnelClient::~TunnelClient()
35{
36    if (devicestatusProxy_ != nullptr) {
37        auto remoteObject = devicestatusProxy_->AsObject();
38        if (remoteObject != nullptr) {
39            remoteObject->RemoveDeathRecipient(deathRecipient_);
40        }
41    }
42}
43
44int32_t TunnelClient::Enable(Intention intention, ParamBase &data, ParamBase &reply)
45{
46    CALL_DEBUG_ENTER;
47    MessageParcel dataParcel;
48    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
49        FI_HILOGE("WriteInterfaceToken fail");
50        return RET_ERR;
51    }
52    if (!data.Marshalling(dataParcel)) {
53        FI_HILOGE("ParamBase::Marshalling fail");
54        return RET_ERR;
55    }
56    if (Connect() != RET_OK) {
57        FI_HILOGE("Can not connect to IntentionService");
58        return RET_ERR;
59    }
60    MessageParcel replyParcel;
61    int32_t ret = devicestatusProxy_->Enable(intention, dataParcel, replyParcel);
62    if (ret != RET_OK) {
63        FI_HILOGE("proxy::Enable fail");
64        return RET_ERR;
65    }
66    if (!reply.Unmarshalling(replyParcel)) {
67        FI_HILOGE("ParamBase::Unmarshalling fail");
68        return RET_ERR;
69    }
70    return RET_OK;
71}
72
73int32_t TunnelClient::Disable(Intention intention, ParamBase &data, ParamBase &reply)
74{
75    CALL_DEBUG_ENTER;
76    MessageParcel dataParcel;
77    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
78        FI_HILOGE("WriteInterfaceToken fail");
79        return RET_ERR;
80    }
81    if (!data.Marshalling(dataParcel)) {
82        FI_HILOGE("ParamBase::Marshalling fail");
83        return RET_ERR;
84    }
85    if (Connect() != RET_OK) {
86        FI_HILOGE("Can not connect to IntentionService");
87        return RET_ERR;
88    }
89    MessageParcel replyParcel;
90    int32_t ret = devicestatusProxy_->Disable(intention, dataParcel, replyParcel);
91    if (ret != RET_OK) {
92        FI_HILOGE("proxy::Disable fail");
93        return RET_ERR;
94    }
95    if (!reply.Unmarshalling(replyParcel)) {
96        FI_HILOGE("ParamBase::Unmarshalling fail");
97        return RET_ERR;
98    }
99    return RET_OK;
100}
101
102int32_t TunnelClient::Start(Intention intention, ParamBase &data, ParamBase &reply)
103{
104    CALL_DEBUG_ENTER;
105    MessageParcel dataParcel;
106    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
107        FI_HILOGE("WriteInterfaceToken fail");
108        return RET_ERR;
109    }
110    if (!data.Marshalling(dataParcel)) {
111        FI_HILOGE("ParamBase::Marshalling fail");
112        return RET_ERR;
113    }
114    if (Connect() != RET_OK) {
115        FI_HILOGE("Can not connect to IntentionService");
116        return RET_ERR;
117    }
118    MessageParcel replyParcel;
119    int32_t ret = devicestatusProxy_->Start(intention, dataParcel, replyParcel);
120    if (ret != RET_OK) {
121        FI_HILOGE("proxy::Start fail");
122        return ret;
123    }
124    if (!reply.Unmarshalling(replyParcel)) {
125        FI_HILOGE("ParamBase::Unmarshalling fail");
126        return RET_ERR;
127    }
128    return RET_OK;
129}
130
131int32_t TunnelClient::Stop(Intention intention, ParamBase &data, ParamBase &reply)
132{
133    CALL_DEBUG_ENTER;
134    MessageParcel dataParcel;
135    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
136        FI_HILOGE("WriteInterfaceToken fail");
137        return RET_ERR;
138    }
139    if (!data.Marshalling(dataParcel)) {
140        FI_HILOGE("ParamBase::Marshalling fail");
141        return RET_ERR;
142    }
143    if (Connect() != RET_OK) {
144        FI_HILOGE("Can not connect to IntentionService");
145        return RET_ERR;
146    }
147    MessageParcel replyParcel;
148    int32_t ret = devicestatusProxy_->Stop(intention, dataParcel, replyParcel);
149    if (ret != RET_OK) {
150        FI_HILOGE("proxy::Stop fail");
151        return RET_ERR;
152    }
153    if (!reply.Unmarshalling(replyParcel)) {
154        FI_HILOGE("ParamBase::Unmarshalling fail");
155        return RET_ERR;
156    }
157    return RET_OK;
158}
159
160int32_t TunnelClient::AddWatch(Intention intention, uint32_t id, ParamBase &data, ParamBase &reply)
161{
162    CALL_DEBUG_ENTER;
163    MessageParcel dataParcel;
164    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
165        FI_HILOGE("WriteInterfaceToken fail");
166        return RET_ERR;
167    }
168    if (!data.Marshalling(dataParcel)) {
169        FI_HILOGE("ParamBase::Marshalling fail");
170        return RET_ERR;
171    }
172    if (Connect() != RET_OK) {
173        FI_HILOGE("Can not connect to IntentionService");
174        return RET_ERR;
175    }
176    MessageParcel replyParcel;
177    int32_t ret = devicestatusProxy_->AddWatch(intention, id, dataParcel, replyParcel);
178    if (ret != RET_OK) {
179        FI_HILOGE("proxy::AddWatch fail");
180        return RET_ERR;
181    }
182    if (!reply.Unmarshalling(replyParcel)) {
183        FI_HILOGE("ParamBase::Unmarshalling fail");
184        return RET_ERR;
185    }
186    return RET_OK;
187}
188
189int32_t TunnelClient::RemoveWatch(Intention intention, uint32_t id, ParamBase &data, ParamBase &reply)
190{
191    CALL_DEBUG_ENTER;
192    MessageParcel dataParcel;
193    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
194        FI_HILOGE("WriteInterfaceToken fail");
195        return RET_ERR;
196    }
197    if (!data.Marshalling(dataParcel)) {
198        FI_HILOGE("ParamBase::Marshalling fail");
199        return RET_ERR;
200    }
201    if (Connect() != RET_OK) {
202        FI_HILOGE("Can not connect to IntentionService");
203        return RET_ERR;
204    }
205    MessageParcel replyParcel;
206    int32_t ret = devicestatusProxy_->RemoveWatch(intention, id, dataParcel, replyParcel);
207    if (ret != RET_OK) {
208        FI_HILOGE("proxy::RemoveWatch fail");
209        return RET_ERR;
210    }
211    if (!reply.Unmarshalling(replyParcel)) {
212        FI_HILOGE("ParamBase::Unmarshalling fail");
213        return RET_ERR;
214    }
215    return RET_OK;
216}
217
218int32_t TunnelClient::SetParam(Intention intention, uint32_t id, ParamBase &data, ParamBase &reply)
219{
220    CALL_DEBUG_ENTER;
221    MessageParcel dataParcel;
222    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
223        FI_HILOGE("WriteInterfaceToken fail");
224        return RET_ERR;
225    }
226    if (!data.Marshalling(dataParcel)) {
227        FI_HILOGE("ParamBase::Marshalling fail");
228        return RET_ERR;
229    }
230    if (Connect() != RET_OK) {
231        FI_HILOGE("Can not connect to IntentionService");
232        return RET_ERR;
233    }
234    MessageParcel replyParcel;
235    int32_t ret = devicestatusProxy_->SetParam(intention, id, dataParcel, replyParcel);
236    if (ret != RET_OK) {
237        FI_HILOGE("proxy::SetParam fail");
238        return RET_ERR;
239    }
240    if (!reply.Unmarshalling(replyParcel)) {
241        FI_HILOGE("ParamBase::Unmarshalling fail");
242        return RET_ERR;
243    }
244    return RET_OK;
245}
246
247int32_t TunnelClient::GetParam(Intention intention, uint32_t id, ParamBase &data, ParamBase &reply)
248{
249    CALL_DEBUG_ENTER;
250    MessageParcel dataParcel;
251    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
252        FI_HILOGE("WriteInterfaceToken fail");
253        return RET_ERR;
254    }
255    if (!data.Marshalling(dataParcel)) {
256        FI_HILOGE("ParamBase::Marshalling fail");
257        return RET_ERR;
258    }
259    if (Connect() != RET_OK) {
260        FI_HILOGE("Can not connect to IntentionService");
261        return RET_ERR;
262    }
263    MessageParcel replyParcel;
264    int32_t ret = devicestatusProxy_->GetParam(intention, id, dataParcel, replyParcel);
265    if (ret != RET_OK) {
266        FI_HILOGE("proxy::GetParam fail");
267        return RET_ERR;
268    }
269    if (!reply.Unmarshalling(replyParcel)) {
270        FI_HILOGE("ParamBase::Unmarshalling fail");
271        return RET_ERR;
272    }
273    return RET_OK;
274}
275
276int32_t TunnelClient::Control(Intention intention, uint32_t id, ParamBase &data, ParamBase &reply)
277{
278    CALL_DEBUG_ENTER;
279    MessageParcel dataParcel;
280    if (!dataParcel.WriteInterfaceToken(IIntention::GetDescriptor())) {
281        FI_HILOGE("WriteInterfaceToken fail");
282        return RET_ERR;
283    }
284    if (!data.Marshalling(dataParcel)) {
285        FI_HILOGE("ParamBase::Marshalling fail");
286        return RET_ERR;
287    }
288    if (Connect() != RET_OK) {
289        FI_HILOGE("Can not connect to IntentionService");
290        return RET_ERR;
291    }
292    MessageParcel replyParcel;
293    int32_t ret = devicestatusProxy_->Control(intention, id, dataParcel, replyParcel);
294    if (ret != RET_OK) {
295        FI_HILOGE("proxy::Control fail");
296        return RET_ERR;
297    }
298    if (!reply.Unmarshalling(replyParcel)) {
299        FI_HILOGE("ParamBase::Unmarshalling fail");
300        return RET_ERR;
301    }
302    return RET_OK;
303}
304
305ErrCode TunnelClient::Connect()
306{
307    CALL_DEBUG_ENTER;
308    std::lock_guard lock(mutex_);
309    if (devicestatusProxy_ != nullptr) {
310        return RET_OK;
311    }
312
313    sptr<ISystemAbilityManager> sa = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
314    CHKPR(sa, E_DEVICESTATUS_GET_SYSTEM_ABILITY_MANAGER_FAILED);
315
316    sptr<IRemoteObject> remoteObject = sa->CheckSystemAbility(MSDP_DEVICESTATUS_SERVICE_ID);
317    CHKPR(remoteObject, E_DEVICESTATUS_GET_SERVICE_FAILED);
318
319    deathRecipient_ = sptr<DeathRecipient>::MakeSptr(shared_from_this());
320    CHKPR(deathRecipient_, ERR_NO_MEMORY);
321
322    if (remoteObject->IsProxyObject()) {
323        if (!remoteObject->AddDeathRecipient(deathRecipient_)) {
324            FI_HILOGE("Add death recipient to DeviceStatus service failed");
325            return E_DEVICESTATUS_ADD_DEATH_RECIPIENT_FAILED;
326        }
327    }
328
329    devicestatusProxy_ = iface_cast<IIntention>(remoteObject);
330    FI_HILOGD("Connecting IntentionService success");
331    return RET_OK;
332}
333
334void TunnelClient::ResetProxy(const wptr<IRemoteObject> &remote)
335{
336    CALL_DEBUG_ENTER;
337    std::lock_guard lock(mutex_);
338    CHKPV(devicestatusProxy_);
339    auto serviceRemote = devicestatusProxy_->AsObject();
340    if ((serviceRemote != nullptr) && (serviceRemote == remote.promote())) {
341        serviceRemote->RemoveDeathRecipient(deathRecipient_);
342        devicestatusProxy_ = nullptr;
343    }
344}
345
346TunnelClient::DeathRecipient::DeathRecipient(std::shared_ptr<TunnelClient> parent)
347    : parent_(parent)
348{}
349
350void TunnelClient::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
351{
352    CALL_DEBUG_ENTER;
353    std::shared_ptr<TunnelClient> parent = parent_.lock();
354    CHKPV(parent);
355    CHKPV(remote);
356    parent->ResetProxy(remote);
357    FI_HILOGD("Recv death notice");
358}
359} // namespace DeviceStatus
360} // namespace Msdp
361} // namespace OHOS
362