* Copyright (c) 2025 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 "sensor_data_manager.h"
#include <charconv>
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
#include "hisysevent.h"
#endif
#include "ipc_skeleton.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
#include "sensor_errors.h"
#include "sensor_utils.h"
#undef LOG_TAG
#define LOG_TAG "SensorDataManager"
namespace OHOS {
namespace Sensors {
using namespace OHOS::HiviewDFX;
namespace {
const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
const std::string SETTING_COLUMN_VALUE = "VALUE";
const std::string SETTING_APP_LOGICAL_DEVICE_CONFIGURATION_KEY = "APP_LOGICAL_DEVICE_CONFIGURATION";
const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
constexpr int32_t DATA_SHARE_READY = 0;
}
SensorDataManager::SensorDataManager()
{}
SensorDataManager::~SensorDataManager()
{
remoteObj_ = nullptr;
std::lock_guard<std::mutex> observerMutex(observerMutex_);
if (UnregisterObserver(observer_) != ERR_OK) {
SEN_HILOGE("UnregisterObserver failed");
}
}
bool SensorDataManager::Init(int32_t deviceMode)
{
auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sm == nullptr) {
SEN_HILOGE("sm cannot be nullptr");
return false;
}
remoteObj_ = sm->GetSystemAbility(SENSOR_SERVICE_ABILITY_ID);
if (remoteObj_ == nullptr) {
SEN_HILOGE("GetSystemAbility return nullptr");
return false;
}
deviceMode_.store(deviceMode);
SensorObserver::UpdateFunc updateFunc = [this]() {
std::string compatibleAppStrategy;
int32_t currentDeviceMode = deviceMode_.load();
if (currentDeviceMode == SINGLE_DISPLAY_THREE_FOLD || currentDeviceMode == SINGLE_DISPLAY_HP_FOLD ||
currentDeviceMode == SINGLE_DISPLAY_LAP_FOLD) {
if (GetStringValue(SETTING_APP_LOGICAL_DEVICE_CONFIGURATION_KEY, compatibleAppStrategy) != ERR_OK) {
SEN_HILOGE("Get app logical device configuration failed");
}
ParseAppLogicalDeviceList(compatibleAppStrategy);
}
SEN_HILOGI("compatibleAppStrategy:%{public}s", compatibleAppStrategy.c_str());
};
std::lock_guard<std::mutex> observerMutex(observerMutex_);
observer_ = CreateObserver(updateFunc);
if (observer_ == nullptr) {
SEN_HILOGE("observer is null");
return false;
}
if (RegisterObserver(observer_) != ERR_OK) {
SEN_HILOGE("RegisterObserver failed");
return false;
}
return true;
}
int32_t SensorDataManager::GetStringValue(const std::string &key, std::string &value)
{
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
auto helper = CreateDataShareHelper(SETTING_URI_PROXY);
if (helper == nullptr) {
SEN_HILOGE("helper is nullptr");
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERROR;
}
std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
DataShare::DataSharePredicates predicates;
predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
Uri uri(AssembleUri(key));
auto resultSet = helper->Query(uri, predicates, columns);
ReleaseDataShareHelper(helper);
if (resultSet == nullptr) {
SEN_HILOGE("resultSet is nullptr");
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERROR;
}
int32_t count;
resultSet->GetRowCount(count);
if (count == 0) {
SEN_HILOGW("Not found value, key:%{public}s, count:%{public}d", key.c_str(), count);
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERROR;
}
const int32_t index = 0;
resultSet->GoToRow(index);
int32_t ret = resultSet->GetString(index, value);
if (ret != ERR_OK) {
SEN_HILOGW("GetString failed, ret:%{public}d", ret);
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERROR;
}
resultSet->Close();
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERR_OK;
}
sptr<SensorObserver> SensorDataManager::CreateObserver(const SensorObserver::UpdateFunc &func)
{
sptr<SensorObserver> observer = new SensorObserver();
if (observer == nullptr) {
SEN_HILOGE("observer is null");
return observer;
}
observer->SetUpdateFunc(func);
return observer;
}
Uri SensorDataManager::AssembleUri(const std::string &key)
{
Uri uri(SETTING_URI_PROXY + "&key=" + key);
return uri;
}
std::shared_ptr<DataShare::DataShareHelper> SensorDataManager::CreateDataShareHelper(const std::string &tableUrl)
{
if (remoteObj_ == nullptr) {
SEN_HILOGE("remoteObj_ is nullptr");
return nullptr;
}
auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj_, tableUrl, SETTINGS_DATA_EXT_URI);
if (ret != DATA_SHARE_READY) {
SEN_HILOGE("Create data_share helper failed, uri proxy:%{public}s", tableUrl.c_str());
return nullptr;
}
SEN_HILOGI("Data_share create success");
return helper;
}
bool SensorDataManager::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> &helper)
{
if (helper == nullptr) {
SEN_HILOGE("helper is nullptr");
return false;
}
if (!helper->Release()) {
SEN_HILOGW("Release helper fail");
return false;
}
return true;
}
void SensorDataManager::ExecRegisterCb(const sptr<SensorObserver> &observer)
{
if (observer == nullptr) {
SEN_HILOGE("observer is nullptr");
return;
}
observer->OnChange();
}
int32_t SensorDataManager::RegisterObserver(const sptr<SensorObserver> &observer)
{
if (observer == nullptr) {
SEN_HILOGE("observer is nullptr");
return ERR_NO_INIT;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
auto helper = CreateDataShareHelper(SETTING_URI_PROXY);
if (helper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "RegisterObserver", "ERROR_CODE", ERR_NO_INIT);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERR_NO_INIT;
}
int32_t currentDeviceMode = deviceMode_.load();
if (currentDeviceMode == SINGLE_DISPLAY_THREE_FOLD || currentDeviceMode == SINGLE_DISPLAY_HP_FOLD ||
currentDeviceMode == SINGLE_DISPLAY_LAP_FOLD) {
auto uriAppLogicalStrategy = AssembleUri(SETTING_APP_LOGICAL_DEVICE_CONFIGURATION_KEY);
helper->RegisterObserver(uriAppLogicalStrategy, observer);
helper->NotifyChange(uriAppLogicalStrategy);
}
std::thread execCb(SensorDataManager::ExecRegisterCb, observer);
execCb.detach();
ReleaseDataShareHelper(helper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
SEN_HILOGI("Succeed to register observer of uri");
return ERR_OK;
}
int32_t SensorDataManager::UnregisterObserver(const sptr<SensorObserver> &observer)
{
if (observer == nullptr) {
SEN_HILOGE("observer is nullptr");
return ERR_NO_INIT;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
auto helper = CreateDataShareHelper(SETTING_URI_PROXY);
if (helper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::SENSOR, "SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "UnregisterObserver", "ERROR_CODE", ERR_NO_INIT);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERR_NO_INIT;
}
int32_t currentDeviceMode = deviceMode_.load();
if (currentDeviceMode == SINGLE_DISPLAY_THREE_FOLD || currentDeviceMode == SINGLE_DISPLAY_HP_FOLD ||
currentDeviceMode == SINGLE_DISPLAY_LAP_FOLD) {
auto uriAppLogicalStrategy = AssembleUri(SETTING_APP_LOGICAL_DEVICE_CONFIGURATION_KEY);
helper->UnregisterObserver(uriAppLogicalStrategy, observer);
}
ReleaseDataShareHelper(helper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
SEN_HILOGI("Succeed to unregister observer");
return ERR_OK;
}
void SensorDataManager::ParseAppLogicalDeviceList(const std::string &compatibleAppStrategy)
{
std::lock_guard<std::mutex> compatibleAppStrategyLock(compatibleAppStrategyMutex_);
if (!compatibleAppStrategyList_.empty()) {
compatibleAppStrategyList_.clear();
}
nlohmann::json compatibleAppStrategyJson = nlohmann::json::parse(compatibleAppStrategy, nullptr, false);
if (compatibleAppStrategyJson.is_discarded()) {
SEN_HILOGE("Parse json failed");
return;
}
for (auto it = compatibleAppStrategyJson.begin(); it != compatibleAppStrategyJson.end(); ++it) {
const std::string& key = it.key();
SEN_HILOGD("key:%{public}s", key.c_str());
const nlohmann::json& value = it.value();
std::string name = "";
GetJsonValue(value, "name", name);
if (name.empty()) {
continue;
}
if (!value.contains("useLogicCamera")) {
continue;
}
int32_t isOpenPolicy = ParseJsonValue(value, "useLogicCamera");
int32_t policy = ParseJsonValue(value, "customLogicDirection");
CompatibleAppData data;
if (isOpenPolicy != 0) {
data.name = name;
data.policy = policy;
SEN_HILOGI("name:%{public}s, policy:%{public}d", name.c_str(), policy);
compatibleAppStrategyList_.emplace_back(data);
}
}
}
int32_t SensorDataManager::ParseJsonValue(const nlohmann::json &value, const std::string &strKey)
{
int32_t tempValue = 0;
if (value.contains(strKey)) {
nlohmann::json policyJson = value.at(strKey);
if (!policyJson.is_object()) {
SEN_HILOGE("Field %{public}s is not a JSON object", strKey.c_str());
return tempValue;
}
for (auto& [key, valueTmp] : policyJson.items()) {
int32_t keyInt = -1;
auto res = std::from_chars(key.data(), key.data() + key.size(), keyInt);
if (res.ec != std::errc()) {
SEN_HILOGE("Failed to convert string %{public}s to number", key.c_str());
continue;
}
auto mode = static_cast<Sensors::FoldDisplayMode>(keyInt);
if (mode == Sensors::FoldDisplayMode::FULL || mode == Sensors::FoldDisplayMode::GLOBAL_FULL) {
if (valueTmp.is_number()) {
tempValue = valueTmp.get<int32_t>();
}
}
SEN_HILOGI("parse json key:%{public}s, value:%{public}d", strKey.c_str(), tempValue);
}
}
return tempValue;
}
std::vector<CompatibleAppData> SensorDataManager::GetCompatibleAppStrategyList()
{
std::lock_guard<std::mutex> compatibleAppStrategyLock(compatibleAppStrategyMutex_);
return compatibleAppStrategyList_;
}
}
}