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 "cooperate_server.h"
17
18 #include <chrono>
19
20 #include <tokenid_kit.h>
21
22 #include "accesstoken_kit.h"
23 #include "cooperate_params.h"
24 #include "default_params.h"
25 #include "devicestatus_define.h"
26 #include "ipc_skeleton.h"
27 #include "utility.h"
28
29 #undef LOG_TAG
30 #define LOG_TAG "CooperateServer"
31
32 namespace OHOS {
33 namespace Msdp {
34 namespace DeviceStatus {
35 namespace {
36 constexpr int32_t REPEAT_ONCE { 1 };
37 constexpr int32_t DEFAULT_UNLOAD_COOLING_TIME_MS { 60000 };
38 constexpr int32_t SYNC_TASK_TIMEOUT_DURATION { 2500 };
39 }
40
CooperateServer(IContext *context)41 CooperateServer::CooperateServer(IContext *context)
42 : context_(context)
43 {}
44
Enable(CallingContext &context, MessageParcel &data, MessageParcel &reply)45 int32_t CooperateServer::Enable(CallingContext &context, MessageParcel &data, MessageParcel &reply)
46 {
47 CALL_DEBUG_ENTER;
48 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
49 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
50 return ret;
51 }
52 DefaultParam param;
53 if (!param.Unmarshalling(data)) {
54 FI_HILOGE("DefaultParam::Unmarshalling fail");
55 return RET_ERR;
56 }
57 CHKPR(context_, RET_ERR);
58 if (unloadTimerId_ >= 0) {
59 context_->GetTimerManager().RemoveTimer(unloadTimerId_);
60 }
61 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
62 CHKPR(cooperate, RET_ERR);
63 cooperate->Enable(context.tokenId, context.pid, param.userData);
64 return RET_OK;
65 }
66
Disable(CallingContext &context, MessageParcel &data, MessageParcel &reply)67 int32_t CooperateServer::Disable(CallingContext &context, MessageParcel &data, MessageParcel &reply)
68 {
69 CALL_DEBUG_ENTER;
70 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
71 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
72 return ret;
73 }
74 DefaultParam param;
75 if (!param.Unmarshalling(data)) {
76 FI_HILOGE("DefaultParam::Unmarshalling fail");
77 return RET_ERR;
78 }
79 CHKPR(context_, RET_ERR);
80 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
81 CHKPR(cooperate, RET_ERR);
82 cooperate->Disable(context.pid, param.userData);
83 unloadTimerId_ = context_->GetTimerManager().AddTimer(DEFAULT_UNLOAD_COOLING_TIME_MS, REPEAT_ONCE,
84 []() {
85 FI_HILOGI("Unload \'cooperate\' module");
86 });
87 if (unloadTimerId_ < 0) {
88 FI_HILOGE("AddTimer failed, will not unload Cooperate");
89 }
90 return RET_OK;
91 }
92
Start(CallingContext &context, MessageParcel &data, MessageParcel &reply)93 int32_t CooperateServer::Start(CallingContext &context, MessageParcel &data, MessageParcel &reply)
94 {
95 CALL_DEBUG_ENTER;
96 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
97 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
98 return ret;
99 }
100 StartCooperateParam param;
101 if (!param.Unmarshalling(data)) {
102 FI_HILOGE("StartCooperateParam::Unmarshalling fail");
103 return RET_ERR;
104 }
105 CHKPR(context_, RET_ERR);
106 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
107 CHKPR(cooperate, RET_ERR);
108 return cooperate->Start(context.pid, param.userData, param.remoteNetworkId, param.startDeviceId);
109 }
110
Stop(CallingContext &context, MessageParcel &data, MessageParcel &reply)111 int32_t CooperateServer::Stop(CallingContext &context, MessageParcel &data, MessageParcel &reply)
112 {
113 CALL_DEBUG_ENTER;
114 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
115 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
116 return ret;
117 }
118 StopCooperateParam param;
119 if (!param.Unmarshalling(data)) {
120 FI_HILOGE("StopCooperateParam::Unmarshalling fail");
121 return RET_ERR;
122 }
123 CHKPR(context_, RET_ERR);
124 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
125 CHKPR(cooperate, RET_ERR);
126 return cooperate->Stop(context.pid, param.userData, param.isUnchained);
127 }
128
AddWatch(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)129 int32_t CooperateServer::AddWatch(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
130 {
131 CALL_DEBUG_ENTER;
132 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
133 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
134 return ret;
135 }
136 CHKPR(context_, RET_ERR);
137 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
138 CHKPR(cooperate, RET_ERR);
139 switch (id) {
140 case CooperateRequestID::REGISTER_LISTENER: {
141 return cooperate->RegisterListener(context.pid);
142 }
143 case CooperateRequestID::REGISTER_HOTAREA_LISTENER: {
144 return cooperate->RegisterHotAreaListener(context.pid);
145 }
146 case CooperateRequestID::REGISTER_EVENT_LISTENER: {
147 RegisterEventListenerParam param;
148 if (!param.Unmarshalling(data)) {
149 FI_HILOGE("RegisterEventListenerParam::Unmarshalling fail");
150 return RET_ERR;
151 }
152 return cooperate->RegisterEventListener(context.pid, param.networkId);
153 }
154 default: {
155 FI_HILOGE("Unexpected request ID (%{public}u)", id);
156 return RET_ERR;
157 }
158 }
159 }
160
RemoveWatch(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)161 int32_t CooperateServer::RemoveWatch(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
162 {
163 CALL_DEBUG_ENTER;
164 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
165 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
166 return ret;
167 }
168 CHKPR(context_, RET_ERR);
169 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
170 CHKPR(cooperate, RET_ERR);
171 switch (id) {
172 case CooperateRequestID::UNREGISTER_LISTENER: {
173 return cooperate->UnregisterListener(context.pid);
174 }
175 case CooperateRequestID::UNREGISTER_HOTAREA_LISTENER: {
176 return cooperate->UnregisterHotAreaListener(context.pid);
177 }
178 case CooperateRequestID::UNREGISTER_EVENT_LISTENER: {
179 UnregisterEventListenerParam param;
180 if (!param.Unmarshalling(data)) {
181 FI_HILOGE("UnregisterEventListenerParam::Unmarshalling fail");
182 return RET_ERR;
183 }
184 return cooperate->UnregisterEventListener(context.pid, param.networkId);
185 }
186 default: {
187 FI_HILOGE("Unexpected request ID (%{public}u)", id);
188 return RET_ERR;
189 }
190 }
191 }
192
SetParam(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)193 int32_t CooperateServer::SetParam(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
194 {
195 CALL_DEBUG_ENTER;
196 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
197 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
198 return ret;
199 }
200 if (id != CooperateRequestID::SET_DAMPLING_COEFFICIENT) {
201 FI_HILOGE("Unexpected request (%{public}u)", id);
202 return RET_ERR;
203 }
204 SetDamplingCoefficientParam param {};
205 if (!param.Unmarshalling(data)) {
206 FI_HILOGE("SetDamplingCoefficientParam::Unmarshalling fail");
207 return RET_ERR;
208 }
209 CHKPR(context_, RET_ERR);
210 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
211 CHKPR(cooperate, RET_ERR);
212 FI_HILOGI("SetDamplingCoefficient(0x%{public}x, %{public}.3f)", param.direction, param.coefficient);
213 return cooperate->SetDamplingCoefficient(param.direction, param.coefficient);
214 }
215
GetParam(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)216 int32_t CooperateServer::GetParam(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
217 {
218 CALL_DEBUG_ENTER;
219 if (int32_t ret = CheckPermission(context); ret != RET_OK) {
220 FI_HILOGE("CheckPermission failed, ret:%{public}d", ret);
221 return ret;
222 }
223 CHKPR(context_, RET_ERR);
224 ICooperate* cooperate = context_->GetPluginManager().LoadCooperate();
225 CHKPR(cooperate, RET_ERR);
226 auto enterStamp = std::chrono::steady_clock::now();
227 auto checkParcelValid = [enterStamp] () {
228 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
229 std::chrono::steady_clock::now() - enterStamp).count();
230 return duration < SYNC_TASK_TIMEOUT_DURATION;
231 };
232 switch (id) {
233 case CooperateRequestID::GET_COOPERATE_STATE: {
234 GetCooperateStateParam param;
235 if (!param.Unmarshalling(data)) {
236 FI_HILOGE("GetCooperateStateParam::Unmarshalling fail");
237 return RET_ERR;
238 }
239 return cooperate->GetCooperateState(context.pid, param.userData, param.networkId);
240 }
241 case CooperateRequestID::GET_COOPERATE_STATE_SYNC: {
242 GetCooperateStateSyncParam param;
243 if (!param.Unmarshalling(data)) {
244 FI_HILOGE("GetCooperateStateParam::Unmarshalling fail");
245 return RET_ERR;
246 }
247 bool state { false };
248 if (cooperate->GetCooperateState(param.udId, state) != RET_OK) {
249 FI_HILOGE("GetCooperateState failed");
250 return RET_ERR;
251 }
252 FI_HILOGI("GetCooperateState for udId:%{public}s successfully, state:%{public}s",
253 Utility::Anonymize(param.udId).c_str(), state ? "true" : "false");
254 if (!checkParcelValid()) {
255 FI_HILOGE("CheckParcelValid failed");
256 return RET_ERR;
257 }
258 if (!BooleanReply(state).Marshalling(reply)) {
259 FI_HILOGE("Marshalling state failed");
260 return RET_ERR;
261 }
262 return RET_OK;
263 }
264 default: {
265 FI_HILOGE("Unexpected request ID (%{public}u)", id);
266 return RET_ERR;
267 }
268 }
269 }
270
Control(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)271 int32_t CooperateServer::Control(CallingContext &context, uint32_t id, MessageParcel &data, MessageParcel &reply)
272 {
273 CALL_DEBUG_ENTER;
274 return RET_ERR;
275 }
276
CheckCooperatePermission(CallingContext &context)277 bool CooperateServer::CheckCooperatePermission(CallingContext &context)
278 {
279 CALL_DEBUG_ENTER;
280 Security::AccessToken::AccessTokenID callerToken = context.tokenId;
281 int32_t result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken,
282 COOPERATE_PERMISSION);
283 return result == Security::AccessToken::PERMISSION_GRANTED;
284 }
285
IsSystemServiceCalling(CallingContext &context)286 bool CooperateServer::IsSystemServiceCalling(CallingContext &context)
287 {
288 const auto flag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(context.tokenId);
289 if (flag == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE ||
290 flag == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
291 FI_HILOGD("system service calling, flag:%{public}u", flag);
292 return true;
293 }
294 return false;
295 }
296
IsSystemCalling(CallingContext &context)297 bool CooperateServer::IsSystemCalling(CallingContext &context)
298 {
299 if (IsSystemServiceCalling(context)) {
300 return true;
301 }
302 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(context.fullTokenId);
303 }
304
CheckPermission(CallingContext &context)305 int32_t CooperateServer::CheckPermission(CallingContext &context)
306 {
307 if (!IsSystemCalling(context)) {
308 FI_HILOGE("The caller is not system hap");
309 return COMMON_NOT_SYSTEM_APP;
310 }
311 if (!CheckCooperatePermission(context)) {
312 FI_HILOGE("The caller has no COOPERATE_MANAGER permission");
313 return COMMON_PERMISSION_CHECK_ERROR;
314 }
315 return RET_OK;
316 }
317 } // namespace DeviceStatus
318 } // namespace Msdp
319 } // namespace OHOS