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

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, 8 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 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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698