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

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 InputManager mInputManager;
29 // Native pointer to C++ GamepadReader object which will be set by CreateJav aObject().
30 private long mNativeGamepadReader = 0;
31 private int mAttachedToWindowCounter;
32
33 private GamepadList() {}
34
35 private void initializeDevices() {
36 // Get list of all the attached input devices.
37 int[] deviceIds = mInputManager.getInputDeviceIds();
38
39 for (int i = 0; i < deviceIds.length; i++) {
40 InputDevice inputDevice = InputDevice.getDevice(deviceIds[i]);
41 // Check for gamepad device
42 if (isGamepadDevice(inputDevice)) {
43 // Register a new gamepad device.
44 registerGamepad(inputDevice);
45 }
46 }
47 // Register an input device listener.
48 mInputManager.registerInputDeviceListener(this, null);
49 }
50
51 private static GamepadList sGamepadList = null;
52
53 public static void onAttachedToWindow(Context context) {
54 assert ThreadUtils.runningOnUiThread();
55 createInstance();
56 sGamepadList.attachedToWindow(context);
57 }
58
59 private void attachedToWindow(Context context) {
60 if (mAttachedToWindowCounter++ == 0) {
61 mInputManager = (InputManager) context.getSystemService(Context.INP UT_SERVICE);
62 initializeDevices();
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 for (int i = 0; i < MAX_GAMEPADS; ++i) {
74 mGamepadDevices[i] = null;
75 }
76 mInputManager.unregisterInputDeviceListener(this);
77 mInputManager = null;
78 }
79 }
80
81 // Override InputDeviceListener methods
82 @Override
83 public void onInputDeviceChanged(int deviceId) {
84 }
85
86 @Override
87 public void onInputDeviceRemoved(int deviceId) {
88 unregisterGamepad(deviceId);
89 }
90
91 @Override
92 public void onInputDeviceAdded(int deviceId) {
93 InputDevice inputDevice = InputDevice.getDevice(deviceId);
94 if (isGamepadDevice(inputDevice))
95 registerGamepad(inputDevice);
96 }
97
98 public static void createInstance() {
99 if (sGamepadList == null) {
100 sGamepadList = new GamepadList();
101 }
102 }
103
104 private int getDeviceCount() {
105 int count = 0;
106 for (int i = 0; i < MAX_GAMEPADS; ++i) {
107 if (getDevice(i) != null) {
108 count++;
109 }
110 }
111 return count;
112 }
113
114 private String getMapping(int index) {
115 return getDevice(index).getMapping();
116 }
117
118 private String getDeviceName(int index) {
119 return getDevice(index).getName();
120 }
121
122 private long getDeviceTimestamp(int index) {
123 return getDevice(index).getTimestamp();
124 }
125
126 private float[] getDeviceAxes(int index) {
127 return getDevice(index).getAxes();
128 }
129
130 private float[] getDeviceButtons(int index) {
131 return getDevice(index).getButtons();
132 }
133
134 private boolean isDeviceConnected(int index) {
135 if (index < MAX_GAMEPADS && getDevice(index) != null) {
136 return true;
137 }
138 return false;
139 }
140
141 public GamepadDevice getDeviceById(int deviceId) {
142 for (int i = 0; i < MAX_GAMEPADS; ++i) {
143 GamepadDevice gamepad = mGamepadDevices[i];
144 if (gamepad != null && gamepad.getId() == deviceId) {
145 return gamepad;
146 }
147 }
148 return null;
149 }
150
151 public GamepadDevice getDevice(int index) {
152 // Maximum 4 Gamepads can be connected at a time starting at index zero.
153 assert index >= 0 && index <= MAX_GAMEPADS - 1;
154 return mGamepadDevices[index];
155 }
156
157 public static boolean dispatchKeyEvent(KeyEvent event) {
158 if (sGamepadList.isGamepadAccessed() && sGamepadList.isGamepadEvent(even t))
159 return sGamepadList.updateForEvent(event);
160 return false;
161 }
162
163 private boolean updateForEvent(KeyEvent event) {
164 GamepadDevice gamepad = getGamepadForEvent(event);
165 if (gamepad != null) {
166 mHaveDevicesBeenInteractedWith = true;
167 return gamepad.updateForEvent(event);
168 }
169 return false;
170 }
171
172 public static boolean onGenericMotionEvent(MotionEvent event) {
173 if (sGamepadList.isGamepadAccessed() && sGamepadList.isGamepadEvent(even t))
174 return sGamepadList.updateForEvent(event);
175 return false;
176 }
177
178 private boolean updateForEvent(MotionEvent event) {
179 GamepadDevice gamepad = getGamepadForEvent(event);
180 if (gamepad != null) {
181 mHaveDevicesBeenInteractedWith = true;
182 return gamepad.updateForEvent(event);
183 }
184 return false;
185 }
186
187 protected int getNextAvailableIndex() {
188 // When multiple gamepads are connected to a user agent, indices must be assigned on a
189 // first-come first-serve basis, starting at zero. If a gamepad is disco nnected, previously
190 // assigned indices must not be reassigned to gamepads that continue to be connected.
191 // However, if a gamepad is disconnected, and subsequently the same or a different
192 // gamepad is then connected, index entries must be reused.
193
194 for (int i = 0; i < MAX_GAMEPADS; ++i) {
195 if (getDevice(i) == null) {
196 return i;
197 }
198 }
199 // Reached maximum gamepads limit.
200 return -1;
201 }
202
203 protected boolean registerGamepad(InputDevice inputDevice) {
204 int index = getNextAvailableIndex();
205 if (index == -1) {
206 return false; // invalid index
207 }
208
209 GamepadDevice gamepad = new GamepadDevice(index, inputDevice);
210 mGamepadDevices[index] = gamepad;
211 return true;
212 }
213
214 protected void unregisterGamepad(int deviceId) {
215 GamepadDevice gamepadDevice = getDeviceById(deviceId);
216 if (gamepadDevice == null) {
217 return; // Not a registered device.
218 }
219 int index = gamepadDevice.getIndex();
220 mGamepadDevices[index] = null;
221 }
222
223 private boolean isGamepadDevice(InputDevice inputDevice) {
224 int sources = inputDevice.getSources();
225 if ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JO YSTICK ) {
226 //Found gamepad device
227 return true;
228 }
229 return false;
230 }
231
232 private GamepadDevice getGamepadForEvent(InputEvent event) {
233 int deviceId = event.getDeviceId();
234 GamepadDevice gamepad = getDeviceById(deviceId);
235 return gamepad;
236 }
237
238 public boolean isGamepadAccessed() {
239 return mIsGamepadAccessed;
240 }
241
242 private boolean isGamepadEvent(MotionEvent event) {
243 if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOU RCE_JOYSTICK) {
244 return true;
245 }
246 return false;
247 }
248
249 // Returns true if event's keycode corresponds to a gamepad key.
250 // Specific handling for dpad keys is required because
251 // KeyEvent.isGamepadButton doesn't consider dpad keys.
252 public boolean isGamepadEvent(KeyEvent event) {
253 int keyCode = event.getKeyCode();
254 switch (keyCode) {
255 case KeyEvent.KEYCODE_DPAD_UP:
256 case KeyEvent.KEYCODE_DPAD_DOWN:
257 case KeyEvent.KEYCODE_DPAD_LEFT:
258 case KeyEvent.KEYCODE_DPAD_RIGHT:
259 return true;
260 default:
261 return KeyEvent.isGamepadButton(keyCode);
262 }
263 }
264
265 @CalledByNative
266 private void getGamepadData() {
267 assert mNativeGamepadReader != 0;
268 int devicecount = getDeviceCount();
269 if (devicecount == 0 || !mHaveDevicesBeenInteractedWith)
270 nativeUpdateDeviceCount(mNativeGamepadReader, 0);
271 else {
272 nativeUpdateDeviceCount(mNativeGamepadReader, devicecount);
273 for (int i = 0; i < MAX_GAMEPADS; i++) {
274 if (isDeviceConnected(i)) {
275 getDevice(i).mapButtonsAndAxes();
276 nativeSetGamepadData(mNativeGamepadReader, i, getMapping(i), true,
277 getDeviceName(i), getDeviceTimestamp(i) , getDeviceAxes(i),
278 getDeviceButtons(i));
279 }
280 else
281 nativeSetGamepadData(mNativeGamepadReader, i, null, false, n ull, 0, null,
282 null);
283 }
284 }
285 }
286
287 @CalledByNative
288 public static GamepadList getInstance(long nativeGamepadReader) {
289 assert sGamepadList != null;
290 sGamepadList.mNativeGamepadReader = nativeGamepadReader;
291 return sGamepadList;
292 }
293
294 @CalledByNative
295 private void notifyForGamepadsAccess(boolean isaccesspaused) {
296 mIsGamepadAccessed = !isaccesspaused;
297 }
298
299 private native void nativeSetGamepadData(long nativeGamepadsReader,
300 int index,
301 String mapping,
302 boolean connected,
303 String devicename,
304 long timestamp,
305 float[] axes,
306 float[] buttons);
307
308 private native void nativeUpdateDeviceCount(long nativeGamepadsReader, int d evicecount);
309
310 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698