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