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 "TouchButtonAccumulator.h"
18 
19 #include "EventHub.h"
20 #include "InputDevice.h"
21 
22 namespace android {
23 
configure()24 void TouchButtonAccumulator::configure() {
25     mHaveBtnTouch = mDeviceContext.hasScanCode(BTN_TOUCH);
26     mHaveStylus = mDeviceContext.hasScanCode(BTN_TOOL_PEN) ||
27             mDeviceContext.hasScanCode(BTN_TOOL_RUBBER) ||
28             mDeviceContext.hasScanCode(BTN_TOOL_BRUSH) ||
29             mDeviceContext.hasScanCode(BTN_TOOL_PENCIL) ||
30             mDeviceContext.hasScanCode(BTN_TOOL_AIRBRUSH);
31 }
32 
reset()33 void TouchButtonAccumulator::reset() {
34     mBtnTouch = mDeviceContext.isKeyPressed(BTN_TOUCH);
35     mBtnStylus = mDeviceContext.isKeyPressed(BTN_STYLUS) ||
36             mDeviceContext.isKeyCodePressed(AKEYCODE_STYLUS_BUTTON_PRIMARY);
37     // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
38     mBtnStylus2 = mDeviceContext.isKeyPressed(BTN_STYLUS2) || mDeviceContext.isKeyPressed(BTN_0) ||
39             mDeviceContext.isKeyCodePressed(AKEYCODE_STYLUS_BUTTON_SECONDARY);
40     mBtnToolFinger = mDeviceContext.isKeyPressed(BTN_TOOL_FINGER);
41     mBtnToolPen = mDeviceContext.isKeyPressed(BTN_TOOL_PEN);
42     mBtnToolRubber = mDeviceContext.isKeyPressed(BTN_TOOL_RUBBER);
43     mBtnToolBrush = mDeviceContext.isKeyPressed(BTN_TOOL_BRUSH);
44     mBtnToolPencil = mDeviceContext.isKeyPressed(BTN_TOOL_PENCIL);
45     mBtnToolAirbrush = mDeviceContext.isKeyPressed(BTN_TOOL_AIRBRUSH);
46     mBtnToolMouse = mDeviceContext.isKeyPressed(BTN_TOOL_MOUSE);
47     mBtnToolLens = mDeviceContext.isKeyPressed(BTN_TOOL_LENS);
48     mBtnToolDoubleTap = mDeviceContext.isKeyPressed(BTN_TOOL_DOUBLETAP);
49     mBtnToolTripleTap = mDeviceContext.isKeyPressed(BTN_TOOL_TRIPLETAP);
50     mBtnToolQuadTap = mDeviceContext.isKeyPressed(BTN_TOOL_QUADTAP);
51     mBtnToolQuintTap = mDeviceContext.isKeyPressed(BTN_TOOL_QUINTTAP);
52     mHidUsageAccumulator.reset();
53 }
54 
process(const RawEvent & rawEvent)55 void TouchButtonAccumulator::process(const RawEvent& rawEvent) {
56     mHidUsageAccumulator.process(rawEvent);
57 
58     if (rawEvent.type == EV_KEY) {
59         switch (rawEvent.code) {
60             case BTN_TOUCH:
61                 mBtnTouch = rawEvent.value;
62                 break;
63             case BTN_STYLUS:
64                 mBtnStylus = rawEvent.value;
65                 break;
66             case BTN_STYLUS2:
67             case BTN_0: // BTN_0 is what gets mapped for the HID usage
68                         // Digitizers.SecondaryBarrelSwitch
69                 mBtnStylus2 = rawEvent.value;
70                 break;
71             case BTN_TOOL_FINGER:
72                 mBtnToolFinger = rawEvent.value;
73                 break;
74             case BTN_TOOL_PEN:
75                 mBtnToolPen = rawEvent.value;
76                 break;
77             case BTN_TOOL_RUBBER:
78                 mBtnToolRubber = rawEvent.value;
79                 break;
80             case BTN_TOOL_BRUSH:
81                 mBtnToolBrush = rawEvent.value;
82                 break;
83             case BTN_TOOL_PENCIL:
84                 mBtnToolPencil = rawEvent.value;
85                 break;
86             case BTN_TOOL_AIRBRUSH:
87                 mBtnToolAirbrush = rawEvent.value;
88                 break;
89             case BTN_TOOL_MOUSE:
90                 mBtnToolMouse = rawEvent.value;
91                 break;
92             case BTN_TOOL_LENS:
93                 mBtnToolLens = rawEvent.value;
94                 break;
95             case BTN_TOOL_DOUBLETAP:
96                 mBtnToolDoubleTap = rawEvent.value;
97                 break;
98             case BTN_TOOL_TRIPLETAP:
99                 mBtnToolTripleTap = rawEvent.value;
100                 break;
101             case BTN_TOOL_QUADTAP:
102                 mBtnToolQuadTap = rawEvent.value;
103                 break;
104             case BTN_TOOL_QUINTTAP:
105                 mBtnToolQuintTap = rawEvent.value;
106                 break;
107             default:
108                 processMappedKey(rawEvent.code, rawEvent.value);
109         }
110         return;
111     }
112 }
113 
processMappedKey(int32_t scanCode,bool down)114 void TouchButtonAccumulator::processMappedKey(int32_t scanCode, bool down) {
115     int32_t keyCode, metaState;
116     uint32_t flags;
117     if (mDeviceContext.mapKey(scanCode, mHidUsageAccumulator.consumeCurrentHidUsage(),
118                               /*metaState=*/0, &keyCode, &metaState, &flags) != OK) {
119         return;
120     }
121     switch (keyCode) {
122         case AKEYCODE_STYLUS_BUTTON_PRIMARY:
123             mBtnStylus = down;
124             break;
125         case AKEYCODE_STYLUS_BUTTON_SECONDARY:
126             mBtnStylus2 = down;
127             break;
128         default:
129             break;
130     }
131 }
132 
getButtonState() const133 uint32_t TouchButtonAccumulator::getButtonState() const {
134     uint32_t result = 0;
135     if (mBtnStylus) {
136         result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
137     }
138     if (mBtnStylus2) {
139         result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
140     }
141     return result;
142 }
143 
getToolType() const144 ToolType TouchButtonAccumulator::getToolType() const {
145     if (mBtnToolMouse || mBtnToolLens) {
146         return ToolType::MOUSE;
147     }
148     if (mBtnToolRubber) {
149         return ToolType::ERASER;
150     }
151     if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
152         return ToolType::STYLUS;
153     }
154     if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap ||
155         mBtnToolQuintTap) {
156         return ToolType::FINGER;
157     }
158     return ToolType::UNKNOWN;
159 }
160 
isToolActive() const161 bool TouchButtonAccumulator::isToolActive() const {
162     return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber || mBtnToolBrush ||
163             mBtnToolPencil || mBtnToolAirbrush || mBtnToolMouse || mBtnToolLens ||
164             mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap || mBtnToolQuintTap;
165 }
166 
isHovering() const167 bool TouchButtonAccumulator::isHovering() const {
168     return mHaveBtnTouch && !mBtnTouch;
169 }
170 
hasStylus() const171 bool TouchButtonAccumulator::hasStylus() const {
172     return mHaveStylus;
173 }
174 
hasButtonTouch() const175 bool TouchButtonAccumulator::hasButtonTouch() const {
176     return mHaveBtnTouch;
177 }
178 
getTouchCount() const179 int TouchButtonAccumulator::getTouchCount() const {
180     if (mBtnTouch) {
181         if (mBtnToolQuintTap) return 5;
182         if (mBtnToolQuadTap) return 4;
183         if (mBtnToolTripleTap) return 3;
184         if (mBtnToolDoubleTap) return 2;
185         if (mBtnToolFinger) return 1;
186     }
187     return 0;
188 }
189 
190 } // namespace android
191