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