1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "../Macros.h"
18
19 #include "VibratorInputMapper.h"
20
21 namespace android {
22
VibratorInputMapper(InputDeviceContext & deviceContext)23 VibratorInputMapper::VibratorInputMapper(InputDeviceContext& deviceContext)
24 : InputMapper(deviceContext), mVibrating(false) {}
25
~VibratorInputMapper()26 VibratorInputMapper::~VibratorInputMapper() {}
27
getSources()28 uint32_t VibratorInputMapper::getSources() {
29 return 0;
30 }
31
populateDeviceInfo(InputDeviceInfo * info)32 void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
33 InputMapper::populateDeviceInfo(info);
34
35 info->setVibrator(true);
36 }
37
process(const RawEvent * rawEvent)38 void VibratorInputMapper::process(const RawEvent* rawEvent) {
39 // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
40 }
41
vibrate(const nsecs_t * pattern,size_t patternSize,ssize_t repeat,int32_t token)42 void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
43 int32_t token) {
44 #if DEBUG_VIBRATOR
45 std::string patternStr;
46 for (size_t i = 0; i < patternSize; i++) {
47 if (i != 0) {
48 patternStr += ", ";
49 }
50 patternStr += StringPrintf("%" PRId64, pattern[i]);
51 }
52 ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
53 patternStr.c_str(), repeat, token);
54 #endif
55
56 mVibrating = true;
57 memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
58 mPatternSize = patternSize;
59 mRepeat = repeat;
60 mToken = token;
61 mIndex = -1;
62
63 nextStep();
64 }
65
cancelVibrate(int32_t token)66 void VibratorInputMapper::cancelVibrate(int32_t token) {
67 #if DEBUG_VIBRATOR
68 ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
69 #endif
70
71 if (mVibrating && mToken == token) {
72 stopVibrating();
73 }
74 }
75
timeoutExpired(nsecs_t when)76 void VibratorInputMapper::timeoutExpired(nsecs_t when) {
77 if (mVibrating) {
78 if (when >= mNextStepTime) {
79 nextStep();
80 } else {
81 getContext()->requestTimeoutAtTime(mNextStepTime);
82 }
83 }
84 }
85
nextStep()86 void VibratorInputMapper::nextStep() {
87 mIndex += 1;
88 if (size_t(mIndex) >= mPatternSize) {
89 if (mRepeat < 0) {
90 // We are done.
91 stopVibrating();
92 return;
93 }
94 mIndex = mRepeat;
95 }
96
97 bool vibratorOn = mIndex & 1;
98 nsecs_t duration = mPattern[mIndex];
99 if (vibratorOn) {
100 #if DEBUG_VIBRATOR
101 ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
102 #endif
103 getDeviceContext().vibrate(duration);
104 } else {
105 #if DEBUG_VIBRATOR
106 ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
107 #endif
108 getDeviceContext().cancelVibrate();
109 }
110 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
111 mNextStepTime = now + duration;
112 getContext()->requestTimeoutAtTime(mNextStepTime);
113 #if DEBUG_VIBRATOR
114 ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
115 #endif
116 }
117
stopVibrating()118 void VibratorInputMapper::stopVibrating() {
119 mVibrating = false;
120 #if DEBUG_VIBRATOR
121 ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
122 #endif
123 getDeviceContext().cancelVibrate();
124 }
125
dump(std::string & dump)126 void VibratorInputMapper::dump(std::string& dump) {
127 dump += INDENT2 "Vibrator Input Mapper:\n";
128 dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
129 }
130
131 } // namespace android
132