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