1 /*
2  * Copyright (c) 2023-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 "intention_service.h"
17 
18 #include <ipc_skeleton.h>
19 #include <string_ex.h>
20 #include <xcollie/xcollie.h>
21 #include <xcollie/xcollie_define.h>
22 
23 #include "devicestatus_define.h"
24 #include "i_plugin.h"
25 
26 #undef LOG_TAG
27 #define LOG_TAG "IntentionService"
28 
29 namespace OHOS {
30 namespace Msdp {
31 namespace DeviceStatus {
32 namespace {
33 constexpr int32_t SERVER_TIMEOUT { 5 };
34 }
35 
IntentionService(IContext *context)36 IntentionService::IntentionService(IContext *context)
37     : context_(context), socketServer_(context), cooperate_(context), drag_(context), dumper_(context, stationary_)
38 {}
39 
Dump(int fd, const std::vector<std::u16string> &args)40 int32_t IntentionService::Dump(int fd, const std::vector<std::u16string> &args)
41 {
42     std::vector<std::string> argList;
43     std::transform(args.begin(), args.end(), std::back_inserter(argList),
44         [](const std::u16string &arg) {
45             return Str16ToStr8(arg);
46         });
47     dumper_.Dump(fd, argList);
48     return RET_OK;
49 }
50 
Enable(Intention intention, MessageParcel &data, MessageParcel &reply)51 int32_t IntentionService::Enable(Intention intention, MessageParcel &data, MessageParcel &reply)
52 {
53     CallingContext context {
54         .intention = intention,
55         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
56         .tokenId = IPCSkeleton::GetCallingTokenID(),
57         .uid = IPCSkeleton::GetCallingUid(),
58         .pid = IPCSkeleton::GetCallingPid(),
59     };
60     CHKPR(context_, RET_ERR);
61     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
62         IPlugin *plugin = LoadPlugin(context.intention);
63         CHKPR(plugin, RET_ERR);
64         return plugin->Enable(context, data, reply);
65     });
66     if (ret != RET_OK) {
67         FI_HILOGE("Enable failed, ret:%{public}d", ret);
68     }
69     return ret;
70 }
71 
Disable(Intention intention, MessageParcel &data, MessageParcel &reply)72 int32_t IntentionService::Disable(Intention intention, MessageParcel &data, MessageParcel &reply)
73 {
74     CallingContext context {
75         .intention = intention,
76         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
77         .tokenId = IPCSkeleton::GetCallingTokenID(),
78         .uid = IPCSkeleton::GetCallingUid(),
79         .pid = IPCSkeleton::GetCallingPid(),
80     };
81     CHKPR(context_, RET_ERR);
82     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
83         IPlugin *plugin = LoadPlugin(context.intention);
84         CHKPR(plugin, RET_ERR);
85         return plugin->Disable(context, data, reply);
86     });
87     if (ret != RET_OK) {
88         FI_HILOGE("Disable failed, ret:%{public}d", ret);
89     }
90     return ret;
91 }
92 
Start(Intention intention, MessageParcel &data, MessageParcel &reply)93 int32_t IntentionService::Start(Intention intention, MessageParcel &data, MessageParcel &reply)
94 {
95     CallingContext context {
96         .intention = intention,
97         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
98         .tokenId = IPCSkeleton::GetCallingTokenID(),
99         .uid = IPCSkeleton::GetCallingUid(),
100         .pid = IPCSkeleton::GetCallingPid(),
101     };
102     CHKPR(context_, RET_ERR);
103     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
104         IPlugin *plugin = LoadPlugin(context.intention);
105         CHKPR(plugin, RET_ERR);
106         return plugin->Start(context, data, reply);
107     });
108     if (ret != RET_OK) {
109         FI_HILOGE("Start failed, ret:%{public}d", ret);
110     }
111     return ret;
112 }
113 
Stop(Intention intention, MessageParcel &data, MessageParcel &reply)114 int32_t IntentionService::Stop(Intention intention, MessageParcel &data, MessageParcel &reply)
115 {
116     CallingContext context {
117         .intention = intention,
118         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
119         .tokenId = IPCSkeleton::GetCallingTokenID(),
120         .uid = IPCSkeleton::GetCallingUid(),
121         .pid = IPCSkeleton::GetCallingPid(),
122     };
123     CHKPR(context_, RET_ERR);
124     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
125         IPlugin *plugin = LoadPlugin(context.intention);
126         CHKPR(plugin, RET_ERR);
127         return plugin->Stop(context, data, reply);
128     });
129     if (ret != RET_OK) {
130         FI_HILOGE("Stop failed, ret:%{public}d", ret);
131     }
132     return ret;
133 }
134 
AddWatch(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)135 int32_t IntentionService::AddWatch(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)
136 {
137     CHKPR(context_, RET_ERR);
138     int32_t timerId = HiviewDFX::XCollie::GetInstance().SetTimer("DeviceStatusIntensionServerAddWatch", SERVER_TIMEOUT,
139         nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_LOG);
140     CallingContext context {
141         .intention = intention,
142         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
143         .tokenId = IPCSkeleton::GetCallingTokenID(),
144         .uid = IPCSkeleton::GetCallingUid(),
145         .pid = IPCSkeleton::GetCallingPid(),
146     };
147     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
148         IPlugin *plugin = LoadPlugin(context.intention);
149         CHKPR(plugin, RET_ERR);
150         return plugin->AddWatch(context, id, data, reply);
151     });
152     if (ret != RET_OK) {
153         FI_HILOGE("AddWatch failed, ret:%{public}d", ret);
154     }
155     HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
156     return ret;
157 }
158 
RemoveWatch(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)159 int32_t IntentionService::RemoveWatch(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)
160 {
161     CallingContext context {
162         .intention = intention,
163         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
164         .tokenId = IPCSkeleton::GetCallingTokenID(),
165         .uid = IPCSkeleton::GetCallingUid(),
166         .pid = IPCSkeleton::GetCallingPid(),
167     };
168     CHKPR(context_, RET_ERR);
169     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
170         IPlugin *plugin = LoadPlugin(context.intention);
171         CHKPR(plugin, RET_ERR);
172         return plugin->RemoveWatch(context, id, data, reply);
173     });
174     if (ret != RET_OK) {
175         FI_HILOGE("RemoveWatch failed, ret:%{public}d", ret);
176     }
177     return ret;
178 }
179 
SetParam(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)180 int32_t IntentionService::SetParam(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)
181 {
182     CallingContext context {
183         .intention = intention,
184         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
185         .tokenId = IPCSkeleton::GetCallingTokenID(),
186         .uid = IPCSkeleton::GetCallingUid(),
187         .pid = IPCSkeleton::GetCallingPid(),
188     };
189     CHKPR(context_, RET_ERR);
190     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
191         IPlugin *plugin = LoadPlugin(context.intention);
192         CHKPR(plugin, RET_ERR);
193         return plugin->SetParam(context, id, data, reply);
194     });
195     if (ret != RET_OK) {
196         FI_HILOGE("SetParam failed, ret:%{public}d", ret);
197     }
198     return ret;
199 }
200 
GetParam(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)201 int32_t IntentionService::GetParam(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)
202 {
203     CallingContext context {
204         .intention = intention,
205         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
206         .tokenId = IPCSkeleton::GetCallingTokenID(),
207         .uid = IPCSkeleton::GetCallingUid(),
208         .pid = IPCSkeleton::GetCallingPid(),
209     };
210     CHKPR(context_, RET_ERR);
211     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
212         IPlugin *plugin = LoadPlugin(context.intention);
213         CHKPR(plugin, RET_ERR);
214         return plugin->GetParam(context, id, data, reply);
215     });
216     if (ret != RET_OK) {
217         FI_HILOGE("GetParam failed, ret:%{public}d", ret);
218     }
219     return ret;
220 }
221 
Control(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)222 int32_t IntentionService::Control(Intention intention, uint32_t id, MessageParcel &data, MessageParcel &reply)
223 {
224     CHKPR(context_, RET_ERR);
225     int32_t timerId = HiviewDFX::XCollie::GetInstance().SetTimer("DeviceStatusIntensionServerControl", SERVER_TIMEOUT,
226         nullptr, nullptr, HiviewDFX::XCOLLIE_FLAG_LOG);
227     CallingContext context {
228         .intention = intention,
229         .fullTokenId = IPCSkeleton::GetCallingFullTokenID(),
230         .tokenId = IPCSkeleton::GetCallingTokenID(),
231         .uid = IPCSkeleton::GetCallingUid(),
232         .pid = IPCSkeleton::GetCallingPid(),
233     };
234     int32_t ret = context_->GetDelegateTasks().PostSyncTask([&] {
235         IPlugin *plugin = LoadPlugin(context.intention);
236         CHKPR(plugin, RET_ERR);
237         return plugin->Control(context, id, data, reply);
238     });
239     if (ret != RET_OK) {
240         FI_HILOGE("Control failed, ret:%{public}d", ret);
241     }
242     HiviewDFX::XCollie::GetInstance().CancelTimer(timerId);
243     return ret;
244 }
245 
LoadPlugin(Intention intention)246 IPlugin* IntentionService::LoadPlugin(Intention intention)
247 {
248     CALL_DEBUG_ENTER;
249     switch (intention) {
250         case Intention::SOCKET: {
251             return &socketServer_;
252         }
253         case Intention::STATIONARY: {
254             return &stationary_;
255         }
256         case Intention::COOPERATE: {
257             return &cooperate_;
258         }
259         case Intention::DRAG: {
260             return &drag_;
261         }
262         default: {
263             return nullptr;
264         }
265     }
266 }
267 } // namespace DeviceStatus
268 } // namespace Msdp
269 } // namespace OHOS
270