1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "vibration_priority_manager.h"
17
18 #include "ipc_skeleton.h"
19 #include "iservice_registry.h"
20 #include "system_ability_definition.h"
21 #include "uri.h"
22
23 #include "sensors_errors.h"
24
25 #undef LOG_TAG
26 #define LOG_TAG "VibrationPriorityManager"
27
28 namespace OHOS {
29 namespace Sensors {
30 namespace {
31 const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
32 const std::string SETTING_COLUMN_VALUE = "VALUE";
33 const std::string SETTING_FEEDBACK_KEY = "physic_navi_haptic_feedback_enabled";
34 const std::string SETTING_RINGER_MODE_KEY = "ringer_mode";
35 const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
36 constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
37 constexpr int32_t DECEM_BASE = 10;
38 } // namespace
39
VibrationPriorityManager()40 VibrationPriorityManager::VibrationPriorityManager()
41 {
42 Initialize();
43 MiscDeviceObserver::UpdateFunc updateFunc = [&]() {
44 int32_t feedback = miscFeedback_;
45 if (GetIntValue(SETTING_FEEDBACK_KEY, feedback) != ERR_OK) {
46 MISC_HILOGE("Get feedback failed");
47 }
48 miscFeedback_ = feedback;
49 MISC_HILOGI("feedback:%{public}d", feedback);
50 int32_t ringerMode = miscAudioRingerMode_;
51 if (GetIntValue(SETTING_RINGER_MODE_KEY, ringerMode) != ERR_OK) {
52 MISC_HILOGE("Get ringerMode failed");
53 }
54 miscAudioRingerMode_ = ringerMode;
55 MISC_HILOGI("ringerMode:%{public}d", ringerMode);
56 };
57 auto observer = CreateObserver(updateFunc);
58 if (observer == nullptr) {
59 MISC_HILOGE("observer is null");
60 return;
61 }
62 observer_ = observer;
63 if (RegisterObserver(observer_) != ERR_OK) {
64 MISC_HILOGE("RegisterObserver failed");
65 }
66 }
67
~VibrationPriorityManager()68 VibrationPriorityManager::~VibrationPriorityManager()
69 {
70 remoteObj_ = nullptr;
71 if (UnregisterObserver(observer_) != ERR_OK) {
72 MISC_HILOGE("UnregisterObserver failed");
73 }
74 }
75
GetIntValue(const std::string & key,int32_t & value)76 int32_t VibrationPriorityManager::GetIntValue(const std::string &key, int32_t &value)
77 {
78 int64_t valueLong;
79 int32_t ret = GetLongValue(key, valueLong);
80 if (ret != ERR_OK) {
81 return ret;
82 }
83 value = static_cast<int32_t>(valueLong);
84 return ERR_OK;
85 }
86
GetLongValue(const std::string & key,int64_t & value)87 int32_t VibrationPriorityManager::GetLongValue(const std::string &key, int64_t &value)
88 {
89 std::string valueStr;
90 int32_t ret = GetStringValue(key, valueStr);
91 if (ret != ERR_OK) {
92 return ret;
93 }
94 value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, DECEM_BASE));
95 return ERR_OK;
96 }
97
GetStringValue(const std::string & key,std::string & value)98 int32_t VibrationPriorityManager::GetStringValue(const std::string &key, std::string &value)
99 {
100 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
101 auto helper = CreateDataShareHelper();
102 if (helper == nullptr) {
103 IPCSkeleton::SetCallingIdentity(callingIdentity);
104 return MISC_NO_INIT_ERR;
105 }
106 std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
107 DataShare::DataSharePredicates predicates;
108 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
109 Uri uri(AssembleUri(key));
110 auto resultSet = helper->Query(uri, predicates, columns);
111 ReleaseDataShareHelper(helper);
112 if (resultSet == nullptr) {
113 MISC_HILOGE("resultSet is nullptr");
114 IPCSkeleton::SetCallingIdentity(callingIdentity);
115 return MISC_INVALID_OPERATION_ERR;
116 }
117 int32_t count;
118 resultSet->GetRowCount(count);
119 if (count == 0) {
120 MISC_HILOGW("Not found value, key:%{public}s, count:%{public}d", key.c_str(), count);
121 IPCSkeleton::SetCallingIdentity(callingIdentity);
122 return MISC_NAME_NOT_FOUND_ERR;
123 }
124 const int32_t index = 0;
125 resultSet->GoToRow(index);
126 int32_t ret = resultSet->GetString(index, value);
127 if (ret != ERR_OK) {
128 MISC_HILOGW("GetString failed, ret:%{public}d", ret);
129 IPCSkeleton::SetCallingIdentity(callingIdentity);
130 return ERROR;
131 }
132 resultSet->Close();
133 IPCSkeleton::SetCallingIdentity(callingIdentity);
134 return ERR_OK;
135 }
136
UpdateStatus()137 void VibrationPriorityManager::UpdateStatus()
138 {
139 if (miscFeedback_ == FEEDBACK_MODE_INVALID) {
140 int32_t feedback = FEEDBACK_MODE_INVALID;
141 if (GetIntValue(SETTING_FEEDBACK_KEY, feedback) != ERR_OK) {
142 feedback = FEEDBACK_MODE_ON;
143 MISC_HILOGE("Get feedback failed");
144 }
145 miscFeedback_ = feedback;
146 }
147 if (miscAudioRingerMode_ == RINGER_MODE_INVALID) {
148 int32_t ringerMode = RINGER_MODE_INVALID;
149 if (GetIntValue(SETTING_RINGER_MODE_KEY, ringerMode) != ERR_OK) {
150 ringerMode = RINGER_MODE_NORMAL;
151 MISC_HILOGE("Get ringerMode failed");
152 }
153 miscAudioRingerMode_ = ringerMode;
154 }
155 }
156
ShouldIgnoreVibrate(const VibrateInfo & vibrateInfo,std::shared_ptr<VibratorThread> vibratorThread)157 VibrateStatus VibrationPriorityManager::ShouldIgnoreVibrate(const VibrateInfo &vibrateInfo,
158 std::shared_ptr<VibratorThread> vibratorThread)
159 {
160 if (vibratorThread == nullptr) {
161 MISC_HILOGD("There is no vibration, it can vibrate");
162 return VIBRATION;
163 }
164 UpdateStatus();
165 if ((vibrateInfo.usage == USAGE_ALARM || vibrateInfo.usage == USAGE_RING || vibrateInfo.usage == USAGE_NOTIFICATION
166 || vibrateInfo.usage == USAGE_COMMUNICATION) && (miscAudioRingerMode_ == RINGER_MODE_SILENT)) {
167 MISC_HILOGD("Vibration is ignored for ringer mode:%{public}d", static_cast<int32_t>(miscAudioRingerMode_));
168 return IGNORE_RINGER_MODE;
169 }
170 if ((vibrateInfo.usage == USAGE_TOUCH || vibrateInfo.usage == USAGE_MEDIA || vibrateInfo.usage == USAGE_UNKNOWN
171 || vibrateInfo.usage == USAGE_PHYSICAL_FEEDBACK || vibrateInfo.usage == USAGE_SIMULATE_REALITY)
172 && (miscFeedback_ == FEEDBACK_MODE_OFF)) {
173 MISC_HILOGD("Vibration is ignored for feedback:%{public}d", static_cast<int32_t>(miscFeedback_));
174 return IGNORE_FEEDBACK;
175 }
176 if (vibratorThread == nullptr) {
177 MISC_HILOGD("There is no vibration, it can vibrate");
178 return VIBRATION;
179 }
180 if (!IsCurrentVibrate(vibratorThread)) {
181 MISC_HILOGD("There is no vibration at the moment, it can vibrate");
182 return VIBRATION;
183 }
184 if (IsLoopVibrate(vibrateInfo)) {
185 MISC_HILOGD("Can vibrate, loop priority is high");
186 return VIBRATION;
187 }
188 return ShouldIgnoreVibrate(vibrateInfo, vibratorThread->GetCurrentVibrateInfo());
189 }
190
IsCurrentVibrate(std::shared_ptr<VibratorThread> vibratorThread) const191 bool VibrationPriorityManager::IsCurrentVibrate(std::shared_ptr<VibratorThread> vibratorThread) const
192 {
193 #if defined(OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM)
194 return ((vibratorThread != nullptr) && (vibratorThread->IsRunning() || VibratorDevice.IsVibratorRunning()));
195 #else
196 return ((vibratorThread != nullptr) && (vibratorThread->IsRunning()));
197 #endif // OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM
198 }
199
IsLoopVibrate(const VibrateInfo & vibrateInfo) const200 bool VibrationPriorityManager::IsLoopVibrate(const VibrateInfo &vibrateInfo) const
201 {
202 return ((vibrateInfo.mode == "preset") && (vibrateInfo.count > 1));
203 }
204
ShouldIgnoreVibrate(const VibrateInfo & vibrateInfo,VibrateInfo currentVibrateInfo) const205 VibrateStatus VibrationPriorityManager::ShouldIgnoreVibrate(const VibrateInfo &vibrateInfo,
206 VibrateInfo currentVibrateInfo) const
207 {
208 if (currentVibrateInfo.usage == USAGE_ALARM) {
209 MISC_HILOGD("Vibration is ignored for alarm");
210 return IGNORE_ALARM;
211 }
212 if (IsLoopVibrate(currentVibrateInfo)) {
213 MISC_HILOGD("Vibration is ignored for repeat");
214 return IGNORE_REPEAT;
215 }
216 if ((currentVibrateInfo.usage != vibrateInfo.usage) && (vibrateInfo.usage == USAGE_UNKNOWN)) {
217 MISC_HILOGD("Vibration is ignored, unknown has a low priority");
218 return IGNORE_UNKNOWN;
219 }
220 return VIBRATION;
221 }
222
CreateObserver(const MiscDeviceObserver::UpdateFunc & func)223 sptr<MiscDeviceObserver> VibrationPriorityManager::CreateObserver(const MiscDeviceObserver::UpdateFunc &func)
224 {
225 sptr<MiscDeviceObserver> observer = new MiscDeviceObserver();
226 if (observer == nullptr) {
227 MISC_HILOGE("observer is null");
228 return observer;
229 }
230 observer->SetUpdateFunc(func);
231 return observer;
232 }
233
Initialize()234 void VibrationPriorityManager::Initialize()
235 {
236 auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
237 if (sm == nullptr) {
238 MISC_HILOGE("sm cannot be nullptr");
239 return;
240 }
241 auto remoteObj = sm->GetSystemAbility(MISCDEVICE_SERVICE_ABILITY_ID);
242 if (remoteObj == nullptr) {
243 MISC_HILOGE("GetSystemAbility return nullptr");
244 return;
245 }
246 remoteObj_ = remoteObj;
247 }
248
AssembleUri(const std::string & key)249 Uri VibrationPriorityManager::AssembleUri(const std::string &key)
250 {
251 Uri uri(SETTING_URI_PROXY + "&key=" + key);
252 return uri;
253 }
254
CreateDataShareHelper()255 std::shared_ptr<DataShare::DataShareHelper> VibrationPriorityManager::CreateDataShareHelper()
256 {
257 if (remoteObj_ == nullptr) {
258 MISC_HILOGE("remoteObj_ is nullptr");
259 return nullptr;
260 }
261 auto helper = DataShare::DataShareHelper::Creator(remoteObj_, SETTING_URI_PROXY, SETTINGS_DATA_EXT_URI);
262 if (helper == nullptr) {
263 MISC_HILOGW("helper is nullptr, uri proxy:%{public}s", SETTING_URI_PROXY.c_str());
264 return nullptr;
265 }
266 return helper;
267 }
268
ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> & helper)269 bool VibrationPriorityManager::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> &helper)
270 {
271 if (!helper->Release()) {
272 MISC_HILOGW("release helper fail");
273 return false;
274 }
275 return true;
276 }
277
ExecRegisterCb(const sptr<MiscDeviceObserver> & observer)278 void VibrationPriorityManager::ExecRegisterCb(const sptr<MiscDeviceObserver> &observer)
279 {
280 if (observer == nullptr) {
281 MISC_HILOGE("observer is nullptr");
282 return;
283 }
284 observer->OnChange();
285 }
286
RegisterObserver(const sptr<MiscDeviceObserver> & observer)287 int32_t VibrationPriorityManager::RegisterObserver(const sptr<MiscDeviceObserver> &observer)
288 {
289 if (observer == nullptr) {
290 MISC_HILOGE("observer is nullptr");
291 return MISC_NO_INIT_ERR;
292 }
293 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
294 auto helper = CreateDataShareHelper();
295 if (helper == nullptr) {
296 IPCSkeleton::SetCallingIdentity(callingIdentity);
297 return MISC_NO_INIT_ERR;
298 }
299 auto uriFeedback = AssembleUri(SETTING_FEEDBACK_KEY);
300 helper->RegisterObserver(uriFeedback, observer);
301 helper->NotifyChange(uriFeedback);
302 auto uriRingerMode = AssembleUri(SETTING_RINGER_MODE_KEY);
303 helper->RegisterObserver(uriRingerMode, observer);
304 helper->NotifyChange(uriRingerMode);
305 std::thread execCb(VibrationPriorityManager::ExecRegisterCb, observer);
306 execCb.detach();
307 ReleaseDataShareHelper(helper);
308 IPCSkeleton::SetCallingIdentity(callingIdentity);
309 MISC_HILOGD("succeed to register observer of uri");
310 return ERR_OK;
311 }
312
UnregisterObserver(const sptr<MiscDeviceObserver> & observer)313 int32_t VibrationPriorityManager::UnregisterObserver(const sptr<MiscDeviceObserver> &observer)
314 {
315 if (observer == nullptr) {
316 MISC_HILOGE("observer is nullptr");
317 return MISC_NO_INIT_ERR;
318 }
319 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
320 auto helper = CreateDataShareHelper();
321 if (helper == nullptr) {
322 IPCSkeleton::SetCallingIdentity(callingIdentity);
323 return MISC_NO_INIT_ERR;
324 }
325 auto uriFeedback = AssembleUri(SETTING_FEEDBACK_KEY);
326 helper->UnregisterObserver(uriFeedback, observer);
327 auto uriRingerMode = AssembleUri(SETTING_RINGER_MODE_KEY);
328 helper->UnregisterObserver(uriRingerMode, observer);
329 ReleaseDataShareHelper(helper);
330 IPCSkeleton::SetCallingIdentity(callingIdentity);
331 MISC_HILOGD("succeed to unregister observer");
332 return ERR_OK;
333 }
334 } // namespace Sensors
335 } // namespace OHOS