* Copyright (c) 2022 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 "vibration_priority_manager.h"
#include <tokenid_kit.h>
#include <regex>
#include "accesstoken_kit.h"
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
#include "hisysevent.h"
#endif
#include "ipc_skeleton.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
#include "os_account_manager.h"
#endif
#include "sensors_errors.h"
#undef LOG_TAG
#define LOG_TAG "VibrationPriorityManager"
namespace OHOS {
namespace Sensors {
using namespace OHOS::HiviewDFX;
const int32_t INVALID_USERID = 100;
const int32_t WHITE_LIST_MAX_COUNT = 100;
static std::atomic_int32_t g_currentUserId = INVALID_USERID;
static std::mutex g_settingMutex;
namespace {
const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
const std::string SETTING_COLUMN_VALUE = "VALUE";
const std::string SETTING_FEEDBACK_KEY = "physic_navi_haptic_feedback_enabled";
const std::string SETTING_RINGER_MODE_KEY = "ringer_mode";
const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
const std::string SCENEBOARD_BUNDLENAME = "com.ohos.sceneboard";
constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
const std::string USER_SETTING_SECURE_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/"
"USER_SETTINGSDATA_SECURE_##USERID##?Proxy=true";
const std::string DO_NOT_DISTURB_SWITCH = "focus_mode_enable";
const std::string DO_NOT_DISTURB_WHITE_LIST = "intelligent_scene_notification_white_list";
const std::string WHITE_LIST_KEY_BUNDLE = "bundle";
const std::string WHITE_LIST_KEY_UID = "uid";
constexpr const char *USERID_REPLACE = "##USERID##";
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
const std::string VIBRATE_WHEN_RINGING_KEY = "hw_vibrate_when_ringing";
#endif
const std::string SETTING_USER_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
const std::string USER_SETTINGS_ENABLE_IME = "settings.inputmethod.enable_ime";
const std::string INPUT_METHODS_KEY = "inputmethods";
const std::string INPUT_METHOD_KEY_BUNDLE_NAME = "bundleName";
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
const std::string SETTING_CROWN_FEEDBACK_KEY = "watch_crown_feedback_enabled";
const std::string SETTING_VIBRATE_INTENSITY_KEY = "vibration_intensity_index";
#endif
constexpr int32_t DECEM_BASE = 10;
}
std::atomic_bool VibrationPriorityManager::isVibratorMute_ = false;
VibrationPriorityManager::VibrationPriorityManager() {}
VibrationPriorityManager::~VibrationPriorityManager()
{
remoteObj_ = nullptr;
if (UnregisterObserver(observer_) != ERR_OK) {
MISC_HILOGE("UnregisterObserver failed");
}
if (UnregisterUserObserver() != ERR_OK) {
MISC_HILOGE("UnregisterUserObserver failed");
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
if (UnregisterUser100Observer() != ERR_OK) {
MISC_HILOGE("UnregisterUser100Observer failed");
}
#endif
if (UnregisterUserImfObserver() != ERR_OK) {
MISC_HILOGE("UnregisterUserImfObserver failed");
}
}
bool VibrationPriorityManager::Init()
{
auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sm == nullptr) {
MISC_HILOGE("sm cannot be nullptr");
return false;
}
remoteObj_ = sm->GetSystemAbility(MISCDEVICE_SERVICE_ABILITY_ID);
if (remoteObj_ == nullptr) {
MISC_HILOGE("GetSystemAbility return nullptr");
return false;
}
MiscDeviceObserver::UpdateFunc updateFunc = [&]() {
int32_t feedback = miscFeedback_;
std::string tableType = "normal";
if (GetIntValue(SETTING_URI_PROXY, SETTING_FEEDBACK_KEY, feedback, tableType) != ERR_OK) {
MISC_HILOGE("Get feedback failed");
}
miscFeedback_ = feedback;
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE",
HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE", "feedback", "STATUS", feedback);
#endif
MISC_HILOGI("feedback:%{public}d", feedback);
int32_t ringerMode = miscAudioRingerMode_;
if (GetIntValue(SETTING_URI_PROXY, SETTING_RINGER_MODE_KEY, ringerMode, tableType) != ERR_OK) {
MISC_HILOGE("Get ringerMode failed");
}
miscAudioRingerMode_ = ringerMode;
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE",
HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE", "ringerMode", "STATUS", ringerMode);
#endif
MISC_HILOGI("ringerMode:%{public}d", ringerMode);
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
MiscCrownIntensityFeedbackInit();
#endif
};
auto observer_ = CreateObserver(updateFunc);
if (observer_ == nullptr) {
MISC_HILOGE("observer is null");
return false;
}
if (RegisterObserver(observer_) != ERR_OK) {
MISC_HILOGE("RegisterObserver failed");
return false;
}
ReregisterCurrentUserObserver();
return true;
}
void VibrationPriorityManager::InitDoNotDisturbData()
{
int32_t switchTemp = doNotDisturbSwitch_;
if (GetDoNotDisturbIntValue(DO_NOT_DISTURB_SWITCH, switchTemp) != ERR_OK) {
doNotDisturbSwitch_ = DONOTDISTURB_SWITCH_OFF;
MISC_HILOGE("Get doNotDisturbSwitch failed");
} else {
PrintDoNotDisturbSwitchStatus(doNotDisturbSwitch_.load(), switchTemp);
doNotDisturbSwitch_ = switchTemp;
MISC_HILOGI("doNotDisturbSwitch:%{public}d", switchTemp);
}
std::lock_guard<std::mutex> whiteListLock(whiteListMutex_);
if (doNotDisturbSwitch_ == DONOTDISTURB_SWITCH_ON) {
std::vector<WhiteListAppInfo> whiteListTemp;
int32_t whiteListRet = GetWhiteListValue(DO_NOT_DISTURB_WHITE_LIST, whiteListTemp);
if (whiteListRet != ERR_OK) {
doNotDisturbSwitch_ = DONOTDISTURB_SWITCH_OFF;
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "GetWhiteListValue", "ERROR_CODE", whiteListRet);
#endif
MISC_HILOGE("Get doNotDisturbWhiteList failed");
} else {
int32_t whiteListSize = static_cast<int32_t>(whiteListTemp.size());
if (whiteListSize == 0) {
doNotDisturbWhiteList_.clear();
} else if (whiteListSize > WHITE_LIST_MAX_COUNT) {
doNotDisturbWhiteList_.clear();
doNotDisturbWhiteList_.assign(whiteListTemp.begin(), whiteListTemp.begin() + WHITE_LIST_MAX_COUNT);
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION",
HiSysEvent::EventType::FAULT, "PKG_NAME", "whiteListActualCount", "ERROR_CODE", whiteListSize);
#endif
MISC_HILOGW("whiteListTemp size:%{public}d", whiteListSize);
} else {
doNotDisturbWhiteList_ = whiteListTemp;
}
MISC_HILOGI("doNotDisturbWhiteList size:%{public}d", static_cast<int32_t>(doNotDisturbWhiteList_.size()));
}
} else if (doNotDisturbSwitch_ == DONOTDISTURB_SWITCH_OFF) {
doNotDisturbWhiteList_.clear();
MISC_HILOGD("clear doNotDisturbWhiteList_, DoNotDisturbSwitch:%{public}d",
static_cast<int32_t>(doNotDisturbSwitch_));
} else {
MISC_HILOGW("DoNotDisturbSwitch invalid, DoNotDisturbSwitch:%{public}d",
static_cast<int32_t>(doNotDisturbSwitch_));
}
}
void VibrationPriorityManager::ReregisterCurrentUserObserver()
{
MISC_HILOGI("ReregisterCurrentUserObserver start");
#ifdef OHOS_BUILD_ENABLE_DO_NOT_DISTURB
UnregisterUserObserver();
#endif
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
UnregisterUser100Observer();
UnregisterUserImfObserver();
UpdateCurrentUserId();
RegisterUserImfObserver();
RegisterUser100Observer();
#endif
#ifdef OHOS_BUILD_ENABLE_DO_NOT_DISTURB
RegisterUserObserver();
#endif
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
void VibrationPriorityManager::UpdateCurrentUserId()
{
std::lock_guard<std::mutex> lock(g_settingMutex);
std::vector<int32_t> activeUserIds;
int retId = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeUserIds);
if (retId != 0) {
MISC_HILOGE("QueryActiveOsAccountIds failed %{public}d", retId);
return;
}
if (activeUserIds.empty()) {
MISC_HILOGE("activeUserIds empty");
return;
}
g_currentUserId.store(activeUserIds[0]);
MISC_HILOGI("g_currentUserId is %{public}d", g_currentUserId.load());
}
#endif
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
void VibrationPriorityManager::InitVibrateWhenRing()
{
int32_t vibrateWhenRing = VIBRATE_WHEN_RING_MODE_INVALID;
std::string tableType = "system";
if (GetIntValue(SETTING_USER_URI_PROXY, VIBRATE_WHEN_RINGING_KEY, vibrateWhenRing, tableType) != ERR_OK) {
MISC_HILOGE("Get vibrateWhenRing failed");
vibrateWhenRing_.store(VIBRATE_WHEN_RING_MODE_ON);
return;
}
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE",
HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE", "vibrateWhenRing", "STATUS", vibrateWhenRing);
MISC_HILOGI("vibrateWhenRing:%{public}d", vibrateWhenRing);
vibrateWhenRing_.store(vibrateWhenRing);
}
#endif
int32_t VibrationPriorityManager::RegisterUserObserver()
{
MISC_HILOGI("RegisterUserObserver start");
std::lock_guard<std::mutex> currentUserObserverLock(currentUserObserverMutex_);
MiscDeviceObserver::UpdateFunc updateFunc = [&]() { InitDoNotDisturbData(); };
currentUserObserver_ = CreateObserver(updateFunc);
if (currentUserObserver_ == nullptr) {
MISC_HILOGE("currentUserObserver_ is null");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "normal";
auto doNotDisturbHelper =
CreateDataShareHelper(ReplaceUserIdForUri(USER_SETTING_SECURE_URI_PROXY, g_currentUserId.load()), tableType);
if (doNotDisturbHelper == nullptr) {
IPCSkeleton::SetCallingIdentity(callingIdentity);
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "RegisterUserObserver", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
MISC_HILOGE("doNotDisturbHelper is nullptr");
return MISC_NO_INIT_ERR;
}
auto doNotDisturbSwitch = DoNotDisturbAssembleUri(DO_NOT_DISTURB_SWITCH);
doNotDisturbHelper->RegisterObserver(doNotDisturbSwitch, currentUserObserver_);
doNotDisturbHelper->NotifyChange(doNotDisturbSwitch);
auto doNotDisturbWhiteList = DoNotDisturbAssembleUri(DO_NOT_DISTURB_WHITE_LIST);
doNotDisturbHelper->RegisterObserver(doNotDisturbWhiteList, currentUserObserver_);
doNotDisturbHelper->NotifyChange(doNotDisturbWhiteList);
std::thread execCb(VibrationPriorityManager::ExecRegisterCb, currentUserObserver_);
execCb.detach();
ReleaseDataShareHelper(doNotDisturbHelper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
MISC_HILOGI("Succeed to RegisterUserObserver of uri");
return ERR_OK;
}
int32_t VibrationPriorityManager::UnregisterUserObserver()
{
MISC_HILOGI("UnregisterUserObserver start");
std::lock_guard<std::mutex> currentUserObserverLock(currentUserObserverMutex_);
if (currentUserObserver_ == nullptr) {
MISC_HILOGE("currentUserObserver_ is nullptr");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "normal";
auto doNotDisturbHelper =
CreateDataShareHelper(ReplaceUserIdForUri(USER_SETTING_SECURE_URI_PROXY, g_currentUserId.load()), tableType);
if (doNotDisturbHelper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "UnregisterUserObserver", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
currentUserObserver_ = nullptr;
MISC_HILOGE("doNotDisturbHelper is nullptr");
return MISC_NO_INIT_ERR;
}
auto doNotDisturbSwitch = DoNotDisturbAssembleUri(DO_NOT_DISTURB_SWITCH);
doNotDisturbHelper->UnregisterObserver(doNotDisturbSwitch, currentUserObserver_);
auto doNotDisturbWhiteList = DoNotDisturbAssembleUri(DO_NOT_DISTURB_WHITE_LIST);
doNotDisturbHelper->UnregisterObserver(doNotDisturbWhiteList, currentUserObserver_);
ReleaseDataShareHelper(doNotDisturbHelper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
currentUserObserver_ = nullptr;
MISC_HILOGI("Succeed to UnregisterUserObserver observer");
return ERR_OK;
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
int32_t VibrationPriorityManager::RegisterUser100Observer()
{
MISC_HILOGI("RegisterUser100Observer start");
MiscDeviceObserver::UpdateFunc updateFunc = [&]() {
InitVibrateWhenRing();
};
std::lock_guard<std::mutex> lock(vibrateWhenRingObserverMutex_);
vibrateWhenRingObserver_ = CreateObserver(updateFunc);
if (vibrateWhenRingObserver_ == nullptr) {
MISC_HILOGE("vibrateWhenRingObserver_ is null");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "system";
auto helper =
CreateDataShareHelper(SETTING_USER_URI_PROXY, tableType);
if (helper == nullptr) {
IPCSkeleton::SetCallingIdentity(callingIdentity);
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "RegisterUser100Observer", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
MISC_HILOGE("doNotDisturbHelper is nullptr");
return MISC_NO_INIT_ERR;
}
auto vibrateWhenRing = AssembleUri(SETTING_USER_URI_PROXY, VIBRATE_WHEN_RINGING_KEY, tableType);
helper->RegisterObserver(vibrateWhenRing, vibrateWhenRingObserver_);
helper->NotifyChange(vibrateWhenRing);
std::thread execCb(VibrationPriorityManager::ExecRegisterCb, vibrateWhenRingObserver_);
execCb.detach();
ReleaseDataShareHelper(helper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
MISC_HILOGI("Succeed to RegisterUser100Observer of uri");
return ERR_OK;
}
#endif
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
int32_t VibrationPriorityManager::UnregisterUser100Observer()
{
MISC_HILOGI("UnregisterUser100Observer start");
std::lock_guard<std::mutex> lock(vibrateWhenRingObserverMutex_);
if (vibrateWhenRingObserver_ == nullptr) {
MISC_HILOGE("vibrateWhenRingObserver_ is nullptr");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "system";
auto helper = CreateDataShareHelper(SETTING_USER_URI_PROXY, tableType);
if (helper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "UnregisterUser100Observer", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
vibrateWhenRingObserver_ = nullptr;
MISC_HILOGE("helper is nullptr");
return MISC_NO_INIT_ERR;
}
auto vibrateWhenRing = AssembleUri(SETTING_USER_URI_PROXY, VIBRATE_WHEN_RINGING_KEY, tableType);
helper->UnregisterObserver(vibrateWhenRing, vibrateWhenRingObserver_);
IPCSkeleton::SetCallingIdentity(callingIdentity);
vibrateWhenRingObserver_ = nullptr;
MISC_HILOGI("Succeed to UnregisterUser100Observer observer");
return ERR_OK;
}
#endif
std::string VibrationPriorityManager::ReplaceUserIdForUri(std::string uri, int32_t userId)
{
std::string tempUri = uri;
std::regex pattern(USERID_REPLACE);
std::string result = std::regex_replace(tempUri, pattern, std::to_string(userId));
const size_t MAX_URI_LENGTH = 2048;
if (result.length() > MAX_URI_LENGTH) {
MISC_HILOGE("URI too long after replacement:%{public}zu", result.length());
return uri;
}
return result;
}
Uri VibrationPriorityManager::DoNotDisturbAssembleUri(const std::string &key)
{
Uri uri(ReplaceUserIdForUri(USER_SETTING_SECURE_URI_PROXY, g_currentUserId.load()) + "&key=" + key);
return uri;
}
int32_t VibrationPriorityManager::GetDoNotDisturbStringValue(const std::string &key, std::string &value)
{
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "normal";
auto helper = CreateDataShareHelper(ReplaceUserIdForUri(USER_SETTING_SECURE_URI_PROXY, g_currentUserId.load()),
tableType);
if (helper == nullptr) {
IPCSkeleton::SetCallingIdentity(callingIdentity);
MISC_HILOGE("helper is nullptr");
return MISC_NO_INIT_ERR;
}
std::vector<std::string> columns = { SETTING_COLUMN_VALUE };
DataShare::DataSharePredicates predicates;
predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
Uri uri(DoNotDisturbAssembleUri(key));
auto resultSet = helper->Query(uri, predicates, columns);
ReleaseDataShareHelper(helper);
if (resultSet == nullptr) {
MISC_HILOGE("resultSet is nullptr");
IPCSkeleton::SetCallingIdentity(callingIdentity);
return MISC_INVALID_OPERATION_ERR;
}
int32_t count;
resultSet->GetRowCount(count);
if (count == 0) {
MISC_HILOGW("Not found value, key:%{public}s, count:%{public}d", key.c_str(), count);
IPCSkeleton::SetCallingIdentity(callingIdentity);
return MISC_NAME_NOT_FOUND_ERR;
}
const int32_t index = 0;
resultSet->GoToRow(index);
int32_t ret = resultSet->GetString(index, value);
if (ret != ERR_OK) {
MISC_HILOGW("GetString failed, ret:%{public}d", ret);
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERROR;
}
resultSet->Close();
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERR_OK;
}
int32_t VibrationPriorityManager::GetDoNotDisturbIntValue(const std::string &key, int32_t &value)
{
int64_t valueLong;
int32_t ret = GetDoNotDisturbLongValue(key, valueLong);
if (ret != ERR_OK) {
MISC_HILOGE("GetDoNotDisturbLongValue failed, ret:%{public}d", ret);
return ret;
}
value = static_cast<int32_t>(valueLong);
return ERR_OK;
}
int32_t VibrationPriorityManager::GetDoNotDisturbLongValue(const std::string &key, int64_t &value)
{
std::string valueStr;
int32_t ret = GetDoNotDisturbStringValue(key, valueStr);
if (ret != ERR_OK) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "GetDoNotDisturbStringValue", "ERROR_CODE", ret);
#endif
MISC_HILOGE("GetDoNotDisturbStringValue failed, ret:%{public}d", ret);
return ret;
}
value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, DECEM_BASE));
return ERR_OK;
}
int32_t VibrationPriorityManager::GetWhiteListValue(const std::string &key, std::vector<WhiteListAppInfo> &value)
{
std::string valueStr;
int32_t ret = GetDoNotDisturbStringValue(key, valueStr);
if (ret != ERR_OK) {
MISC_HILOGE("GetDoNotDisturbStringValue failed, ret:%{public}d", ret);
return ret;
}
if (valueStr.empty()) {
MISC_HILOGE("String value empty");
return ERROR;
}
cJSON *jsonArray = nullptr;
jsonArray = cJSON_Parse(valueStr.c_str());
if (!cJSON_IsArray(jsonArray)) {
MISC_HILOGE("The string value is not array");
DeleteCJSONValue(jsonArray);
return ERROR;
}
int32_t size = cJSON_GetArraySize(jsonArray);
for (int32_t i = 0; i < size; ++i) {
cJSON *valJson = cJSON_GetArrayItem(jsonArray, i);
if (!cJSON_IsObject(valJson)) {
MISC_HILOGE("The json is not object");
DeleteCJSONValue(jsonArray);
return ERROR;
}
if (!cJSON_HasObjectItem(valJson, WHITE_LIST_KEY_BUNDLE.c_str()) ||
!cJSON_HasObjectItem(valJson, WHITE_LIST_KEY_UID.c_str())) {
MISC_HILOGE("The json is not bundle or uid");
DeleteCJSONValue(jsonArray);
return ERROR;
}
WhiteListAppInfo whiteListAppInfo;
cJSON *valBundle = cJSON_GetObjectItem(valJson, WHITE_LIST_KEY_BUNDLE.c_str());
cJSON *valUid = cJSON_GetObjectItem(valJson, WHITE_LIST_KEY_UID.c_str());
if ((!cJSON_IsString(valBundle)) || !cJSON_IsNumber(valUid)) {
MISC_HILOGE("The value of index %{public}d is not match", i);
DeleteCJSONValue(jsonArray);
return ERROR;
}
whiteListAppInfo.bundle = valBundle->valuestring;
whiteListAppInfo.uid = static_cast<int64_t>(valUid->valueint);
value.push_back(whiteListAppInfo);
}
DeleteCJSONValue(jsonArray);
return ERR_OK;
}
void VibrationPriorityManager::DeleteCJSONValue(cJSON *jsonValue)
{
if (jsonValue != nullptr) {
cJSON_Delete(jsonValue);
}
}
bool VibrationPriorityManager::IgnoreAppVibrations(const VibrateInfo &vibrateInfo)
{
if (vibrateInfo.usage != USAGE_NOTIFICATION && vibrateInfo.usage != USAGE_RING) {
MISC_HILOGD("Vibration is not ignored , usage:%{public}d", vibrateInfo.usage);
return false;
}
if (doNotDisturbSwitch_ != DONOTDISTURB_SWITCH_ON) {
MISC_HILOGD("DoNotDisturbSwitch is off");
return false;
}
std::lock_guard<std::mutex> whiteListLock(whiteListMutex_);
for (const WhiteListAppInfo &whiteListAppInfo : doNotDisturbWhiteList_) {
if (vibrateInfo.packageName == whiteListAppInfo.bundle) {
MISC_HILOGD("Not ignore app vibration, the app is on the whitelist, bundleName::%{public}s",
vibrateInfo.packageName.c_str());
return false;
}
}
MISC_HILOGI("Ignore app vibration, bundleName::%{public}s", vibrateInfo.packageName.c_str());
return true;
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
void VibrationPriorityManager::MiscCrownIntensityFeedbackInit(void)
{
int32_t crownfeedback = miscCrownFeedback_;
std::string tableType = "normal";
if (GetIntValue(SETTING_URI_PROXY, SETTING_CROWN_FEEDBACK_KEY, crownfeedback, tableType) != ERR_OK) {
MISC_HILOGE("Get crownfeedback failed");
}
miscCrownFeedback_ = crownfeedback;
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE", HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE",
"crownfeedback", "STATUS", crownfeedback);
#endif
int32_t intensity = miscIntensity_;
if (GetIntValue(SETTING_URI_PROXY, SETTING_VIBRATE_INTENSITY_KEY, intensity, tableType) != ERR_OK) {
intensity = FEEDBACK_INTENSITY_STRONGE;
MISC_HILOGE("Get intensity failed");
}
miscIntensity_ = intensity;
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE", HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE",
"intensity", "STATUS", intensity);
#endif
}
bool VibrationPriorityManager::ShouldIgnoreByIntensity(const VibrateInfo &vibrateInfo)
{
std::string effect = vibrateInfo.effect;
if (effect.find("crown") != std::string::npos) {
if (miscCrownFeedback_ == FEEDBACK_MODE_OFF) {
return true;
}
} else {
if (miscIntensity_ == FEEDBACK_INTENSITY_NONE) {
if ((effect.find("short") != std::string::npos) || (effect.find("feedback") != std::string::npos)) {
return false;
}
return true;
}
}
return false;
}
#endif
int32_t VibrationPriorityManager::GetIntValue(const std::string &uri, const std::string &key, int32_t &value,
const std::string &tableType)
{
int64_t valueLong;
int32_t ret = GetLongValue(uri, key, valueLong, tableType);
if (ret != ERR_OK) {
return ret;
}
value = static_cast<int32_t>(valueLong);
return ERR_OK;
}
int32_t VibrationPriorityManager::GetLongValue(const std::string &uri, const std::string &key, int64_t &value,
const std::string &tableType)
{
std::string valueStr;
int32_t ret = GetStringValue(uri, key, valueStr, tableType);
if (ret != ERR_OK) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "GetStringValue", "ERROR_CODE", ret);
#endif
MISC_HILOGE("GetStringValue failed, ret:%{public}d", ret);
return ret;
}
value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, DECEM_BASE));
return ERR_OK;
}
int32_t VibrationPriorityManager::GetStringValue(const std::string &uriProxy, const std::string &key,
std::string &value, const std::string &tableType)
{
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
auto helper = CreateDataShareHelper(uriProxy, tableType);
if (helper == nullptr) {
IPCSkeleton::SetCallingIdentity(callingIdentity);
return MISC_NO_INIT_ERR;
}
std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
DataShare::DataSharePredicates predicates;
predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
Uri uri(AssembleUri(uriProxy, key, tableType));
auto resultSet = helper->Query(uri, predicates, columns);
ReleaseDataShareHelper(helper);
if (resultSet == nullptr) {
MISC_HILOGE("resultSet is nullptr");
IPCSkeleton::SetCallingIdentity(callingIdentity);
return MISC_INVALID_OPERATION_ERR;
}
int32_t count;
resultSet->GetRowCount(count);
if (count == 0) {
MISC_HILOGW("Not found value, key:%{public}s, count:%{public}d", key.c_str(), count);
IPCSkeleton::SetCallingIdentity(callingIdentity);
return MISC_NAME_NOT_FOUND_ERR;
}
const int32_t index = 0;
resultSet->GoToRow(index);
int32_t ret = resultSet->GetString(index, value);
if (ret != ERR_OK) {
MISC_HILOGW("GetString failed, ret:%{public}d", ret);
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERROR;
}
resultSet->Close();
IPCSkeleton::SetCallingIdentity(callingIdentity);
return ERR_OK;
}
void VibrationPriorityManager::UpdateStatus()
{
if (miscFeedback_ == FEEDBACK_MODE_INVALID) {
int32_t feedback = FEEDBACK_MODE_INVALID;
std::string tableType = "normal";
if (GetIntValue(SETTING_URI_PROXY, SETTING_FEEDBACK_KEY, feedback, tableType) != ERR_OK) {
feedback = FEEDBACK_MODE_ON;
MISC_HILOGE("Get feedback failed");
}
miscFeedback_ = feedback;
}
if (miscAudioRingerMode_ == RINGER_MODE_INVALID) {
int32_t ringerMode = RINGER_MODE_INVALID;
std::string tableType = "normal";
if (GetIntValue(SETTING_URI_PROXY, SETTING_RINGER_MODE_KEY, ringerMode, tableType) != ERR_OK) {
ringerMode = RINGER_MODE_NORMAL;
MISC_HILOGE("Get ringerMode failed");
}
miscAudioRingerMode_ = ringerMode;
}
if (doNotDisturbSwitch_ == DONOTDISTURB_SWITCH_INVALID) {
InitDoNotDisturbData();
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
if (vibrateWhenRing_.load() == VIBRATE_WHEN_RING_MODE_INVALID) {
InitVibrateWhenRing();
}
UpdateInputMethodBundleNames();
#endif
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
if (miscCrownFeedback_ == FEEDBACK_MODE_INVALID) {
int32_t corwnfeedback = FEEDBACK_MODE_INVALID;
std::string tableType = "normal";
if (GetIntValue(SETTING_URI_PROXY, SETTING_CROWN_FEEDBACK_KEY, corwnfeedback, tableType) != ERR_OK) {
corwnfeedback = FEEDBACK_MODE_ON;
MISC_HILOGE("Get corwnfeedback failed");
}
miscCrownFeedback_ = corwnfeedback;
}
if (miscIntensity_ == FEEDBACK_INTENSITY_INVALID) {
int32_t intensity = FEEDBACK_INTENSITY_INVALID;
std::string tableType = "normal";
if (GetIntValue(SETTING_URI_PROXY, SETTING_VIBRATE_INTENSITY_KEY, intensity, tableType) != ERR_OK) {
intensity = FEEDBACK_INTENSITY_STRONGE;
MISC_HILOGE("Get intensity failed");
}
miscIntensity_ = intensity;
}
#endif
}
bool VibrationPriorityManager::IsSystemServiceCalling()
{
const auto tokenId = IPCSkeleton::GetCallingTokenID();
const auto flag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
if (flag == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
MISC_HILOGD("System service calling, flag: %{public}u", flag);
return true;
}
return false;
}
bool VibrationPriorityManager::IsSystemCalling()
{
if (IsSystemServiceCalling()) {
return true;
}
return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID());
}
void VibrationPriorityManager::ReportSwitchStatus()
{
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE", HiSysEvent::EventType::BEHAVIOR,
"SWITCH_TYPE", "feedbackCurrentStatus", "STATUS", miscFeedback_.load());
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE", HiSysEvent::EventType::BEHAVIOR,
"SWITCH_TYPE", "ringerModeCurrentStatus", "STATUS", miscAudioRingerMode_.load());
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE", HiSysEvent::EventType::BEHAVIOR,
"SWITCH_TYPE", "crownfeedback", "STATUS", miscCrownFeedback_.load());
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE", HiSysEvent::EventType::BEHAVIOR,
"SWITCH_TYPE", "intensity", "STATUS", miscIntensity_.load());
#endif
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE", HiSysEvent::EventType::BEHAVIOR,
"SWITCH_TYPE", "currentDoNotDisturbSwitch", "STATUS", doNotDisturbSwitch_.load());
#endif
}
void VibrationPriorityManager::PrintDoNotDisturbSwitchStatus(int32_t oldSwitchStatus, int32_t currentSwitchStatus)
{
if (oldSwitchStatus != currentSwitchStatus) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE",
HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE", "doNotDisturbSwitch", "STATUS", currentSwitchStatus);
#endif
}
}
void VibrationPriorityManager::InitInputMethodData()
{
std::string valueStr;
std::string tableType = "system";
int32_t ret = GetStringValue(SETTING_USER_URI_PROXY, USER_SETTINGS_ENABLE_IME, valueStr, tableType);
if (ret != ERR_OK) {
MISC_HILOGE("GetStringValue failed, ret:%{public}d", ret);
return;
}
if (valueStr.empty()) {
MISC_HILOGE("String value empty");
return;
}
cJSON *jsonValue = cJSON_Parse(valueStr.c_str());
if (jsonValue == nullptr) {
MISC_HILOGE("String value is not json");
return;
}
cJSON *inputMethodsJson = cJSON_GetObjectItem(jsonValue, INPUT_METHODS_KEY.c_str());
if (inputMethodsJson == nullptr || !cJSON_IsArray(inputMethodsJson)) {
MISC_HILOGE("Data is empty or data structure is incorrect");
cJSON_Delete(jsonValue);
return;
}
std::lock_guard<std::mutex> inputMethodBundleNamesLock(inputMethodBundleNamesMutex_);
inputMethodBundleNames_.clear();
int32_t size = cJSON_GetArraySize(inputMethodsJson);
for (int32_t i = 0; i < size; ++i) {
cJSON *valJson = cJSON_GetArrayItem(inputMethodsJson, i);
if (valJson == nullptr) {
MISC_HILOGE("Data is empty or data structure is incorrect");
cJSON_Delete(jsonValue);
return;
}
cJSON *valBundleName = cJSON_GetObjectItem(valJson, INPUT_METHOD_KEY_BUNDLE_NAME.c_str());
if (valBundleName == nullptr || !cJSON_IsString(valBundleName)) {
MISC_HILOGE("Data is empty or data structure is incorrect");
cJSON_Delete(jsonValue);
return;
}
inputMethodBundleNames_.push_back(valBundleName->valuestring);
}
inputMethodBundleNamesInitialized_.store(true);
cJSON_Delete(jsonValue);
}
int32_t VibrationPriorityManager::RegisterUserImfObserver()
{
MISC_HILOGI("RegisterUserImfObserver start");
std::lock_guard<std::mutex> currentUserImfObserverLock(currentUserImfObserverMutex_);
MiscDeviceObserver::UpdateFunc updateFunc = [&]() { InitInputMethodData(); };
currentUserImfObserver_ = CreateObserver(updateFunc);
if (currentUserImfObserver_ == nullptr) {
MISC_HILOGE("currentUserImfObserver_ is null");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "system";
auto inputMethodHelper = CreateDataShareHelper(SETTING_USER_URI_PROXY, tableType);
if (inputMethodHelper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "RegisterUserImfObserver", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
MISC_HILOGE("inputMethodHelper is nullptr");
return MISC_NO_INIT_ERR;
}
Uri uriImf = AssembleUri(SETTING_USER_URI_PROXY, USER_SETTINGS_ENABLE_IME, tableType);
inputMethodHelper->RegisterObserver(uriImf, currentUserImfObserver_);
inputMethodHelper->NotifyChange(uriImf);
std::thread execCb(VibrationPriorityManager::ExecRegisterCb, currentUserImfObserver_);
execCb.detach();
ReleaseDataShareHelper(inputMethodHelper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
MISC_HILOGI("Succeed to RegisterUserImfObserver");
return ERR_OK;
}
int32_t VibrationPriorityManager::UnregisterUserImfObserver()
{
MISC_HILOGI("UnregisterUserImfObserver start");
std::lock_guard<std::mutex> currentUserImfObserverLock(currentUserImfObserverMutex_);
if (currentUserImfObserver_ == nullptr) {
MISC_HILOGE("currentUserImfObserver_ is nullptr");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "system";
auto inputMethodHelper = CreateDataShareHelper(SETTING_USER_URI_PROXY, tableType);
if (inputMethodHelper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "UnregisterUserImfObserver", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
currentUserImfObserver_ = nullptr;
MISC_HILOGE("inputMethodHelper is nullptr");
return MISC_NO_INIT_ERR;
}
Uri uriImf = AssembleUri(SETTING_USER_URI_PROXY, USER_SETTINGS_ENABLE_IME, tableType);
inputMethodHelper->UnregisterObserver(uriImf, currentUserImfObserver_);
ReleaseDataShareHelper(inputMethodHelper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
currentUserImfObserver_ = nullptr;
MISC_HILOGI("Succeed to UnregisterUserImfObserver");
return ERR_OK;
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
bool VibrationPriorityManager::ShouldIgnoreInputMethod(const VibrateInfo &vibrateInfo)
{
if (vibrateInfo.packageName == SCENEBOARD_BUNDLENAME) {
MISC_HILOGD("Can not ignore for %{public}s", vibrateInfo.packageName.c_str());
return false;
}
std::lock_guard<std::mutex> inputMethodBundleNamesLock(inputMethodBundleNamesMutex_);
if (std::find(inputMethodBundleNames_.begin(), inputMethodBundleNames_.end(),
vibrateInfo.packageName) != inputMethodBundleNames_.end()) {
MISC_HILOGD("Input method bundleName:%{public}s", vibrateInfo.packageName.c_str());
return true;
}
return false;
}
void VibrationPriorityManager::UpdateInputMethodBundleNames()
{
if (inputMethodBundleNamesInitialized_.load()) {
MISC_HILOGD("Input method bundle names has been initialized");
return;
}
InitInputMethodData();
}
#endif
VibrateStatus VibrationPriorityManager::ShouldIgnoreVibrate(const VibrateInfo &vibrateInfo,
const std::shared_ptr<VibratorThread> &vibratorThread, const VibratorIdentifierIPC& identifier)
{
UpdateStatus();
if ((vibrateInfo.usage == USAGE_ALARM || vibrateInfo.usage == USAGE_RING
|| vibrateInfo.usage == USAGE_NOTIFICATION || vibrateInfo.usage == USAGE_COMMUNICATION)
&& (isVibratorMute_.load())) {
MISC_HILOGD("Vibration is ignored for vibrator mute");
return IGNORE_VIBRATOR_MUTE;
}
if (!IsSystemCalling() || vibrateInfo.systemUsage == false) {
if (IgnoreAppVibrations(vibrateInfo)) {
MISC_HILOGD("Vibration is ignored for doNotDisturb, usage:%{public}d", vibrateInfo.usage);
return IGNORE_GLOBAL_SETTINGS;
}
if ((vibrateInfo.usage == USAGE_ALARM || vibrateInfo.usage == USAGE_RING
|| vibrateInfo.usage == USAGE_NOTIFICATION || vibrateInfo.usage == USAGE_COMMUNICATION)
&& (miscAudioRingerMode_ == RINGER_MODE_SILENT)) {
MISC_HILOGD("Vibration is ignored for ringer mode:%{public}d", static_cast<int32_t>(miscAudioRingerMode_));
return IGNORE_RINGER_MODE;
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
int32_t ringerMode = miscAudioRingerMode_.load();
int32_t vibrateWhenRing = vibrateWhenRing_.load();
if ((vibrateInfo.usage == USAGE_RING || vibrateInfo.usage == USAGE_COMMUNICATION)
&& (ringerMode == RINGER_MODE_NORMAL) && (vibrateWhenRing == VIBRATE_WHEN_RING_MODE_OFF)) {
MISC_HILOGD("Vibration is ignored for vibrateWhenRinging, ringer:%{public}d, vibrateWhenRinging:%{public}d",
ringerMode, vibrateWhenRing);
return IGNORE_RINGER_VIBRATE_WHEN_RING;
}
#endif
if (((vibrateInfo.usage == USAGE_TOUCH || vibrateInfo.usage == USAGE_MEDIA || vibrateInfo.usage == USAGE_UNKNOWN
|| vibrateInfo.usage == USAGE_PHYSICAL_FEEDBACK || vibrateInfo.usage == USAGE_SIMULATE_REALITY)
&& (miscFeedback_ == FEEDBACK_MODE_OFF))
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_INPUT_METHOD
&& !ShouldIgnoreInputMethod(vibrateInfo)) {
#else
) {
#endif
MISC_HILOGD("Vibration is ignored for feedback:%{public}d", static_cast<int32_t>(miscFeedback_));
return IGNORE_FEEDBACK;
}
}
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
if (ShouldIgnoreByIntensity(vibrateInfo)) {
MISC_HILOGI("ShouldIgnoreByIntensity: vibrateInfo.effect:%{public}s", vibrateInfo.effect.c_str());
return IGNORE_FEEDBACK;
}
#endif
if (vibratorThread == nullptr) {
MISC_HILOGD("There is no vibration, it can vibrate");
return VIBRATION;
}
if (!IsCurrentVibrate(vibratorThread, identifier)) {
MISC_HILOGD("There is no vibration at the moment, it can vibrate");
return VIBRATION;
}
if (IsLoopVibrate(vibrateInfo)) {
MISC_HILOGD("Can vibrate, loop priority is high");
return VIBRATION;
}
return ShouldIgnoreVibrate(vibrateInfo, vibratorThread->GetCurrentVibrateInfo());
}
bool VibrationPriorityManager::IsCurrentVibrate(const std::shared_ptr<VibratorThread> &vibratorThread,
const VibratorIdentifierIPC& identifier) const
{
#if defined(OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM) && defined(HDF_DRIVERS_INTERFACE_VIBRATOR)
return ((vibratorThread != nullptr) && (vibratorThread->IsRunning() ||
VibratorDevice.IsVibratorRunning(identifier)));
#else
return ((vibratorThread != nullptr) && (vibratorThread->IsRunning()));
#endif
}
bool VibrationPriorityManager::IsLoopVibrate(const VibrateInfo &vibrateInfo) const
{
return ((vibrateInfo.mode == "preset") && (vibrateInfo.count > 1));
}
VibrateStatus VibrationPriorityManager::ShouldIgnoreVibrate(const VibrateInfo &vibrateInfo,
VibrateInfo currentVibrateInfo) const
{
if (currentVibrateInfo.usage == USAGE_ALARM) {
MISC_HILOGD("Vibration is ignored for alarm");
return IGNORE_ALARM;
}
if (IsLoopVibrate(currentVibrateInfo)) {
MISC_HILOGD("Vibration is ignored for repeat");
return IGNORE_REPEAT;
}
if ((currentVibrateInfo.usage != vibrateInfo.usage) && (vibrateInfo.usage == USAGE_UNKNOWN)) {
MISC_HILOGD("Vibration is ignored, unknown has a low priority");
return IGNORE_UNKNOWN;
}
return VIBRATION;
}
sptr<MiscDeviceObserver> VibrationPriorityManager::CreateObserver(const MiscDeviceObserver::UpdateFunc &func)
{
sptr<MiscDeviceObserver> observer = new MiscDeviceObserver();
if (observer == nullptr) {
MISC_HILOGE("observer is null");
return observer;
}
observer->SetUpdateFunc(func);
return observer;
}
Uri VibrationPriorityManager::AssembleUri(const std::string &uriProxy, const std::string &key,
const std::string &tableType)
{
std::string finalUri = uriProxy;
int32_t currentUserId = g_currentUserId.load();
if (currentUserId > 0 && tableType == "system") {
finalUri += std::to_string(currentUserId) + "?Proxy=true";
}
return Uri(finalUri + "&key=" + key);
}
std::shared_ptr<DataShare::DataShareHelper> VibrationPriorityManager::CreateDataShareHelper(const std::string &tableUrl,
const std::string &tableType)
{
if (remoteObj_ == nullptr) {
MISC_HILOGE("remoteObj_ is nullptr");
return nullptr;
}
std::shared_ptr<DataShare::DataShareHelper> helper = nullptr;
std::string SettingSystemUrlProxy = "";
int32_t currentUserId = g_currentUserId.load();
if (currentUserId > 0 && tableType == "system") {
SettingSystemUrlProxy =
tableUrl + std::to_string(currentUserId) + "?Proxy=true";
helper = DataShare::DataShareHelper::Creator(remoteObj_, SettingSystemUrlProxy, SETTINGS_DATA_EXT_URI);
} else {
helper = DataShare::DataShareHelper::Creator(remoteObj_, tableUrl, SETTINGS_DATA_EXT_URI);
}
if (helper == nullptr) {
MISC_HILOGE("Create data_share helper failed, uri proxy:%{public}s", tableUrl.c_str());
}
return helper;
}
bool VibrationPriorityManager::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> &helper)
{
if (!helper->Release()) {
MISC_HILOGW("Release helper fail");
return false;
}
return true;
}
void VibrationPriorityManager::ExecRegisterCb(const sptr<MiscDeviceObserver> &observer)
{
if (observer == nullptr) {
MISC_HILOGE("observer is nullptr");
return;
}
observer->OnChange();
}
int32_t VibrationPriorityManager::RegisterObserver(const sptr<MiscDeviceObserver> &observer)
{
if (observer == nullptr) {
MISC_HILOGE("observer is nullptr");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "normal";
auto helper = CreateDataShareHelper(SETTING_URI_PROXY, tableType);
if (helper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "RegisterObserver", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
return MISC_NO_INIT_ERR;
}
auto uriFeedback = AssembleUri(SETTING_URI_PROXY, SETTING_FEEDBACK_KEY, tableType);
helper->RegisterObserver(uriFeedback, observer);
helper->NotifyChange(uriFeedback);
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
auto uriCrownFeedback = AssembleUri(SETTING_URI_PROXY, SETTING_CROWN_FEEDBACK_KEY, tableType);
helper->RegisterObserver(uriCrownFeedback, observer);
helper->NotifyChange(uriCrownFeedback);
auto uriIntensityContrl = AssembleUri(SETTING_URI_PROXY, SETTING_VIBRATE_INTENSITY_KEY, tableType);
helper->RegisterObserver(uriIntensityContrl, observer);
helper->NotifyChange(uriIntensityContrl);
#endif
auto uriRingerMode = AssembleUri(SETTING_URI_PROXY, SETTING_RINGER_MODE_KEY, tableType);
helper->RegisterObserver(uriRingerMode, observer);
helper->NotifyChange(uriRingerMode);
std::thread execCb(VibrationPriorityManager::ExecRegisterCb, observer);
execCb.detach();
ReleaseDataShareHelper(helper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
MISC_HILOGI("Succeed to register observer of uri");
return ERR_OK;
}
int32_t VibrationPriorityManager::UnregisterObserver(const sptr<MiscDeviceObserver> &observer)
{
if (observer == nullptr) {
MISC_HILOGE("observer is nullptr");
return MISC_NO_INIT_ERR;
}
std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
std::string tableType = "normal";
auto helper = CreateDataShareHelper(SETTING_URI_PROXY, tableType);
if (helper == nullptr) {
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION", HiSysEvent::EventType::FAULT,
"PKG_NAME", "UnregisterObserver", "ERROR_CODE", MISC_NO_INIT_ERR);
#endif
IPCSkeleton::SetCallingIdentity(callingIdentity);
return MISC_NO_INIT_ERR;
}
auto uriFeedback = AssembleUri(SETTING_URI_PROXY, SETTING_FEEDBACK_KEY, tableType);
helper->UnregisterObserver(uriFeedback, observer);
#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CROWN
auto uriCrownFeedback = AssembleUri(SETTING_URI_PROXY, SETTING_CROWN_FEEDBACK_KEY, tableType);
helper->UnregisterObserver(uriCrownFeedback, observer);
auto uriIntensityContrl = AssembleUri(SETTING_URI_PROXY, SETTING_VIBRATE_INTENSITY_KEY, tableType);
helper->UnregisterObserver(uriIntensityContrl, observer);
#endif
auto uriRingerMode = AssembleUri(SETTING_URI_PROXY, SETTING_RINGER_MODE_KEY, tableType);
helper->UnregisterObserver(uriRingerMode, observer);
ReleaseDataShareHelper(helper);
IPCSkeleton::SetCallingIdentity(callingIdentity);
MISC_HILOGI("Succeed to unregister observer");
return ERR_OK;
}
void VibrationPriorityManager::SetIgnoreSwitchStatus(bool status)
{
isVibratorMute_.store(status);
}
}
}