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

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

Issue 133943002: Gamepad API support for chrome on android (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 6 years, 9 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;
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 protected boolean mHaveDevicesBeenInteractedWith = false;
27 private boolean mIsGamepadAccessed = false;
28 private final Object mLock = new Object();
29 private InputManager mInputManager;
30 private int mAttachedToWindowCounter;
31
32 private GamepadList() {}
33
34 private void initializeDevices() {
35 // Get list of all the attached input devices.
36 int[] deviceIds = mInputManager.getInputDeviceIds();
37 for (int i = 0; i < deviceIds.length; i++) {
38 InputDevice inputDevice = InputDevice.getDevice(deviceIds[i]);
39 // Check for gamepad device
40 if (isGamepadDevice(inputDevice)) {
41 // Register a new gamepad device.
42 registerGamepad(inputDevice);
43 }
44 }
45 // Register an input device listener.
46 mInputManager.registerInputDeviceListener(this, null);
47 }
48
49 private static GamepadList sGamepadList = null;
50
51 public static void onAttachedToWindow(Context context) {
52 assert ThreadUtils.runningOnUiThread();
jdduke (slow) 2014/03/24 17:38:15 Do we have any guarantees that this method will be
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Whenever a v
53 createInstance();
54 sGamepadList.attachedToWindow(context);
55 }
56
57 private void attachedToWindow(Context context) {
58 if (mAttachedToWindowCounter++ == 0) {
59 synchronized (mLock) {
60 mInputManager = (InputManager) context.getSystemService(Context .INPUT_SERVICE);
jdduke (slow) 2014/03/24 17:38:15 mInputManager is only accessed on the UI thread, s
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
61 initializeDevices();
62 }
63 }
64 }
65
66 public static void onDetachedFromWindow() {
67 assert ThreadUtils.runningOnUiThread();
68 sGamepadList.detachedFromWindow();
69 }
70
71 private void detachedFromWindow() {
72 if (--mAttachedToWindowCounter == 0) {
73 synchronized (mLock) {
74 for (int i = 0; i < MAX_GAMEPADS; ++i) {
75 mGamepadDevices[i] = null;
76 }
77 }
78 mInputManager.unregisterInputDeviceListener(this);
79 mInputManager = null;
80 }
81 }
82
83 // Override InputDeviceListener methods
84 @Override
85 public void onInputDeviceChanged(int deviceId) {
86 }
87
88 @Override
89 public void onInputDeviceRemoved(int deviceId) {
90 synchronized (mLock) {
91 unregisterGamepad(deviceId);
92 }
93 }
94
95 @Override
96 public void onInputDeviceAdded(int deviceId) {
97 InputDevice inputDevice = InputDevice.getDevice(deviceId);
98 synchronized (mLock) {
99 if (isGamepadDevice(inputDevice))
jdduke (slow) 2014/03/24 17:38:15 Please pull this check outside the lock, and early
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
100 registerGamepad(inputDevice);
101 }
102 }
103
104 public static void createInstance() {
105 if (sGamepadList == null) {
106 sGamepadList = new GamepadList();
107 }
108 }
109
110 private int getDeviceCount() {
111 int count = 0;
112 for (int i = 0; i < MAX_GAMEPADS; ++i) {
113 if (getDevice(i) != null) {
114 count++;
115 }
116 }
117 return count;
118 }
119
120 private String getMapping(int index) {
121 return getDevice(index).getMapping();
122 }
123
124 private String getDeviceName(int index) {
125 return getDevice(index).getName();
126 }
127
128 private long getDeviceTimestamp(int index) {
129 return getDevice(index).getTimestamp();
130 }
131
132 private float[] getDeviceAxes(int index) {
133 return getDevice(index).getAxes();
134 }
135
136 private float[] getDeviceButtons(int index) {
137 return getDevice(index).getButtons();
138 }
139
140 private boolean isDeviceConnected(int index) {
141 if (index < MAX_GAMEPADS && getDevice(index) != null) {
142 return true;
143 }
144 return false;
145 }
146
147 public GamepadDevice getDeviceById(int deviceId) {
jdduke (slow) 2014/03/24 17:38:15 Why is this public? Any public member that accesse
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Changing it
148 for (int i = 0; i < MAX_GAMEPADS; ++i) {
149 GamepadDevice gamepad = mGamepadDevices[i];
150 if (gamepad != null && gamepad.getId() == deviceId) {
151 return gamepad;
152 }
153 }
154 return null;
155 }
156
157 public GamepadDevice getDevice(int index) {
jdduke (slow) 2014/03/24 17:38:15 Again, why public?
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
158 // Maximum 4 Gamepads can be connected at a time starting at index zero.
159 assert index >= 0 && index <= MAX_GAMEPADS - 1;
jdduke (slow) 2014/03/24 17:38:15 index < MAX_GAMEPADS
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
160 return mGamepadDevices[index];
161 }
162
163 public static boolean dispatchKeyEvent(KeyEvent event) {
164 if (sGamepadList.mIsGamepadAccessed && sGamepadList.isGamepadEvent(event ))
jdduke (slow) 2014/03/24 17:38:15 These public static methods are accessing shared d
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
165 return sGamepadList.updateForEvent(event);
166 return false;
167 }
168
169 private boolean updateForEvent(KeyEvent event) {
170 synchronized (mLock) {
171 GamepadDevice gamepad = getGamepadForEvent(event);
172 if (gamepad != null) {
173 mHaveDevicesBeenInteractedWith = true;
jdduke (slow) 2014/03/24 17:38:15 Why not store this variable in each GamepadDevice?
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Now storing
174 return gamepad.updateForEvent(event);
175 }
176 return false;
177 }
178 }
179
180 public static boolean onGenericMotionEvent(MotionEvent event) {
181 if (sGamepadList.mIsGamepadAccessed && sGamepadList.isGamepadEvent(event ))
182 return sGamepadList.updateForEvent(event);
183 return false;
184 }
185
186 private boolean updateForEvent(MotionEvent event) {
187 synchronized (mLock) {
188 GamepadDevice gamepad = getGamepadForEvent(event);
189 if (gamepad != null) {
190 mHaveDevicesBeenInteractedWith = true;
191 return gamepad.updateForEvent(event);
192 }
193 return false;
194 }
195 }
196
197 protected int getNextAvailableIndex() {
198 // When multiple gamepads are connected to a user agent, indices must be assigned on a
199 // first-come first-serve basis, starting at zero. If a gamepad is disco nnected, previously
200 // assigned indices must not be reassigned to gamepads that continue to be connected.
201 // However, if a gamepad is disconnected, and subsequently the same or a different
202 // gamepad is then connected, index entries must be reused.
203
204 for (int i = 0; i < MAX_GAMEPADS; ++i) {
205 if (getDevice(i) == null) {
206 return i;
207 }
208 }
209 // Reached maximum gamepads limit.
210 return -1;
211 }
212
213 protected boolean registerGamepad(InputDevice inputDevice) {
214 int index = getNextAvailableIndex();
215 if (index == -1) {
216 return false; // invalid index
217 }
218
219 GamepadDevice gamepad = new GamepadDevice(index, inputDevice);
220 mGamepadDevices[index] = gamepad;
221 return true;
222 }
223
224 protected void unregisterGamepad(int deviceId) {
225 GamepadDevice gamepadDevice = getDeviceById(deviceId);
226 if (gamepadDevice == null) {
227 return; // Not a registered device.
228 }
229 int index = gamepadDevice.getIndex();
230 mGamepadDevices[index] = null;
231 }
232
233 private boolean isGamepadDevice(InputDevice inputDevice) {
jdduke (slow) 2014/03/24 17:38:15 This method can be static.
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
234 int sources = inputDevice.getSources();
235 if ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JO YSTICK ) {
236 //Found gamepad device
237 return true;
238 }
239 return false;
240 }
241
242 private GamepadDevice getGamepadForEvent(InputEvent event) {
243 int deviceId = event.getDeviceId();
244 GamepadDevice gamepad = getDeviceById(deviceId);
245 return gamepad;
246 }
247
248 private boolean isGamepadEvent(MotionEvent event) {
jdduke (slow) 2014/03/24 17:38:15 This method can be static.
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
249 if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOU RCE_JOYSTICK) {
250 return true;
251 }
252 return false;
253 }
254
255 // Returns true if event's keycode corresponds to a gamepad key.
256 // Specific handling for dpad keys is required because
257 // KeyEvent.isGamepadButton doesn't consider dpad keys.
258 public boolean isGamepadEvent(KeyEvent event) {
jdduke (slow) 2014/03/26 16:37:58 Hmm, is this accessed anywhere else? If not, pleas
SaurabhK 2014/03/27 13:32:31 On 2014/03/26 16:37:58, jdduke wrote: Made private
259 int keyCode = event.getKeyCode();
260 switch (keyCode) {
261 case KeyEvent.KEYCODE_DPAD_UP:
262 case KeyEvent.KEYCODE_DPAD_DOWN:
263 case KeyEvent.KEYCODE_DPAD_LEFT:
264 case KeyEvent.KEYCODE_DPAD_RIGHT:
265 return true;
266 default:
267 return KeyEvent.isGamepadButton(keyCode);
268 }
269 }
270
271 @CalledByNative
272 static void getGamepadData(long gamepads) {
273 assert sGamepadList != null;
274 sGamepadList.grabGamepadData(gamepads);
275 }
276
277 private void grabGamepadData(long gamepads) {
278 synchronized (mLock) {
279 for (int i = 0; i < MAX_GAMEPADS; i++) {
280 if (mHaveDevicesBeenInteractedWith && isDeviceConnected(i)) {
281 getDevice(i).mapButtonsAndAxes();
282 nativeSetGamepadData(gamepads, i, getMapping(i), true,
jdduke (slow) 2014/03/24 17:38:15 Why all these helper methods? Why not do something
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Done.
283 getDeviceName(i), getDeviceTimestamp(i) , getDeviceAxes(i),
284 getDeviceButtons(i));
285 }
286 else
287 nativeSetGamepadData(gamepads, i, null, false, null, 0, null , null);
288 }
289 }
290 }
291
292 @CalledByNative
293 static void notifyForGamepadsAccess(boolean isaccesspaused) {
jdduke (slow) 2014/03/26 16:37:58 Nit: isAccessPaused.
SaurabhK 2014/03/27 13:32:31 On 2014/03/26 16:37:58, jdduke wrote: Done.
294 assert sGamepadList != null;
295 synchronized (sGamepadList.mLock) {
296 sGamepadList.mIsGamepadAccessed = !isaccesspaused;
jdduke (slow) 2014/03/26 16:37:58 It feels a little funky locking the static instanc
SaurabhK 2014/03/27 13:32:31 On 2014/03/26 16:37:58, jdduke wrote: Done.
297 if (isaccesspaused) {
298 for (int i = 0; i < MAX_GAMEPADS; i++) {
299 GamepadDevice gamepadDevice = sGamepadList.getDevice(i);
300 if(gamepadDevice != null)
301 gamepadDevice.clearData();
302 }
303 }
304 }
305 }
306
307 private native void nativeSetGamepadData(long gamepads,
jdduke (slow) 2014/03/24 17:38:15 Please rename all |gamepads| references to |native
SaurabhK 2014/03/26 16:10:07 On 2014/03/24 17:38:15, jdduke wrote: Is it neede
jdduke (slow) 2014/03/26 16:37:58 Hmm, I think that's a convention, but I don't feel
308 int index,
309 String mapping,
310 boolean connected,
311 String devicename,
312 long timestamp,
313 float[] axes,
314 float[] buttons);
315
316 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698