OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.content.browser; | |
6 | |
7 import android.content.Context; | |
8 import android.hardware.input.InputManager; | |
9 import android.hardware.input.InputManager.InputDeviceListener; | |
10 import android.view.InputDevice; | |
11 import android.view.InputEvent; | |
12 import android.view.KeyEvent; | |
13 import android.view.MotionEvent; | |
14 | |
15 import org.chromium.base.CalledByNative; | |
16 import org.chromium.base.JNINamespace; | |
17 import org.chromium.base.ThreadUtils; | |
18 | |
19 /* | |
20 * Class to manage connected gamepad devices list. | |
21 */ | |
22 @JNINamespace("content") | |
23 class GamepadList implements InputDeviceListener { | |
24 private static final int MAX_GAMEPADS = 4; | |
25 private GamepadDevice[] mGamepadDevices = new GamepadDevice[MAX_GAMEPADS]; | |
26 private boolean mIsGamepadAccessed = false; | |
27 private final Object mLock = new Object(); | |
28 private InputManager mInputManager; | |
29 private int mAttachedToWindowCounter; | |
30 | |
31 private GamepadList() {} | |
32 | |
33 private void initializeDevices() { | |
34 // Get list of all the attached input devices. | |
35 int[] deviceIds = mInputManager.getInputDeviceIds(); | |
36 for (int i = 0; i < deviceIds.length; i++) { | |
37 InputDevice inputDevice = InputDevice.getDevice(deviceIds[i]); | |
38 // Check for gamepad device | |
39 if (isGamepadDevice(inputDevice)) { | |
40 // Register a new gamepad device. | |
41 registerGamepad(inputDevice); | |
42 } | |
43 } | |
44 } | |
45 | |
46 private static GamepadList sGamepadList = null; | |
47 | |
48 public static void onAttachedToWindow(Context context) { | |
49 assert ThreadUtils.runningOnUiThread(); | |
50 createInstance(); | |
51 sGamepadList.attachedToWindow(context); | |
52 } | |
53 | |
54 private void attachedToWindow(Context context) { | |
55 if (mAttachedToWindowCounter++ == 0) { | |
56 mInputManager = (InputManager) context.getSystemService(Context.INP UT_SERVICE); | |
57 synchronized (mLock) { | |
58 initializeDevices(); | |
59 } | |
60 // Register an input device listener. | |
61 mInputManager.registerInputDeviceListener(this, null); | |
62 } | |
63 } | |
64 | |
65 public static void onDetachedFromWindow() { | |
66 assert ThreadUtils.runningOnUiThread(); | |
67 sGamepadList.detachedFromWindow(); | |
68 } | |
69 | |
70 private void detachedFromWindow() { | |
71 if (--mAttachedToWindowCounter == 0) { | |
72 synchronized (mLock) { | |
73 for (int i = 0; i < MAX_GAMEPADS; ++i) { | |
74 mGamepadDevices[i] = null; | |
75 } | |
76 } | |
77 mInputManager.unregisterInputDeviceListener(this); | |
78 mInputManager = null; | |
79 } | |
80 } | |
81 | |
82 // Override InputDeviceListener methods | |
83 @Override | |
84 public void onInputDeviceChanged(int deviceId) { | |
85 } | |
86 | |
87 @Override | |
88 public void onInputDeviceRemoved(int deviceId) { | |
89 synchronized (mLock) { | |
90 unregisterGamepad(deviceId); | |
91 } | |
92 } | |
93 | |
94 @Override | |
95 public void onInputDeviceAdded(int deviceId) { | |
96 InputDevice inputDevice = InputDevice.getDevice(deviceId); | |
97 if(!isGamepadDevice(inputDevice)) return; | |
98 synchronized (mLock) { | |
99 registerGamepad(inputDevice); | |
100 } | |
101 } | |
102 | |
103 public static void createInstance() { | |
104 if (sGamepadList == null) { | |
105 sGamepadList = new GamepadList(); | |
106 } | |
107 } | |
108 | |
109 private int getDeviceCount() { | |
110 int count = 0; | |
111 for (int i = 0; i < MAX_GAMEPADS; ++i) { | |
112 if (getDevice(i) != null) { | |
113 count++; | |
114 } | |
115 } | |
116 return count; | |
117 } | |
118 | |
119 private boolean isDeviceConnected(int index) { | |
120 if (index < MAX_GAMEPADS && getDevice(index) != null) { | |
121 return true; | |
122 } | |
123 return false; | |
124 } | |
125 | |
126 private GamepadDevice getDeviceById(int deviceId) { | |
127 for (int i = 0; i < MAX_GAMEPADS; ++i) { | |
128 GamepadDevice gamepad = mGamepadDevices[i]; | |
129 if (gamepad != null && gamepad.getId() == deviceId) { | |
130 return gamepad; | |
131 } | |
132 } | |
133 return null; | |
134 } | |
135 | |
136 private GamepadDevice getDevice(int index) { | |
137 // Maximum 4 Gamepads can be connected at a time starting at index zero. | |
138 assert index >= 0 && index < MAX_GAMEPADS; | |
139 return mGamepadDevices[index]; | |
140 } | |
141 | |
142 public static boolean dispatchKeyEvent(KeyEvent event) { | |
143 if (!isGamepadEvent(event)) return false; | |
144 return sGamepadList.updateForEvent(event); | |
145 } | |
146 | |
147 private static boolean updateForEvent(KeyEvent event) { | |
148 synchronized (sGamepadList.mLock) { | |
149 if (!sGamepadList.mIsGamepadAccessed) return false; | |
150 GamepadDevice gamepad = sGamepadList.getGamepadForEvent(event); | |
151 if (gamepad != null) { | |
152 return gamepad.updateForEvent(event); | |
153 } | |
154 return false; | |
155 } | |
156 } | |
157 | |
158 public static boolean onGenericMotionEvent(MotionEvent event) { | |
159 if (!isGamepadEvent(event)) return false; | |
160 return sGamepadList.updateForEvent(event); | |
161 } | |
162 | |
163 private static boolean updateForEvent(MotionEvent event) { | |
164 synchronized (sGamepadList.mLock) { | |
165 if (!sGamepadList.mIsGamepadAccessed) return false; | |
166 GamepadDevice gamepad = sGamepadList.getGamepadForEvent(event); | |
167 if (gamepad != null) { | |
jdduke (slow)
2014/03/26 16:37:58
if (gamepad == null) return false;
return gamepad.
SaurabhK
2014/03/27 13:32:31
On 2014/03/26 16:37:58, jdduke wrote:
Done.
| |
168 return gamepad.updateForEvent(event); | |
169 } | |
170 return false; | |
171 } | |
172 } | |
173 | |
174 private int getNextAvailableIndex() { | |
175 // When multiple gamepads are connected to a user agent, indices must be assigned on a | |
176 // first-come first-serve basis, starting at zero. If a gamepad is disco nnected, previously | |
177 // assigned indices must not be reassigned to gamepads that continue to be connected. | |
178 // However, if a gamepad is disconnected, and subsequently the same or a different | |
179 // gamepad is then connected, index entries must be reused. | |
180 | |
181 for (int i = 0; i < MAX_GAMEPADS; ++i) { | |
182 if (getDevice(i) == null) { | |
183 return i; | |
184 } | |
185 } | |
186 // Reached maximum gamepads limit. | |
187 return -1; | |
188 } | |
189 | |
190 private boolean registerGamepad(InputDevice inputDevice) { | |
191 int index = getNextAvailableIndex(); | |
192 if (index == -1) { | |
193 return false; // invalid index | |
194 } | |
195 | |
196 GamepadDevice gamepad = new GamepadDevice(index, inputDevice); | |
197 mGamepadDevices[index] = gamepad; | |
198 return true; | |
199 } | |
200 | |
201 private void unregisterGamepad(int deviceId) { | |
202 GamepadDevice gamepadDevice = getDeviceById(deviceId); | |
203 if (gamepadDevice == null) { | |
jdduke (slow)
2014/03/26 16:37:58
Nit: No braces, return on same line.
SaurabhK
2014/03/27 13:32:31
On 2014/03/26 16:37:58, jdduke wrote:
Done.
| |
204 return; // Not a registered device. | |
205 } | |
206 int index = gamepadDevice.getIndex(); | |
207 mGamepadDevices[index] = null; | |
208 } | |
209 | |
210 private static boolean isGamepadDevice(InputDevice inputDevice) { | |
211 int sources = inputDevice.getSources(); | |
212 if ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JO YSTICK ) { | |
213 //Found gamepad device | |
214 return true; | |
215 } | |
216 return false; | |
217 } | |
218 | |
219 private GamepadDevice getGamepadForEvent(InputEvent event) { | |
220 int deviceId = event.getDeviceId(); | |
221 GamepadDevice gamepad = getDeviceById(deviceId); | |
222 return gamepad; | |
223 } | |
224 | |
225 private static boolean isGamepadEvent(MotionEvent event) { | |
226 if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOU RCE_JOYSTICK) { | |
jdduke (slow)
2014/03/26 16:37:58
Just
return (event.getSource() & InputDevice.SOU
SaurabhK
2014/03/27 13:32:31
On 2014/03/26 16:37:58, jdduke wrote:
Done.
| |
227 return true; | |
228 } | |
229 return false; | |
230 } | |
231 | |
232 // Returns true if event's keycode corresponds to a gamepad key. | |
233 // Specific handling for dpad keys is required because | |
234 // KeyEvent.isGamepadButton doesn't consider dpad keys. | |
235 private static boolean isGamepadEvent(KeyEvent event) { | |
236 int keyCode = event.getKeyCode(); | |
237 switch (keyCode) { | |
238 case KeyEvent.KEYCODE_DPAD_UP: | |
239 case KeyEvent.KEYCODE_DPAD_DOWN: | |
240 case KeyEvent.KEYCODE_DPAD_LEFT: | |
241 case KeyEvent.KEYCODE_DPAD_RIGHT: | |
242 return true; | |
243 default: | |
244 return KeyEvent.isGamepadButton(keyCode); | |
245 } | |
246 } | |
247 | |
248 @CalledByNative | |
249 static void getGamepadData(long gamepads) { | |
250 assert sGamepadList != null; | |
251 sGamepadList.grabGamepadData(gamepads); | |
252 } | |
253 | |
254 private void grabGamepadData(long gamepads) { | |
255 synchronized (mLock) { | |
256 for (int i = 0; i < MAX_GAMEPADS; i++) { | |
257 final GamepadDevice device = getDevice(i); | |
258 if (device != null && device.hasDeviceBeenInteractedWith()) { | |
kbalazs
2014/03/26 19:24:53
The gesture check (a la hasBeenInteractedWith()) i
SaurabhK
2014/03/27 13:32:31
On 2014/03/26 19:24:53, kbalazs wrote:
Correctly
| |
259 device.mapButtonsAndAxes(); | |
260 nativeSetGamepadData(gamepads, i, device.getMapping(), true, | |
261 device.getName(), device.getTimestamp() , device.getAxes(), | |
262 device.getButtons()); | |
263 } | |
264 else | |
265 nativeSetGamepadData(gamepads, i, null, false, null, 0, null , null); | |
266 } | |
267 } | |
268 } | |
269 | |
270 @CalledByNative | |
271 static void notifyForGamepadsAccess(boolean isaccesspaused) { | |
272 assert sGamepadList != null; | |
273 synchronized (sGamepadList.mLock) { | |
274 sGamepadList.mIsGamepadAccessed = !isaccesspaused; | |
275 if (isaccesspaused) { | |
276 for (int i = 0; i < MAX_GAMEPADS; i++) { | |
277 GamepadDevice gamepadDevice = sGamepadList.getDevice(i); | |
278 if(gamepadDevice != null) | |
279 gamepadDevice.clearData(); | |
jdduke (slow)
2014/03/26 16:37:58
Nit:
if (gamepadDevice == null) continue;
gamepad
SaurabhK
2014/03/27 13:32:31
On 2014/03/26 16:37:58, jdduke wrote:
Done.
| |
280 } | |
281 } | |
282 } | |
283 } | |
284 | |
285 private native void nativeSetGamepadData(long gamepads, | |
286 int index, | |
287 String mapping, | |
288 boolean connected, | |
289 String devicename, | |
290 long timestamp, | |
291 float[] axes, | |
292 float[] buttons); | |
293 | |
294 } | |
OLD | NEW |