diff --git a/services/sensor/include/sensor_suspend_policy.h b/services/sensor/include/sensor_suspend_policy.h new file mode 100755 index 0000000000000000000000000000000000000000..b8a147fa6439fbab115889b8995bd9fa591842ab --- /dev/null +++ b/services/sensor/include/sensor_suspend_policy.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef SENSOR_SUSPEND_POLICY_H +#define SENSOR_SUSPEND_POLICY_H + +#include +#include +#include +#include + +#include "app_sensor.h" +#include "client_info.h" +#include "i_sensor_status_callback.h" +#include "sensor_agent_type.h" +#include "sensor_hdi_connection.h" +#include "sensor_manager.h" +#include "sensors_errors.h" + +namespace OHOS { +namespace Sensors { +class SensorSuspendPolicy : public Singleton{ +public: + ErrCode DoSuspend(int32_t pid); + ErrCode DoResume(int32_t pid); + ErrCode GetAppSensorList(int32_t pid, std::vector &appSensorList); + ErrCode AddCallback(sptr callback); + void ExecuteCallbackAsync(int32_t pid, int32_t sensorId, bool isActive, + int64_t samplingPeriodNs, int64_t maxReportDelayNs); + bool InitDeathRecipient(); + void ProcessDeathObserver(wptr remote); + +private: + struct ClassComp { + bool operator()(const sptr &callback1, + const sptr &callback2) const + { + return callback1->AsObject() < callback2->AsObject(); + } + }; + bool CheckFreezingSensor(int32_t sensorId); + bool DisableSensorList(std::unordered_map &SensorInfoMap, + std::vector &sensorIdList, int32_t pid); + ErrCode DisableSensor(std::unordered_map &SensorInfoMap, + int32_t sensorId, int32_t pid); + ErrCode EnableSensor(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, int64_t maxReportDelayNs); + ErrCode RestoreSensorInfo(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, int64_t maxReportDelayNs); + SensorHdiConnection &sensorHdiConnection_ = SensorHdiConnection::GetInstance(); + ClientInfo &clientInfo_ = ClientInfo::GetInstance(); + SensorManager &sensorManager_ = SensorManager::GetInstance(); + std::mutex pidSensorInfoMutex_; + std::unordered_map> pidSensorInfoMap_; + std::mutex callbackMutex_; + std::set, ClassComp> callbackSet_; + sptr sensorStatusCBDeathRecipient_ { nullptr }; +}; +} // namespace Sensors +} // namespace OHOS +#endif // SENSOR_SUSPEND_POLICY_H diff --git a/services/sensor/src/sensor_suspend_policy.cpp b/services/sensor/src/sensor_suspend_policy.cpp index 82ac98324343a998174c455212e19b7ea2382bbf..351c9ac706386e7bff209ffd4ffbc118ca92a205 100644 --- a/services/sensor/src/sensor_suspend_policy.cpp +++ b/services/sensor/src/sensor_suspend_policy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 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 @@ -15,10 +15,8 @@ #include "sensor_suspend_policy.h" +#include "death_recipient_template.h" #include "sensor.h" -#include "sensor_agent_type.h" -#include "sensor_service.h" -#include "system_ability_definition.h" namespace OHOS { namespace Sensors { @@ -28,73 +26,143 @@ namespace { constexpr HiLogLabel LABEL = { LOG_CORE, SENSOR_LOG_DOMAIN, "SensorSuspendPolicy" }; constexpr int32_t INVALID_SENSOR_ID = -1; constexpr int64_t MAX_EVENT_COUNT = 1000; -constexpr int64_t DEFAULT_SAMPLING_RATE = 200000000; -constexpr int64_t DEFAULT_REPORT_DELAY = 0; } // namespace -SensorSuspendPolicy::~SensorSuspendPolicy() -{} +bool SensorSuspendPolicy::InitDeathRecipient() +{ + if (sensorStatusCBDeathRecipient_ == nullptr) { + sensorStatusCBDeathRecipient_ = new (std::nothrow) DeathRecipientTemplate(*const_cast(this)); + if (sensorStatusCBDeathRecipient_ == nullptr) { + SEN_HILOGE("Failed to get sensorStatusCBDeathRecipient_"); + return false; + } + } + return true; +} + +void SensorSuspendPolicy::ProcessDeathObserver(wptr remote) +{ + sptr client = remote.promote(); + CHKPV(client); + sptr callback = iface_cast(client); + std::lock_guard callbackLock(callbackMutex_); + size_t ret = callbackSet_.erase(callback); + if (ret != 0) { + client->RemoveDeathRecipient(sensorStatusCBDeathRecipient_); + } +} bool SensorSuspendPolicy::CheckFreezingSensor(int32_t sensorId) { return ((sensorId == SENSOR_TYPE_ID_PEDOMETER_DETECTION) || (sensorId == SENSOR_TYPE_ID_PEDOMETER)); } -ErrCode SensorSuspendPolicy::DisableSensor(int32_t sensorId, int32_t pid) +ErrCode SensorSuspendPolicy::DoSuspend(int32_t pid) { CALL_LOG_ENTER; - if (sensorId == INVALID_SENSOR_ID) { - SEN_HILOGE("sensorId is invalid"); - return ERR_NO_INIT; + std::vector sensorIdList = clientInfo_.GetSensorIdByPid(pid); + std::lock_guard pidSensorInfoLock(pidSensorInfoMutex_); + auto pidSensorInfoIt = pidSensorInfoMap_.find(pid); + if (pidSensorInfoIt != pidSensorInfoMap_.end()) { + if (sensorIdList.empty()) { + SEN_HILOGI("Pid already suspend, all sensors suspend success, not need suspend again, pid: %{public}d", pid); + return ERR_OK; + } else { + SEN_HILOGI("Pid already suspend, some sensors suspend failed, suspend these sensors again, pid: %{public}d", pid); + std::unordered_map SensorInfoMap = pidSensorInfoIt->second; + if (!DisableSensorList(SensorInfoMap, sensorIdList, pid)) { + SEN_HILOGE("Some sensor disable failed"); + return DISABLE_SENSOR_ERR; + } + return ERR_OK; + } } - if (sensorManager_.IsOtherClientUsingSensor(sensorId, pid)) { - SEN_HILOGW("other client is using this sensor now, cannot disable"); - return ERR_OK; + if (sensorIdList.empty()) { + SEN_HILOGE("Pid sensorId list is empty, pid: %{public}d", pid); + return ERROR; } - if (interface_.DisableSensor(sensorId) != ERR_OK) { - SEN_HILOGE("DisableSensor is failed"); + std::unordered_map SensorInfoMap; + bool suspendAllSensors = DisableSensorList(SensorInfoMap, sensorIdList, pid); + pidSensorInfoMap_.insert(std::make_pair(pid, SensorInfoMap)); + if (!suspendAllSensors) { + SEN_HILOGE("Some sensor disable failed"); return DISABLE_SENSOR_ERR; } - return sensorManager_.AfterDisableSensor(sensorId); + return ERR_OK; } -void SensorSuspendPolicy::DoSuspend(const std::shared_ptr &info) +bool SensorSuspendPolicy::DisableSensorList(std::unordered_map &SensorInfoMap, + std::vector &sensorIdList, int32_t pid) { CALL_LOG_ENTER; - std::lock_guard suspendLock(suspendMutex_); - auto &list = info->GetAppIPCInfoList(); - for (const auto &appInfo : list) { - std::vector sensorIdList = clientInfo_.GetSensorIdByPid(appInfo.pid); - if (sensorIdList.empty()) { + bool suspendAllSensors = true; + for (auto &sensorId : sensorIdList) { + if (CheckFreezingSensor(sensorId)) { continue; } - pidSensorIdMap_.emplace(std::make_pair(appInfo.pid, sensorIdList)); - for (auto &sensorId : sensorIdList) { - if (CheckFreezingSensor(sensorId)) { - continue; - } - auto sensorInfo = clientInfo_.GetCurPidSensorInfo(sensorId, appInfo.pid); - sensorIdInfoMap_.emplace(std::make_pair(sensorId, sensorInfo)); - DisableSensor(sensorId, appInfo.pid); + auto ret = DisableSensor(SensorInfoMap, sensorId, pid); + if (ret != ERR_OK) { + SEN_HILOGE("Disable Sensor is failed. sensorId: %{public}u, pid: %{public}d, ret: %{public}d", + sensorId, pid, ret); + suspendAllSensors = false; } } + return suspendAllSensors; } -ErrCode SensorSuspendPolicy::SaveSubscriber(int32_t sensorId, int64_t samplingPeriodNs, - int64_t maxReportDelayNs, int32_t pid) +ErrCode SensorSuspendPolicy::DisableSensor(std::unordered_map &SensorInfoMap, + int32_t sensorId, int32_t pid) { - auto ret = sensorManager_.SaveSubscriber(sensorId, pid, samplingPeriodNs, maxReportDelayNs); - if (ret != ERR_OK) { - SEN_HILOGE("SaveSubscriber is failed"); - return ret; + CALL_LOG_ENTER; + if (sensorId == INVALID_SENSOR_ID) { + SEN_HILOGE("SensorId is invalid"); + return ERR_NO_INIT; } - sensorManager_.StartDataReportThread(); - if (!sensorManager_.SetBestSensorParams(sensorId, samplingPeriodNs, maxReportDelayNs)) { - SEN_HILOGE("SetBestSensorParams is failed"); - clientInfo_.RemoveSubscriber(sensorId, pid); + auto sensorInfo = clientInfo_.GetCurPidSensorInfo(sensorId, pid); + if (sensorManager_.IsOtherClientUsingSensor(sensorId, pid)) { + SEN_HILOGW("Other client is using this sensor now, cannot disable"); + SensorInfoMap.insert(std::make_pair(sensorId, sensorInfo)); + return ERR_OK; + } + if (sensorHdiConnection_.DisableSensor(sensorId) != ERR_OK) { + SEN_HILOGE("DisableSensor is failed"); + return DISABLE_SENSOR_ERR; + } + SensorInfoMap.insert(std::make_pair(sensorId, sensorInfo)); + return sensorManager_.AfterDisableSensor(sensorId); +} + +ErrCode SensorSuspendPolicy::DoResume(int32_t pid) +{ + CALL_LOG_ENTER; + std::lock_guard pidSensorInfoLock(pidSensorInfoMutex_); + auto pidSensorInfoIt = pidSensorInfoMap_.find(pid); + if (pidSensorInfoIt == pidSensorInfoMap_.end()) { + SEN_HILOGE("Pid not have suspend sensors, pid: %{public}d", pid); + return ERROR; + } + bool resumeAllSensors = true; + std::unordered_map SensorInfoMap = pidSensorInfoIt->second; + for (auto sensorIt = SensorInfoMap.begin(); sensorIt != SensorInfoMap.end();) { + int32_t sensorId = sensorIt->first; + int64_t samplingPeriodNs = sensorIt->second.GetSamplingPeriodNs(); + int64_t maxReportDelayNs = sensorIt->second.GetMaxReportDelayNs(); + auto ret = EnableSensor(sensorId, pid, samplingPeriodNs, maxReportDelayNs); + if (ret != ERR_OK) { + SEN_HILOGE("Enable Sensor is failed. sensorId: %{public}u, pid: %{public}d, ret: %{public}d", + sensorId, pid, ret); + resumeAllSensors = false; + ++sensorIt; + } else { + sensorIt = SensorInfoMap.erase(sensorIt); + } + } + if (!resumeAllSensors) { + SEN_HILOGE("Some sensor enable failed"); return ENABLE_SENSOR_ERR; } - return ret; + pidSensorInfoMap_.erase(pidSensorInfoIt); + return ERR_OK; } ErrCode SensorSuspendPolicy::EnableSensor(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, @@ -103,76 +171,115 @@ ErrCode SensorSuspendPolicy::EnableSensor(int32_t sensorId, int32_t pid, int64_t CALL_LOG_ENTER; if ((sensorId == INVALID_SENSOR_ID) || (samplingPeriodNs == 0) || ((samplingPeriodNs != 0L) && (maxReportDelayNs / samplingPeriodNs > MAX_EVENT_COUNT))) { - SEN_HILOGE("sensorId is 0 or maxReportDelayNs exceed the maximum value"); + SEN_HILOGE("SensorId is 0 or maxReportDelayNs exceed the maximum value"); return ERR_NO_INIT; } - if (clientInfo_.GetSensorState(sensorId) == SENSOR_ENABLED) { - SEN_HILOGW("sensor has been enabled already"); - auto ret = SaveSubscriber(sensorId, samplingPeriodNs, maxReportDelayNs, pid); + if (clientInfo_.GetSensorState(sensorId)) { + SEN_HILOGW("Sensor has been enabled already, sensorId: %{public}d", sensorId); + auto ret = RestoreSensorInfo(sensorId, pid, samplingPeriodNs, maxReportDelayNs); if (ret != ERR_OK) { - SEN_HILOGE("SaveSubscriber is failed"); + SEN_HILOGE("RestoreSensorInfo is failed, ret: %{public}d", ret); return ret; } - uint32_t flag = sensorManager_.GetSensorFlag(sensorId); - ret = flushInfo_.FlushProcess(sensorId, flag, pid, true); if (ret != ERR_OK) { - SEN_HILOGW("ret:%{public}d", ret); + SEN_HILOGE("FlushProcess is failed, ret: %{public}d", ret); } return ERR_OK; } - auto ret = SaveSubscriber(sensorId, samplingPeriodNs, maxReportDelayNs, pid); + auto ret = RestoreSensorInfo(sensorId, pid, samplingPeriodNs, maxReportDelayNs); if (ret != ERR_OK) { - SEN_HILOGE("SaveSubscriber is failed"); + SEN_HILOGE("RestoreSensorInfo is failed, ret: %{public}d", ret); return ret; } - ret = interface_.EnableSensor(sensorId); + ret = sensorHdiConnection_.EnableSensor(sensorId); if (ret != ERR_OK) { - SEN_HILOGE("EnableSensor is failed"); + SEN_HILOGE("EnableSensor is failed, ret: %{public}d", ret); + clientInfo_.RemoveSubscriber(sensorId, pid); + return ENABLE_SENSOR_ERR; + } + return ERR_OK; +} + +ErrCode SensorSuspendPolicy::RestoreSensorInfo(int32_t sensorId, int32_t pid, int64_t samplingPeriodNs, + int64_t maxReportDelayNs) +{ + auto ret = sensorManager_.SaveSubscriber(sensorId, pid, samplingPeriodNs, maxReportDelayNs); + if (ret != ERR_OK) { + SEN_HILOGE("RestoreSensorInfo is failed, ret: %{public}d", ret); + return ret; + } + sensorManager_.StartDataReportThread(); + if (!sensorManager_.SetBestSensorParams(sensorId, samplingPeriodNs, maxReportDelayNs)) { + SEN_HILOGE("SetBestSensorParams is failed"); clientInfo_.RemoveSubscriber(sensorId, pid); return ENABLE_SENSOR_ERR; } return ret; } -std::vector SensorSuspendPolicy::GetSensorIdByPid(int32_t pid) +ErrCode SensorSuspendPolicy::GetAppSensorList(int32_t pid, std::vector &appSensorList) { - SEN_HILOGD("pid:%{public}d", pid); - auto it = pidSensorIdMap_.find(pid); - if (it != pidSensorIdMap_.end()) { - SEN_HILOGD("pid:%{public}d found", pid); - return it->second; - } - SEN_HILOGD("pid:%{public}d not found", pid); - return {}; + CALL_LOG_ENTER; + std::vector sensorIdList = clientInfo_.GetSensorIdByPid(pid); + for (auto &sensorId : sensorIdList) { + auto sensorInfo = clientInfo_.GetCurPidSensorInfo(sensorId, pid); + int64_t samplingPeriodNs = sensorInfo.GetSamplingPeriodNs(); + int64_t maxReportDelayNs = sensorInfo.GetMaxReportDelayNs(); + AppSensor appSensor(pid, sensorId, true, samplingPeriodNs, maxReportDelayNs); + appSensorList.push_back(appSensor); + } + std::lock_guard pidSensorInfoLock(pidSensorInfoMutex_); + auto pidSensorInfoIt = pidSensorInfoMap_.find(pid); + if (pidSensorInfoIt != pidSensorInfoMap_.end()) { + std::unordered_map SensorInfoMap = pidSensorInfoIt->second; + for (auto &sensorInfo : SensorInfoMap) { + int32_t sensorId = sensorInfo.first; + int64_t samplingPeriodNs = sensorInfo.second.GetSamplingPeriodNs(); + int64_t maxReportDelayNs = sensorInfo.second.GetMaxReportDelayNs(); + AppSensor appSensor(pid, sensorId, false, samplingPeriodNs, maxReportDelayNs); + appSensorList.push_back(appSensor); + } + } + return ERR_OK; } -void SensorSuspendPolicy::DoActive(const std::shared_ptr &info) +ErrCode SensorSuspendPolicy::AddCallback(sptr callback) { CALL_LOG_ENTER; - int64_t samplePeriod = DEFAULT_SAMPLING_RATE; - int64_t maxReportDelay = DEFAULT_REPORT_DELAY; - std::vector sensorIdList; - std::lock_guard suspendLock(suspendMutex_); - auto &list = info->GetAppIPCInfoList(); - for (const auto &appInfo : list) { - sensorIdList = GetSensorIdByPid(appInfo.pid); - for (auto &sensorId : sensorIdList) { - if (CheckFreezingSensor(sensorId)) { - continue; - } - auto it = sensorIdInfoMap_.find(sensorId); - if (it != sensorIdInfoMap_.end()) { - samplePeriod = it->second.GetSamplingPeriodNs(); - maxReportDelay = it->second.GetMaxReportDelayNs(); - } - auto ret = EnableSensor(sensorId, appInfo.pid, samplePeriod, maxReportDelay); - if (ret != ERR_OK) { - SEN_HILOGE("sensorId:%{public}u,pid:%{public}d,ret:%{public}d", sensorId, appInfo.pid, ret); - } + if (callback == nullptr) { + SEN_HILOGE("Callback is nullptr"); + return ERROR; + } + auto object = callback->AsObject(); + if (object == nullptr) { + SEN_HILOGE("Callback->AsObject() is nullptr"); + return ERROR; + } + std::lock_guard callbackLock(callbackMutex_); + auto retPair = callbackSet_.insert(callback); + if (retPair.second) { + object->AddDeathRecipient(sensorStatusCBDeathRecipient_); + } + return ERR_OK; +} + +void SensorSuspendPolicy::ExecuteCallbackAsync(int32_t pid, int32_t sensorId, bool isActive, + int64_t samplingPeriodNs, int64_t maxReportDelayNs) +{ + CALL_LOG_ENTER; + AppSensorInfo appSensorInfo; + appSensorInfo.pid = pid; + appSensorInfo.sensorId = sensorId; + appSensorInfo.isActive = isActive; + appSensorInfo.samplingPeriodNs = samplingPeriodNs; + appSensorInfo.maxReportDelayNs = maxReportDelayNs; + std::lock_guard callbackLock(callbackMutex_); + for (auto callbackIt = callbackSet_.begin(); callbackIt != callbackSet_.end(); ++callbackIt) { + auto callback = *callbackIt; + if (callback != nullptr) { + callback->OnSensorChanged(appSensorInfo); } } - pidSensorIdMap_.clear(); - sensorIdInfoMap_.clear(); } } // namespace Sensors } // namespace OHOS