Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/input/GamepadList.java

Issue 133943002: Gamepad API support for chrome on android (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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.input;
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 * It is a Java counterpart of GamepadPlatformDataFetcherAndroid and feeds Gamep ad API with input
23 * data.
24 */
25 @JNINamespace("content")
26 public class GamepadList implements InputDeviceListener {
27 private static final int MAX_GAMEPADS = 4;
28
29 private static GamepadList sGamepadList = null;
jdduke (slow) 2014/05/12 15:25:35 It looks like we're initializing this variable on
30
31 private final Object mLock = new Object();
32
33 private final GamepadDevice[] mGamepadDevices = new GamepadDevice[MAX_GAMEPA DS];
34 private InputManager mInputManager;
35 private int mAttachedToWindowCounter;
36 private boolean mIsGamepadAccessed;
37
38 private GamepadList() {}
39
40 private void initializeDevices() {
41 // Get list of all the attached input devices.
42 int[] deviceIds = mInputManager.getInputDeviceIds();
43 for (int i = 0; i < deviceIds.length; i++) {
44 InputDevice inputDevice = InputDevice.getDevice(deviceIds[i]);
45 // Check for gamepad device
46 if (isGamepadDevice(inputDevice)) {
47 // Register a new gamepad device.
48 registerGamepad(inputDevice);
49 }
50 }
51 }
52
53 /**
54 * Notifies the GamepadList that a {@link ContentView} is attached to a wind ow and it should
55 * prepare itself for gamepad input. It must be called before {@link onGener icMotionEvent} and
56 * {@link dispatchKeyEvent}.
57 */
58 public static void onAttachedToWindow(Context context) {
59 assert ThreadUtils.runningOnUiThread();
60 createInstance();
61 sGamepadList.attachedToWindow(context);
62 }
63
64 private void attachedToWindow(Context context) {
65 if (mAttachedToWindowCounter++ == 0) {
66 mInputManager = (InputManager) context.getSystemService(Context.INPU T_SERVICE);
67 synchronized (mLock) {
68 initializeDevices();
69 }
70 // Register an input device listener.
71 mInputManager.registerInputDeviceListener(this, null);
72 }
73 }
74
75 /**
76 * Notifies the GamepadList that a {@link ContentView} is detached from it's window.
77 */
78 public static void onDetachedFromWindow() {
79 assert ThreadUtils.runningOnUiThread();
80 sGamepadList.detachedFromWindow();
81 }
82
83 private void detachedFromWindow() {
84 if (--mAttachedToWindowCounter == 0) {
85 synchronized (mLock) {
86 for (int i = 0; i < MAX_GAMEPADS; ++i) {
87 mGamepadDevices[i] = null;
88 }
89 }
90 mInputManager.unregisterInputDeviceListener(this);
91 mInputManager = null;
92 }
93 }
94
95 // ------------------------------------------------------------
96
97 // Override InputDeviceListener methods
98 @Override
99 public void onInputDeviceChanged(int deviceId) {
100 }
101
102 @Override
103 public void onInputDeviceRemoved(int deviceId) {
104 synchronized (mLock) {
105 unregisterGamepad(deviceId);
106 }
107 }
108
109 @Override
110 public void onInputDeviceAdded(int deviceId) {
111 InputDevice inputDevice = InputDevice.getDevice(deviceId);
112 if (!isGamepadDevice(inputDevice)) return;
113 synchronized (mLock) {
114 registerGamepad(inputDevice);
115 }
116 }
117
118 // ------------------------------------------------------------
119
120 private static void createInstance() {
121 if (sGamepadList == null) {
122 sGamepadList = new GamepadList();
123 }
124 }
125
126 private int getDeviceCount() {
127 int count = 0;
128 for (int i = 0; i < MAX_GAMEPADS; i++) {
129 if (getDevice(i) != null) {
130 count++;
131 }
132 }
133 return count;
134 }
135
136 private boolean isDeviceConnected(int index) {
137 if (index < MAX_GAMEPADS && getDevice(index) != null) {
138 return true;
139 }
140 return false;
141 }
142
143 private GamepadDevice getDeviceById(int deviceId) {
144 for (int i = 0; i < MAX_GAMEPADS; i++) {
145 GamepadDevice gamepad = mGamepadDevices[i];
146 if (gamepad != null && gamepad.getId() == deviceId) {
147 return gamepad;
148 }
149 }
150 return null;
151 }
152
153 private GamepadDevice getDevice(int index) {
154 // Maximum 4 Gamepads can be connected at a time starting at index zero.
155 assert index >= 0 && index < MAX_GAMEPADS;
156 return mGamepadDevices[index];
157 }
158
159 /**
160 * Handles key events from the gamepad devices.
161 * @return True if the event has been consumed.
162 */
163 public static boolean dispatchKeyEvent(KeyEvent event) {
164 if (!isGamepadEvent(event)) return false;
165 return sGamepadList.handleKeyEvent(event);
166 }
167
168 private boolean handleKeyEvent(KeyEvent event) {
169 synchronized (mLock) {
170 if (!mIsGamepadAccessed) return false;
171 GamepadDevice gamepad = getGamepadForEvent(event);
172 if (gamepad == null) return false;
173 return gamepad.handleKeyEvent(event);
174 }
175 }
176
177 /**
178 * Handles motion events from the gamepad devices.
179 * @return True if the event has been consumed.
180 */
181 public static boolean onGenericMotionEvent(MotionEvent event) {
182 if (!isGamepadEvent(event)) return false;
183 return sGamepadList.handleMotionEvent(event);
184 }
185
186 private boolean handleMotionEvent(MotionEvent event) {
187 synchronized (mLock) {
188 if (!mIsGamepadAccessed) return false;
189 GamepadDevice gamepad = getGamepadForEvent(event);
190 if (gamepad == null) return false;
191 return gamepad.handleMotionEvent(event);
192 }
193 }
194
195 private int getNextAvailableIndex() {
196 // When multiple gamepads are connected to a user agent, indices must be assigned on a
197 // first-come first-serve basis, starting at zero. If a gamepad is disco nnected, previously
198 // assigned indices must not be reassigned to gamepads that continue to be connected.
199 // However, if a gamepad is disconnected, and subsequently the same or a different
200 // gamepad is then connected, index entries must be reused.
201
202 for (int i = 0; i < MAX_GAMEPADS; ++i) {
203 if (getDevice(i) == null) {
204 return i;
205 }
206 }
207 // Reached maximum gamepads limit.
208 return -1;
209 }
210
211 private boolean registerGamepad(InputDevice inputDevice) {
212 int index = getNextAvailableIndex();
213 if (index == -1) return false; // invalid index
214
215 GamepadDevice gamepad = new GamepadDevice(index, inputDevice);
216 mGamepadDevices[index] = gamepad;
217 return true;
218 }
219
220 private void unregisterGamepad(int deviceId) {
221 GamepadDevice gamepadDevice = getDeviceById(deviceId);
222 if (gamepadDevice == null) return; // Not a registered device.
223 int index = gamepadDevice.getIndex();
224 mGamepadDevices[index] = null;
225 }
226
227 private static boolean isGamepadDevice(InputDevice inputDevice) {
228 return ((inputDevice.getSources() & InputDevice.SOURCE_JOYSTICK) ==
229 InputDevice.SOURCE_JOYSTICK);
230 }
231
232 private GamepadDevice getGamepadForEvent(InputEvent event) {
233 return getDeviceById(event.getDeviceId());
234 }
235
236 /**
237 * @return True if the motion event corresponds to a gamepad event.
238 */
239 public static boolean isGamepadEvent(MotionEvent event) {
240 return ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice .SOURCE_JOYSTICK);
241 }
242
243 /**
244 * @return True if event's keycode corresponds to a gamepad key.
245 */
246 public static boolean isGamepadEvent(KeyEvent event) {
247 int keyCode = event.getKeyCode();
248 switch (keyCode) {
249 // Specific handling for dpad keys is required because
250 // KeyEvent.isGamepadButton doesn't consider dpad keys.
251 case KeyEvent.KEYCODE_DPAD_UP:
252 case KeyEvent.KEYCODE_DPAD_DOWN:
253 case KeyEvent.KEYCODE_DPAD_LEFT:
254 case KeyEvent.KEYCODE_DPAD_RIGHT:
255 return true;
256 default:
257 return KeyEvent.isGamepadButton(keyCode);
258 }
259 }
260
261 @CalledByNative
262 static void updateGamepadData(long webGamepadsPtr) {
263 assert sGamepadList != null;
264 sGamepadList.grabGamepadData(webGamepadsPtr);
265 }
266
267 private void grabGamepadData(long webGamepadsPtr) {
268 synchronized (mLock) {
269 for (int i = 0; i < MAX_GAMEPADS; i++) {
270 final GamepadDevice device = getDevice(i);
271 if (device != null) {
272 device.updateButtonsAndAxesMapping();
273 nativeSetGamepadData(webGamepadsPtr, i, device.isStandardGam epad(), true,
274 device.getName(), device.getTimestamp(), device.getA xes(),
275 device.getButtons());
276 } else {
277 nativeSetGamepadData(webGamepadsPtr, i, false, false, null, 0, null, null);
278 }
279 }
280 }
281 }
282
283 @CalledByNative
284 static void notifyForGamepadsAccess(boolean isAccessPaused) {
285 assert sGamepadList != null;
286 sGamepadList.setIsGamepadAccessed(!isAccessPaused);
287 }
288
289 private void setIsGamepadAccessed(boolean isGamepadAccessed) {
290 synchronized (mLock) {
291 mIsGamepadAccessed = isGamepadAccessed;
292 if (isGamepadAccessed) {
293 for (int i = 0; i < MAX_GAMEPADS; i++) {
294 GamepadDevice gamepadDevice = getDevice(i);
295 if (gamepadDevice == null) continue;
296 gamepadDevice.clearData();
297 }
298 }
299 }
300 }
301
302 private native void nativeSetGamepadData(long webGamepadsPtr, int index, boo lean mapping,
303 boolean connected, String devicename, long timestamp, float[] axes, float[] buttons);
304
305 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698