• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,const InputReaderConfiguration & readerConfig)23 VibratorInputMapper::VibratorInputMapper(InputDeviceContext& deviceContext,
24                                          const InputReaderConfiguration& readerConfig)
25       : InputMapper(deviceContext, readerConfig), mVibrating(false), mSequence(0) {}
26 
~VibratorInputMapper()27 VibratorInputMapper::~VibratorInputMapper() {}
28 
getSources() const29 uint32_t VibratorInputMapper::getSources() const {
30     return 0;
31 }
32 
populateDeviceInfo(InputDeviceInfo & info)33 void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
34     InputMapper::populateDeviceInfo(info);
35 
36     info.setVibrator(true);
37 }
38 
process(const RawEvent * rawEvent)39 std::list<NotifyArgs> VibratorInputMapper::process(const RawEvent* rawEvent) {
40     // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
41     return {};
42 }
43 
vibrate(const VibrationSequence & sequence,ssize_t repeat,int32_t token)44 std::list<NotifyArgs> VibratorInputMapper::vibrate(const VibrationSequence& sequence,
45                                                    ssize_t repeat, int32_t token) {
46     if (DEBUG_VIBRATOR) {
47         ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
48               sequence.toString().c_str(), repeat, token);
49     }
50     std::list<NotifyArgs> out;
51 
52     mVibrating = true;
53     mSequence = sequence;
54     mRepeat = repeat;
55     mToken = token;
56     mIndex = -1;
57 
58     // Request InputReader to notify InputManagerService for vibration started.
59     out.push_back(
60             NotifyVibratorStateArgs(getContext()->getNextId(), systemTime(), getDeviceId(), true));
61     out += nextStep();
62     return out;
63 }
64 
cancelVibrate(int32_t token)65 std::list<NotifyArgs> VibratorInputMapper::cancelVibrate(int32_t token) {
66     if (DEBUG_VIBRATOR) {
67         ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
68     }
69     std::list<NotifyArgs> out;
70 
71     if (mVibrating && mToken == token) {
72         out.push_back(stopVibrating());
73     }
74     return out;
75 }
76 
isVibrating()77 bool VibratorInputMapper::isVibrating() {
78     return mVibrating;
79 }
80 
getVibratorIds()81 std::vector<int32_t> VibratorInputMapper::getVibratorIds() {
82     return getDeviceContext().getVibratorIds();
83 }
84 
timeoutExpired(nsecs_t when)85 std::list<NotifyArgs> VibratorInputMapper::timeoutExpired(nsecs_t when) {
86     std::list<NotifyArgs> out;
87     if (mVibrating) {
88         if (when >= mNextStepTime) {
89             out += nextStep();
90         } else {
91             getContext()->requestTimeoutAtTime(mNextStepTime);
92         }
93     }
94     return out;
95 }
96 
nextStep()97 std::list<NotifyArgs> VibratorInputMapper::nextStep() {
98     if (DEBUG_VIBRATOR) {
99         ALOGD("nextStep: index=%d, vibrate deviceId=%d", (int)mIndex, getDeviceId());
100     }
101     std::list<NotifyArgs> out;
102     mIndex += 1;
103     if (size_t(mIndex) >= mSequence.pattern.size()) {
104         if (mRepeat < 0) {
105             // We are done.
106             out.push_back(stopVibrating());
107             return out;
108         }
109         mIndex = mRepeat;
110     }
111 
112     const VibrationElement& element = mSequence.pattern[mIndex];
113     if (element.isOn()) {
114         if (DEBUG_VIBRATOR) {
115             std::string description = element.toString();
116             ALOGD("nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
117                   description.c_str());
118         }
119         getDeviceContext().vibrate(element);
120     } else {
121         if (DEBUG_VIBRATOR) {
122             ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
123         }
124         getDeviceContext().cancelVibrate();
125     }
126     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
127     std::chrono::nanoseconds duration =
128             std::chrono::duration_cast<std::chrono::nanoseconds>(element.duration);
129     mNextStepTime = now + duration.count();
130     getContext()->requestTimeoutAtTime(mNextStepTime);
131     if (DEBUG_VIBRATOR) {
132         ALOGD("nextStep: scheduled timeout in %lldms", element.duration.count());
133     }
134     return out;
135 }
136 
stopVibrating()137 NotifyVibratorStateArgs VibratorInputMapper::stopVibrating() {
138     mVibrating = false;
139     if (DEBUG_VIBRATOR) {
140         ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
141     }
142     getDeviceContext().cancelVibrate();
143 
144     // Request InputReader to notify InputManagerService for vibration complete.
145     return NotifyVibratorStateArgs(getContext()->getNextId(), systemTime(), getDeviceId(), false);
146 }
147 
dump(std::string & dump)148 void VibratorInputMapper::dump(std::string& dump) {
149     dump += INDENT2 "Vibrator Input Mapper:\n";
150     dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
151     if (mVibrating) {
152         dump += INDENT3 "Pattern: ";
153         dump += mSequence.toString();
154         dump += "\n";
155         dump += StringPrintf(INDENT3 "Repeat Index: %zd\n", mRepeat);
156     }
157 }
158 
159 } // namespace android
160