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