* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "device_manager_service_notify.h"
#include "dm_anonymous.h"
#include "dm_error_type.h"
#include "dm_log.h"
#include "permission_manager.h"
namespace OHOS {
namespace DistributedHardware {
DM_IMPLEMENT_SINGLE_INSTANCE(DeviceManagerServiceNotify);
namespace {
constexpr uint32_t MAX_CALLBACK_LEN = 1000;
const static std::map<DmCommonNotifyEvent, DmCommonNotifyEvent> unRegNotifyEventMap_ = {
{DmCommonNotifyEvent::UN_REG_DEVICE_STATE, DmCommonNotifyEvent::REG_DEVICE_STATE},
{DmCommonNotifyEvent::UN_REG_DEVICE_SCREEN_STATE, DmCommonNotifyEvent::REG_DEVICE_SCREEN_STATE},
{DmCommonNotifyEvent::UN_REG_REMOTE_DEVICE_TRUST_CHANGE, DmCommonNotifyEvent::REG_REMOTE_DEVICE_TRUST_CHANGE},
{DmCommonNotifyEvent::UN_REG_CREDENTIAL_AUTH_STATUS_NOTIFY, DmCommonNotifyEvent::REG_CREDENTIAL_AUTH_STATUS_NOTIFY},
{DmCommonNotifyEvent::UN_REG_AUTH_CODE_INVALID, DmCommonNotifyEvent::REG_AUTH_CODE_INVALID},
{DmCommonNotifyEvent::UN_REG_SERVICE_STATE, DmCommonNotifyEvent::REG_SERVICE_STATE},
};
const static std::set<DmCommonNotifyEvent> regNotifyEventSet_ = {
DmCommonNotifyEvent::REG_DEVICE_STATE,
DmCommonNotifyEvent::REG_DEVICE_SCREEN_STATE,
DmCommonNotifyEvent::REG_REMOTE_DEVICE_TRUST_CHANGE,
DmCommonNotifyEvent::REG_CREDENTIAL_AUTH_STATUS_NOTIFY,
DmCommonNotifyEvent::REG_AUTH_CODE_INVALID,
DmCommonNotifyEvent::REG_SERVICE_STATE,
};
}
int32_t DeviceManagerServiceNotify::RegisterCallBack(int32_t dmCommonNotifyEvent, const ProcessInfo &processInfo)
{
LOGI("start event %{public}d pkgName: %{public}s.", dmCommonNotifyEvent, processInfo.pkgName.c_str());
if (!PermissionManager::GetInstance().CheckDataSyncPermission() &&
!PermissionManager::GetInstance().CheckAccessServicePermission()) {
LOGE("The caller does not have permission.");
return ERR_DM_NO_PERMISSION;
}
if (processInfo.pkgName.empty()) {
LOGE("Invalid parameter, pkgName is empty.");
return ERR_DM_INPUT_PARA_INVALID;
}
DmCommonNotifyEvent notifyEvent = static_cast<DmCommonNotifyEvent>(dmCommonNotifyEvent);
std::lock_guard<std::mutex> autoLock(callbackLock_);
if (unRegNotifyEventMap_.find(notifyEvent) != unRegNotifyEventMap_.end()) {
if (callbackMap_.find(unRegNotifyEventMap_.at(notifyEvent)) == callbackMap_.end()) {
LOGI("notifyEvent is not exist %{public}d.", unRegNotifyEventMap_.at(notifyEvent));
return DM_OK;
}
callbackMap_.at(unRegNotifyEventMap_.at(notifyEvent)).erase(processInfo);
return DM_OK;
}
if (regNotifyEventSet_.find(notifyEvent) == regNotifyEventSet_.end()) {
LOGE("notifyEvent is not support %{public}d.", notifyEvent);
return ERR_DM_INPUT_PARA_INVALID;
}
if (callbackMap_.find(notifyEvent) == callbackMap_.end()) {
std::set<ProcessInfo> processInfoSet;
processInfoSet.insert(processInfo);
callbackMap_[notifyEvent] = processInfoSet;
return DM_OK;
}
if (callbackMap_[notifyEvent].size() >= MAX_CALLBACK_LEN) {
LOGE("too many callbacks dmCommonNotifyEvent: %{public}d, pkgName: %{public}s", dmCommonNotifyEvent,
processInfo.pkgName.c_str());
return ERR_DM_FAILED;
}
callbackMap_.at(notifyEvent).insert(processInfo);
return DM_OK;
}
void DeviceManagerServiceNotify::GetCallBack(int32_t dmCommonNotifyEvent, std::set<ProcessInfo> &processInfos)
{
LOGI("start event %{public}d.", dmCommonNotifyEvent);
DmCommonNotifyEvent notifyEvent = static_cast<DmCommonNotifyEvent>(dmCommonNotifyEvent);
std::lock_guard<std::mutex> autoLock(callbackLock_);
if (regNotifyEventSet_.find(notifyEvent) == regNotifyEventSet_.end()) {
LOGE("notifyEvent is not support %{public}d.", notifyEvent);
return;
}
if (callbackMap_.find(notifyEvent) == callbackMap_.end()) {
LOGE("callback is empty %{public}d.", notifyEvent);
return;
}
processInfos = callbackMap_.at(notifyEvent);
}
void DeviceManagerServiceNotify::ClearDiedProcessCallback(const ProcessInfo &processInfo)
{
LOGI("start pkgName %{public}s.", processInfo.pkgName.c_str());
std::lock_guard<std::mutex> autoLock(callbackLock_);
for (auto iter = callbackMap_.begin(); iter != callbackMap_.end();) {
iter->second.erase(processInfo);
if (iter->second.empty()) {
iter = callbackMap_.erase(iter);
} else {
++iter;
}
}
}
}
}