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 <tokenid_kit.h>
19
20 #include "accesstoken_kit.h"
21 #include "bundle_mgr_client.h"
22 #include "hisysevent.h"
23 #include "ipc_skeleton.h"
24 #include "iservice_registry.h"
25 #include "os_account_manager.h"
26 #include "running_process_info.h"
27 #include "system_ability_definition.h"
28 #include "uri.h"
29
30 #include "sensors_errors.h"
31
32 #undef LOG_TAG
33 #define LOG_TAG "VibrationPriorityManager"
34
35 namespace OHOS {
36 namespace Sensors {
37 using namespace OHOS::HiviewDFX;
38 namespace {
39 const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
40 const std::string SETTING_COLUMN_VALUE = "VALUE";
41 const std::string SETTING_FEEDBACK_KEY = "physic_navi_haptic_feedback_enabled";
42 const std::string SETTING_RINGER_MODE_KEY = "ringer_mode";
43 const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
44 const std::string SCENEBOARD_BUNDLENAME = "com.ohos.sceneboard";
45 constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
46 constexpr int32_t DECEM_BASE = 10;
47 constexpr int32_t DATA_SHARE_READY = 0;
48 constexpr int32_t DATA_SHARE_NOT_READY = 1055;
49 } // namespace
50
VibrationPriorityManager()51 VibrationPriorityManager::VibrationPriorityManager() {}
52
~VibrationPriorityManager()53 VibrationPriorityManager::~VibrationPriorityManager()
54 {
55 remoteObj_ = nullptr;
56 if (UnregisterObserver(observer_) != ERR_OK) {
57 MISC_HILOGE("UnregisterObserver failed");
58 }
59 }
60
Init()61 bool VibrationPriorityManager::Init()
62 {
63 auto sm = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
64 if (sm == nullptr) {
65 MISC_HILOGE("sm cannot be nullptr");
66 return false;
67 }
68 remoteObj_ = sm->GetSystemAbility(MISCDEVICE_SERVICE_ABILITY_ID);
69 if (remoteObj_ == nullptr) {
70 MISC_HILOGE("GetSystemAbility return nullptr");
71 return false;
72 }
73 MiscDeviceObserver::UpdateFunc updateFunc = [&]() {
74 int32_t feedback = miscFeedback_;
75 if (GetIntValue(SETTING_FEEDBACK_KEY, feedback) != ERR_OK) {
76 MISC_HILOGE("Get feedback failed");
77 }
78 miscFeedback_ = feedback;
79 HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE",
80 HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE", "feedback", "STATUS", feedback);
81 MISC_HILOGI("feedback:%{public}d", feedback);
82 int32_t ringerMode = miscAudioRingerMode_;
83 if (GetIntValue(SETTING_RINGER_MODE_KEY, ringerMode) != ERR_OK) {
84 MISC_HILOGE("Get ringerMode failed");
85 }
86 miscAudioRingerMode_ = ringerMode;
87 HiSysEventWrite(HiSysEvent::Domain::MISCDEVICE, "SWITCHES_TOGGLE",
88 HiSysEvent::EventType::BEHAVIOR, "SWITCH_TYPE", "ringerMode", "STATUS", ringerMode);
89 MISC_HILOGI("ringerMode:%{public}d", ringerMode);
90 };
91 auto observer_ = CreateObserver(updateFunc);
92 if (observer_ == nullptr) {
93 MISC_HILOGE("observer is null");
94 return false;
95 }
96 if (RegisterObserver(observer_) != ERR_OK) {
97 MISC_HILOGE("RegisterObserver failed");
98 return false;
99 }
100 return true;
101 }
102
GetIntValue(const std::string & key,int32_t & value)103 int32_t VibrationPriorityManager::GetIntValue(const std::string &key, int32_t &value)
104 {
105 int64_t valueLong;
106 int32_t ret = GetLongValue(key, valueLong);
107 if (ret != ERR_OK) {
108 return ret;
109 }
110 value = static_cast<int32_t>(valueLong);
111 return ERR_OK;
112 }
113
GetLongValue(const std::string & key,int64_t & value)114 int32_t VibrationPriorityManager::GetLongValue(const std::string &key, int64_t &value)
115 {
116 std::string valueStr;
117 int32_t ret = GetStringValue(key, valueStr);
118 if (ret != ERR_OK) {
119 return ret;
120 }
121 value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, DECEM_BASE));
122 return ERR_OK;
123 }
124
GetStringValue(const std::string & key,std::string & value)125 int32_t VibrationPriorityManager::GetStringValue(const std::string &key, std::string &value)
126 {
127 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
128 auto helper = CreateDataShareHelper();
129 if (helper == nullptr) {
130 IPCSkeleton::SetCallingIdentity(callingIdentity);
131 return MISC_NO_INIT_ERR;
132 }
133 std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
134 DataShare::DataSharePredicates predicates;
135 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
136 Uri uri(AssembleUri(key));
137 auto resultSet = helper->Query(uri, predicates, columns);
138 ReleaseDataShareHelper(helper);
139 if (resultSet == nullptr) {
140 MISC_HILOGE("resultSet is nullptr");
141 IPCSkeleton::SetCallingIdentity(callingIdentity);
142 return MISC_INVALID_OPERATION_ERR;
143 }
144 int32_t count;
145 resultSet->GetRowCount(count);
146 if (count == 0) {
147 MISC_HILOGW("Not found value, key:%{public}s, count:%{public}d", key.c_str(), count);
148 IPCSkeleton::SetCallingIdentity(callingIdentity);
149 return MISC_NAME_NOT_FOUND_ERR;
150 }
151 const int32_t index = 0;
152 resultSet->GoToRow(index);
153 int32_t ret = resultSet->GetString(index, value);
154 if (ret != ERR_OK) {
155 MISC_HILOGW("GetString failed, ret:%{public}d", ret);
156 IPCSkeleton::SetCallingIdentity(callingIdentity);
157 return ERROR;
158 }
159 resultSet->Close();
160 IPCSkeleton::SetCallingIdentity(callingIdentity);
161 return ERR_OK;
162 }
163
UpdateStatus()164 void VibrationPriorityManager::UpdateStatus()
165 {
166 if (miscFeedback_ == FEEDBACK_MODE_INVALID) {
167 int32_t feedback = FEEDBACK_MODE_INVALID;
168 if (GetIntValue(SETTING_FEEDBACK_KEY, feedback) != ERR_OK) {
169 feedback = FEEDBACK_MODE_ON;
170 MISC_HILOGE("Get feedback failed");
171 }
172 miscFeedback_ = feedback;
173 }
174 if (miscAudioRingerMode_ == RINGER_MODE_INVALID) {
175 int32_t ringerMode = RINGER_MODE_INVALID;
176 if (GetIntValue(SETTING_RINGER_MODE_KEY, ringerMode) != ERR_OK) {
177 ringerMode = RINGER_MODE_NORMAL;
178 MISC_HILOGE("Get ringerMode failed");
179 }
180 miscAudioRingerMode_ = ringerMode;
181 }
182 }
183
IsSystemServiceCalling()184 bool VibrationPriorityManager::IsSystemServiceCalling()
185 {
186 const auto tokenId = IPCSkeleton::GetCallingTokenID();
187 const auto flag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId);
188 if (flag == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
189 MISC_HILOGD("System service calling, flag: %{public}u", flag);
190 return true;
191 }
192 return false;
193 }
194
IsSystemCalling()195 bool VibrationPriorityManager::IsSystemCalling()
196 {
197 if (IsSystemServiceCalling()) {
198 return true;
199 }
200 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID());
201 }
202
ShouldIgnoreInputMethod(const VibrateInfo & vibrateInfo)203 bool VibrationPriorityManager::ShouldIgnoreInputMethod(const VibrateInfo &vibrateInfo)
204 {
205 if (vibrateInfo.packageName == SCENEBOARD_BUNDLENAME) {
206 MISC_HILOGD("Can not ignore for %{public}s", vibrateInfo.packageName.c_str());
207 return false;
208 }
209 int32_t pid = vibrateInfo.pid;
210 AppExecFwk::RunningProcessInfo processinfo{};
211 appMgrClientPtr_ = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
212 if (appMgrClientPtr_ == nullptr) {
213 MISC_HILOGE("appMgrClientPtr is nullptr");
214 return false;
215 }
216 int32_t ret = appMgrClientPtr_->AppExecFwk::AppMgrClient::GetRunningProcessInfoByPid(pid, processinfo);
217 if (ret != ERR_OK) {
218 MISC_HILOGE("Getrunningprocessinfobypid failed");
219 return false;
220 }
221 if (processinfo.extensionType_ == AppExecFwk::ExtensionAbilityType::INPUTMETHOD) {
222 return true;
223 }
224 std::vector<int32_t> activeUserIds;
225 int retId = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeUserIds);
226 if (retId != 0) {
227 MISC_HILOGE("QueryActiveOsAccountIds failed %{public}d", retId);
228 return false;
229 }
230 if (activeUserIds.empty()) {
231 MISC_HILOGE("activeUserId empty");
232 return false;
233 }
234 for (const auto &bundleName : processinfo.bundleNames) {
235 MISC_HILOGD("bundleName = %{public}s", bundleName.c_str());
236 AppExecFwk::BundleMgrClient bundleMgrClient;
237 AppExecFwk::BundleInfo bundleInfo;
238 auto res = bundleMgrClient.AppExecFwk::BundleMgrClient::GetBundleInfo(bundleName,
239 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, activeUserIds[0]);
240 if (!res) {
241 MISC_HILOGE("Getbundleinfo fail");
242 return false;
243 }
244 for (const auto &extensionInfo : bundleInfo.extensionInfos) {
245 if (extensionInfo.type == AppExecFwk::ExtensionAbilityType::INPUTMETHOD) {
246 MISC_HILOGD("extensioninfo type is %{public}d", extensionInfo.type);
247 return true;
248 }
249 }
250 }
251 return false;
252 }
253
ShouldIgnoreVibrate(const VibrateInfo & vibrateInfo,std::shared_ptr<VibratorThread> vibratorThread)254 VibrateStatus VibrationPriorityManager::ShouldIgnoreVibrate(const VibrateInfo &vibrateInfo,
255 std::shared_ptr<VibratorThread> vibratorThread)
256 {
257 UpdateStatus();
258 if (!IsSystemCalling() || vibrateInfo.systemUsage == false) {
259 if ((vibrateInfo.usage == USAGE_ALARM || vibrateInfo.usage == USAGE_RING
260 || vibrateInfo.usage == USAGE_NOTIFICATION || vibrateInfo.usage == USAGE_COMMUNICATION)
261 && (miscAudioRingerMode_ == RINGER_MODE_SILENT)) {
262 MISC_HILOGD("Vibration is ignored for ringer mode:%{public}d", static_cast<int32_t>(miscAudioRingerMode_));
263 return IGNORE_RINGER_MODE;
264 }
265 if (((vibrateInfo.usage == USAGE_TOUCH || vibrateInfo.usage == USAGE_MEDIA || vibrateInfo.usage == USAGE_UNKNOWN
266 || vibrateInfo.usage == USAGE_PHYSICAL_FEEDBACK || vibrateInfo.usage == USAGE_SIMULATE_REALITY)
267 && (miscFeedback_ == FEEDBACK_MODE_OFF)) && !ShouldIgnoreInputMethod(vibrateInfo)) {
268 MISC_HILOGD("Vibration is ignored for feedback:%{public}d", static_cast<int32_t>(miscFeedback_));
269 return IGNORE_FEEDBACK;
270 }
271 }
272 if (vibratorThread == nullptr) {
273 MISC_HILOGD("There is no vibration, it can vibrate");
274 return VIBRATION;
275 }
276 if (!IsCurrentVibrate(vibratorThread)) {
277 MISC_HILOGD("There is no vibration at the moment, it can vibrate");
278 return VIBRATION;
279 }
280 if (IsLoopVibrate(vibrateInfo)) {
281 MISC_HILOGD("Can vibrate, loop priority is high");
282 return VIBRATION;
283 }
284 return ShouldIgnoreVibrate(vibrateInfo, vibratorThread->GetCurrentVibrateInfo());
285 }
286
IsCurrentVibrate(std::shared_ptr<VibratorThread> vibratorThread) const287 bool VibrationPriorityManager::IsCurrentVibrate(std::shared_ptr<VibratorThread> vibratorThread) const
288 {
289 #if defined(OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM)
290 return ((vibratorThread != nullptr) && (vibratorThread->IsRunning() || VibratorDevice.IsVibratorRunning()));
291 #else
292 return ((vibratorThread != nullptr) && (vibratorThread->IsRunning()));
293 #endif // OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM
294 }
295
IsLoopVibrate(const VibrateInfo & vibrateInfo) const296 bool VibrationPriorityManager::IsLoopVibrate(const VibrateInfo &vibrateInfo) const
297 {
298 return ((vibrateInfo.mode == "preset") && (vibrateInfo.count > 1));
299 }
300
ShouldIgnoreVibrate(const VibrateInfo & vibrateInfo,VibrateInfo currentVibrateInfo) const301 VibrateStatus VibrationPriorityManager::ShouldIgnoreVibrate(const VibrateInfo &vibrateInfo,
302 VibrateInfo currentVibrateInfo) const
303 {
304 if (currentVibrateInfo.usage == USAGE_ALARM) {
305 MISC_HILOGD("Vibration is ignored for alarm");
306 return IGNORE_ALARM;
307 }
308 if (IsLoopVibrate(currentVibrateInfo)) {
309 MISC_HILOGD("Vibration is ignored for repeat");
310 return IGNORE_REPEAT;
311 }
312 if ((currentVibrateInfo.usage != vibrateInfo.usage) && (vibrateInfo.usage == USAGE_UNKNOWN)) {
313 MISC_HILOGD("Vibration is ignored, unknown has a low priority");
314 return IGNORE_UNKNOWN;
315 }
316 return VIBRATION;
317 }
318
CreateObserver(const MiscDeviceObserver::UpdateFunc & func)319 sptr<MiscDeviceObserver> VibrationPriorityManager::CreateObserver(const MiscDeviceObserver::UpdateFunc &func)
320 {
321 sptr<MiscDeviceObserver> observer = new MiscDeviceObserver();
322 if (observer == nullptr) {
323 MISC_HILOGE("observer is null");
324 return observer;
325 }
326 observer->SetUpdateFunc(func);
327 return observer;
328 }
329
AssembleUri(const std::string & key)330 Uri VibrationPriorityManager::AssembleUri(const std::string &key)
331 {
332 Uri uri(SETTING_URI_PROXY + "&key=" + key);
333 return uri;
334 }
335
CreateDataShareHelper()336 std::shared_ptr<DataShare::DataShareHelper> VibrationPriorityManager::CreateDataShareHelper()
337 {
338 if (remoteObj_ == nullptr) {
339 MISC_HILOGE("remoteObj_ is nullptr");
340 return nullptr;
341 }
342 auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj_, SETTING_URI_PROXY, SETTINGS_DATA_EXT_URI);
343 if (ret == DATA_SHARE_READY) {
344 return helper;
345 } else if (ret == DATA_SHARE_NOT_READY) {
346 MISC_HILOGE("Create data_share helper failed, uri proxy:%{public}s", SETTING_URI_PROXY.c_str());
347 return nullptr;
348 }
349 MISC_HILOGI("Data_share create unknown");
350 return nullptr;
351 }
352
ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> & helper)353 bool VibrationPriorityManager::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> &helper)
354 {
355 if (!helper->Release()) {
356 MISC_HILOGW("Release helper fail");
357 return false;
358 }
359 return true;
360 }
361
ExecRegisterCb(const sptr<MiscDeviceObserver> & observer)362 void VibrationPriorityManager::ExecRegisterCb(const sptr<MiscDeviceObserver> &observer)
363 {
364 if (observer == nullptr) {
365 MISC_HILOGE("observer is nullptr");
366 return;
367 }
368 observer->OnChange();
369 }
370
RegisterObserver(const sptr<MiscDeviceObserver> & observer)371 int32_t VibrationPriorityManager::RegisterObserver(const sptr<MiscDeviceObserver> &observer)
372 {
373 if (observer == nullptr) {
374 MISC_HILOGE("observer is nullptr");
375 return MISC_NO_INIT_ERR;
376 }
377 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
378 auto helper = CreateDataShareHelper();
379 if (helper == nullptr) {
380 IPCSkeleton::SetCallingIdentity(callingIdentity);
381 return MISC_NO_INIT_ERR;
382 }
383 auto uriFeedback = AssembleUri(SETTING_FEEDBACK_KEY);
384 helper->RegisterObserver(uriFeedback, observer);
385 helper->NotifyChange(uriFeedback);
386 auto uriRingerMode = AssembleUri(SETTING_RINGER_MODE_KEY);
387 helper->RegisterObserver(uriRingerMode, observer);
388 helper->NotifyChange(uriRingerMode);
389 std::thread execCb(VibrationPriorityManager::ExecRegisterCb, observer);
390 execCb.detach();
391 ReleaseDataShareHelper(helper);
392 IPCSkeleton::SetCallingIdentity(callingIdentity);
393 MISC_HILOGI("Succeed to register observer of uri");
394 return ERR_OK;
395 }
396
UnregisterObserver(const sptr<MiscDeviceObserver> & observer)397 int32_t VibrationPriorityManager::UnregisterObserver(const sptr<MiscDeviceObserver> &observer)
398 {
399 if (observer == nullptr) {
400 MISC_HILOGE("observer is nullptr");
401 return MISC_NO_INIT_ERR;
402 }
403 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
404 auto helper = CreateDataShareHelper();
405 if (helper == nullptr) {
406 IPCSkeleton::SetCallingIdentity(callingIdentity);
407 return MISC_NO_INIT_ERR;
408 }
409 auto uriFeedback = AssembleUri(SETTING_FEEDBACK_KEY);
410 helper->UnregisterObserver(uriFeedback, observer);
411 auto uriRingerMode = AssembleUri(SETTING_RINGER_MODE_KEY);
412 helper->UnregisterObserver(uriRingerMode, observer);
413 ReleaseDataShareHelper(helper);
414 IPCSkeleton::SetCallingIdentity(callingIdentity);
415 MISC_HILOGI("Succeed to unregister observer");
416 return ERR_OK;
417 }
418 } // namespace Sensors
419 } // namespace OHOS