• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "miscdevice_service.h"
17 
18 #include <string_ex.h>
19 
20 #include "sensors_errors.h"
21 #include "system_ability_definition.h"
22 #include "vibration_priority_manager.h"
23 #include "v1_0/light_interface_proxy.h"
24 
25 namespace OHOS {
26 namespace Sensors {
27 using namespace OHOS::HiviewDFX;
28 
29 namespace {
30 constexpr HiLogLabel LABEL = { LOG_CORE, MISC_LOG_DOMAIN, "MiscdeviceService" };
31 constexpr int32_t MIN_VIBRATOR_TIME = 0;
32 constexpr int32_t MAX_VIBRATOR_TIME = 1800000;
33 }  // namespace
34 
35 REGISTER_SYSTEM_ABILITY_BY_ID(MiscdeviceService, MISCDEVICE_SERVICE_ABILITY_ID, true);
36 
MiscdeviceService(int32_t systemAbilityId,bool runOnCreate)37 MiscdeviceService::MiscdeviceService(int32_t systemAbilityId, bool runOnCreate)
38     : SystemAbility(systemAbilityId, runOnCreate),
39       lightExist_(false),
40       vibratorExist_(false),
41       state_(MiscdeviceServiceState::STATE_STOPPED),
42       vibratorThread_(nullptr)
43 {}
44 
~MiscdeviceService()45 MiscdeviceService::~MiscdeviceService()
46 {
47     if (vibratorThread_ != nullptr) {
48         while (vibratorThread_->IsRunning()) {
49             vibratorThread_->NotifyExit();
50             vibratorThread_->NotifyExitSync();
51         }
52     }
53 }
54 
OnDump()55 void MiscdeviceService::OnDump()
56 {
57     MISC_HILOGI("ondump is invoked");
58 }
59 
OnStart()60 void MiscdeviceService::OnStart()
61 {
62     CALL_LOG_ENTER;
63     if (state_ == MiscdeviceServiceState::STATE_RUNNING) {
64         MISC_HILOGW("state_ already started");
65         return;
66     }
67     if (!InitInterface()) {
68         MISC_HILOGE("Init interface error");
69         return;
70     }
71     if (!InitLightInterface()) {
72         MISC_HILOGE("InitLightInterface failed");
73         return;
74     }
75     if (!SystemAbility::Publish(this)) {
76         MISC_HILOGE("publish MiscdeviceService failed");
77         return;
78     }
79     auto ret = miscDdeviceIdMap_.insert(std::make_pair(MiscdeviceDeviceId::LED, lightExist_));
80     if (!ret.second) {
81         MISC_HILOGI("light exist in miscDdeviceIdMap_");
82         ret.first->second = lightExist_;
83     }
84     ret = miscDdeviceIdMap_.insert(std::make_pair(MiscdeviceDeviceId::VIBRATOR, vibratorExist_));
85     if (!ret.second) {
86         MISC_HILOGI("vibrator exist in miscDdeviceIdMap_");
87         ret.first->second = vibratorExist_;
88     }
89     state_ = MiscdeviceServiceState::STATE_RUNNING;
90 }
91 
InitInterface()92 bool MiscdeviceService::InitInterface()
93 {
94     auto ret = vibratorHdiConnection_.ConnectHdi();
95     if (ret != ERR_OK) {
96         MISC_HILOGE("InitVibratorServiceImpl failed");
97         return false;
98     }
99     return true;
100 }
101 
InitLightInterface()102 bool MiscdeviceService::InitLightInterface()
103 {
104     auto ret = lightHdiConnection_.ConnectHdi();
105     if (ret != ERR_OK) {
106         MISC_HILOGE("ConnectHdi failed");
107         return false;
108     }
109     return true;
110 }
111 
IsValid(int32_t lightId)112 bool MiscdeviceService::IsValid(int32_t lightId)
113 {
114     CALL_LOG_ENTER;
115     for (const auto &item : lightInfos_) {
116         if (lightId == item.lightId) {
117             return true;
118         }
119     }
120     return false;
121 }
122 
IsLightAnimationValid(const LightAnimation & animation)123 bool MiscdeviceService::IsLightAnimationValid(const LightAnimation &animation)
124 {
125     if ((animation.mode < 0) || (animation.mode >= LIGHT_MODE_BUTT)) {
126         MISC_HILOGE("animation mode is invalid, mode:%{pubilc}d", animation.mode);
127         return false;
128     }
129     if ((animation.onTime < 0) || (animation.offTime < 0)) {
130         MISC_HILOGE("animation onTime or offTime is invalid, onTime:%{pubilc}d, offTime:%{pubilc}d",
131             animation.onTime, animation.offTime);
132         return false;
133     }
134     return true;
135 }
136 
OnStop()137 void MiscdeviceService::OnStop()
138 {
139     CALL_LOG_ENTER;
140     if (state_ == MiscdeviceServiceState::STATE_STOPPED) {
141         MISC_HILOGW("MiscdeviceService stopped already");
142         return;
143     }
144     state_ = MiscdeviceServiceState::STATE_STOPPED;
145     int32_t ret = vibratorHdiConnection_.DestroyHdiConnection();
146     if (ret != ERR_OK) {
147         MISC_HILOGE("destroy hdi connection fail");
148     }
149 }
150 
151 
ShouldIgnoreVibrate(const VibrateInfo & info)152 bool MiscdeviceService::ShouldIgnoreVibrate(const VibrateInfo &info)
153 {
154     return (PriorityManager->ShouldIgnoreVibrate(info, vibratorThread_) != VIBRATION);
155 }
156 
Vibrate(int32_t vibratorId,int32_t timeOut,int32_t usage)157 int32_t MiscdeviceService::Vibrate(int32_t vibratorId, int32_t timeOut, int32_t usage)
158 {
159     if ((timeOut <= MIN_VIBRATOR_TIME) || (timeOut > MAX_VIBRATOR_TIME)
160         || (usage >= USAGE_MAX) || (usage < 0)) {
161         MISC_HILOGE("Invalid parameter");
162         return PARAMETER_ERROR;
163     }
164     VibrateInfo info = {
165         .mode = "time",
166         .packageName = GetPackageName(GetCallingTokenID()),
167         .pid = GetCallingPid(),
168         .uid = GetCallingUid(),
169         .usage = usage,
170         .duration = timeOut
171     };
172     std::lock_guard<std::mutex> lock(vibratorThreadMutex_);
173     if (ShouldIgnoreVibrate(info)) {
174         MISC_HILOGE("Vibration is ignored and high priority is vibrating");
175         return ERROR;
176     }
177     StartVibrateThread(info);
178     return NO_ERROR;
179 }
180 
CancelVibrator(int32_t vibratorId)181 int32_t MiscdeviceService::CancelVibrator(int32_t vibratorId)
182 {
183     std::lock_guard<std::mutex> lock(vibratorThreadMutex_);
184     if ((vibratorThread_ == nullptr) || (!vibratorThread_->IsRunning())) {
185         MISC_HILOGE("No vibration, no need to stop");
186         return ERROR;
187     }
188     while (vibratorThread_->IsRunning()) {
189         MISC_HILOGD("Notify the vibratorThread, vibratorId : %{public}d", vibratorId);
190         vibratorThread_->NotifyExit();
191         vibratorThread_->NotifyExitSync();
192     }
193     return NO_ERROR;
194 }
195 
PlayVibratorEffect(int32_t vibratorId,const std::string & effect,int32_t count,int32_t usage)196 int32_t MiscdeviceService::PlayVibratorEffect(int32_t vibratorId, const std::string &effect,
197     int32_t count, int32_t usage)
198 {
199     if ((vibratorEffects.find(effect) == vibratorEffects.end()) || (count < 1)
200         || (usage >= USAGE_MAX) || (usage < 0)) {
201         MISC_HILOGE("Invalid parameter");
202         return PARAMETER_ERROR;
203     }
204     VibrateInfo info = {
205         .mode = "preset",
206         .packageName = GetPackageName(GetCallingTokenID()),
207         .pid = GetCallingPid(),
208         .uid = GetCallingUid(),
209         .usage = usage,
210         .duration = vibratorEffects[effect],
211         .effect = effect,
212         .count = count
213     };
214     std::lock_guard<std::mutex> lock(vibratorThreadMutex_);
215     if (ShouldIgnoreVibrate(info)) {
216         MISC_HILOGE("Vibration is ignored and high priority is vibrating");
217         return ERROR;
218     }
219     StartVibrateThread(info);
220     return NO_ERROR;
221 }
222 
StartVibrateThread(VibrateInfo info)223 void MiscdeviceService::StartVibrateThread(VibrateInfo info)
224 {
225     if (vibratorThread_ == nullptr) {
226         vibratorThread_ = std::make_shared<VibratorThread>();
227     }
228     while (vibratorThread_->IsRunning()) {
229         vibratorThread_->NotifyExit();
230         vibratorThread_->NotifyExitSync();
231     }
232     vibratorThread_->UpdateVibratorEffect(info);
233     vibratorThread_->Start("VibratorThread");
234     DumpHelper->SaveVibrateRecord(info);
235 }
236 
StopVibratorEffect(int32_t vibratorId,const std::string & effect)237 int32_t MiscdeviceService::StopVibratorEffect(int32_t vibratorId, const std::string &effect)
238 {
239     std::lock_guard<std::mutex> lock(vibratorThreadMutex_);
240     if ((vibratorThread_ == nullptr) || (!vibratorThread_->IsRunning())) {
241         MISC_HILOGE("No vibration, no need to stop");
242         return ERROR;
243     }
244     const VibrateInfo info = vibratorThread_->GetCurrentVibrateInfo();
245     if ((info.mode != effect) || (info.pid != GetCallingPid())) {
246         MISC_HILOGE("Stop vibration information mismatch");
247         return ERROR;
248     }
249     while (vibratorThread_->IsRunning()) {
250         MISC_HILOGD("notify the vibratorThread, vibratorId : %{public}d", vibratorId);
251         vibratorThread_->NotifyExit();
252         vibratorThread_->NotifyExitSync();
253     }
254     return NO_ERROR;
255 }
256 
GetPackageName(AccessTokenID tokenId)257 std::string MiscdeviceService::GetPackageName(AccessTokenID tokenId)
258 {
259     std::string packageName;
260     int32_t tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId);
261     switch (tokenType) {
262         case ATokenTypeEnum::TOKEN_HAP: {
263             HapTokenInfo hapInfo;
264             if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != 0) {
265                 MISC_HILOGE("get hap token info fail");
266                 return {};
267             }
268             packageName = hapInfo.bundleName;
269             break;
270         }
271         case ATokenTypeEnum::TOKEN_NATIVE:
272         case ATokenTypeEnum::TOKEN_SHELL: {
273             NativeTokenInfo tokenInfo;
274             if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) != 0) {
275                 MISC_HILOGE("get native token info fail");
276                 return {};
277             }
278             packageName = tokenInfo.processName;
279             break;
280         }
281         default: {
282             MISC_HILOGW("token type not match");
283             break;
284         }
285     }
286     return packageName;
287 }
288 
GetLightList()289 std::vector<LightInfo> MiscdeviceService::GetLightList()
290 {
291     if (!InitLightList()) {
292         MISC_HILOGE("InitLightList init failed");
293         return lightInfos_;
294     }
295     return lightInfos_;
296 }
297 
InitLightList()298 bool MiscdeviceService::InitLightList()
299 {
300     int32_t ret = lightHdiConnection_.GetLightList(lightInfos_);
301     if (ret != ERR_OK) {
302         MISC_HILOGE("InitLightList failed, ret:%{public}d", ret);
303         return false;
304     }
305     return true;
306 }
307 
TurnOn(int32_t lightId,const LightColor & color,const LightAnimation & animation)308 int32_t MiscdeviceService::TurnOn(int32_t lightId, const LightColor &color, const LightAnimation &animation)
309 {
310     CALL_LOG_ENTER;
311     if (!IsValid(lightId)) {
312         MISC_HILOGE("lightId is invalid, lightId:%{pubilc}d", lightId);
313         return MISCDEVICE_NATIVE_SAM_ERR;
314     }
315     if (!IsLightAnimationValid(animation)) {
316         MISC_HILOGE("animation is invalid");
317         return MISCDEVICE_NATIVE_SAM_ERR;
318     }
319     int32_t ret = lightHdiConnection_.TurnOn(lightId, color, animation);
320     if (ret != ERR_OK) {
321         MISC_HILOGE("TurnOn failed, error:%{public}d", ret);
322         return ERROR;
323     }
324     return ret;
325 }
326 
TurnOff(int32_t lightId)327 int32_t MiscdeviceService::TurnOff(int32_t lightId)
328 {
329     CALL_LOG_ENTER;
330     if (!IsValid(lightId)) {
331         MISC_HILOGE("lightId is invalid, lightId:%{pubilc}d", lightId);
332         return MISCDEVICE_NATIVE_SAM_ERR;
333     }
334     int32_t ret = lightHdiConnection_.TurnOff(lightId);
335     if (ret != ERR_OK) {
336         MISC_HILOGE("TurnOff failed, error:%{public}d", ret);
337         return ERROR;
338     }
339     return ret;
340 }
341 
Dump(int32_t fd,const std::vector<std::u16string> & args)342 int32_t MiscdeviceService::Dump(int32_t fd, const std::vector<std::u16string> &args)
343 {
344     CALL_LOG_ENTER;
345     if (fd < 0) {
346         MISC_HILOGE("Invalid fd");
347         return DUMP_PARAM_ERR;
348     }
349     if (args.empty()) {
350         MISC_HILOGE("args cannot be empty");
351         dprintf(fd, "args cannot be empty\n");
352         DumpHelper->DumpHelp(fd);
353         return DUMP_PARAM_ERR;
354     }
355     std::vector<std::string> argList = { "" };
356     std::transform(args.begin(), args.end(), std::back_inserter(argList),
357         [](const std::u16string &arg) {
358         return Str16ToStr8(arg);
359     });
360     DumpHelper->ParseCommand(fd, argList);
361     return ERR_OK;
362 }
363 }  // namespace Sensors
364 }  // namespace OHOS
365