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 | |
18 /* | |
19 * Class to manage connected gamepad devices list. | |
20 */ | |
21 @JNINamespace("content") | |
22 class GamepadList implements InputDeviceListener { | |
23 private static final int MAX_GAMEPADS = 4; | |
24 private GamepadDevice[] mGamepadDevices = new GamepadDevice[MAX_GAMEPADS]; | |
25 protected boolean mHaveDevicesBeenInteractedWith = false; | |
26 private boolean IS_GAMEPAD_ACCESSED = false; | |
kbalazs
2014/02/20 00:48:24
Shouldn't be named with initials since it's not a
SaurabhK
2014/02/26 14:14:26
On 2014/02/20 00:48:24, kbalazs wrote:
Done.
| |
27 private InputManager inputManager; | |
xwang
2014/02/25 10:26:58
inputManager -> mInputManager?
SaurabhK
2014/02/26 14:14:26
On 2014/02/25 10:26:58, xwang wrote:
Done.
| |
28 // Native pointer to C++ GamepadReader object which will be set by CreateJav aObject(). | |
29 private long mNativeGamepadReader = 0; | |
30 | |
31 private GamepadList(Context context) { | |
32 | |
33 inputManager = (InputManager) context.getSystemService(Context.INPUT_SE RVICE); | |
34 // Get list of all the attached input devices. | |
35 int[] deviceIds = inputManager.getInputDeviceIds(); | |
36 | |
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 inputManager.registerInputDeviceListener(this, null); | |
47 } | |
48 | |
49 private static GamepadList gamepadList = null; | |
xwang
2014/02/25 10:26:58
gamepadList -> sGamepadList
SaurabhK
2014/02/26 14:14:26
On 2014/02/25 10:26:58, xwang wrote:
Done.
| |
50 | |
51 // Override InputDeviceListener methods | |
52 @Override | |
53 public void onInputDeviceChanged(int deviceId) { | |
54 } | |
55 | |
56 @Override | |
57 public void onInputDeviceRemoved(int deviceId) { | |
58 unregisterGamepad(deviceId); | |
59 } | |
60 | |
61 @Override | |
62 public void onInputDeviceAdded(int deviceId) { | |
63 InputDevice inputDevice = InputDevice.getDevice(deviceId); | |
64 if (isGamepadDevice(inputDevice)) | |
65 registerGamepad(inputDevice); | |
66 } | |
67 | |
68 public static GamepadList createInstance(Context context) { | |
69 if (gamepadList != null) { | |
70 return gamepadList; | |
71 } else { | |
72 gamepadList = new GamepadList(context); | |
73 return gamepadList; | |
74 } | |
75 } | |
76 | |
77 private boolean haveDevicesBeenInteractedWith() { return mHaveDevicesBeenInt eractedWith; } | |
xwang
2014/02/25 10:26:58
Is it necessary to add a private function to acces
SaurabhK
2014/02/26 14:14:26
On 2014/02/25 10:26:58, xwang wrote:
Removed it.
| |
78 | |
79 private int getDeviceCount() { | |
80 int count = 0; | |
81 for (int i = 0; i < getCount(); ++i) { | |
82 if (getDevice(i) != null) { | |
83 count++; | |
84 } | |
85 } | |
86 return count; | |
87 } | |
88 | |
89 private String getDeviceName(int index) { | |
90 return getDevice(index).getName(); | |
91 } | |
92 | |
93 private long getDeviceTimestamp(int index) { | |
94 return getDevice(index).getTimestamp(); | |
95 } | |
96 | |
97 private float[] getDeviceAxes(int index) { | |
98 return getDevice(index).getAxes(); | |
99 } | |
100 | |
101 private float[] getDeviceButtons(int index) { | |
102 return getDevice(index).getButtons(); | |
103 } | |
104 | |
105 private boolean isDeviceConnected(int index) { | |
106 if (index < MAX_GAMEPADS && getDevice(index) != null) { | |
107 return true; | |
108 } | |
109 return false; | |
110 } | |
111 | |
112 private boolean isKnownGamepadLayout(int index) { | |
113 return getDevice(index).isKnownGamepadLayout(); | |
114 } | |
115 | |
116 public GamepadDevice getDeviceById(int deviceId) { | |
117 for (int i = 0; i < getCount(); ++i) { | |
118 GamepadDevice gamepad = mGamepadDevices[i]; | |
119 if (gamepad != null && gamepad.getId() == deviceId) { | |
120 return gamepad; | |
121 } | |
122 } | |
123 return null; | |
124 } | |
125 | |
126 public GamepadDevice getDevice(int index) { | |
127 // Maximum 4 Gamepads can be connected at a time starting at index zero. | |
128 assert index >= 0 && index <= getCount() - 1; | |
129 return mGamepadDevices[index]; | |
130 } | |
131 | |
132 public int getCount() { | |
kbalazs
2014/02/20 00:48:24
This doesn't look very useful to me, I would just
SaurabhK
2014/02/26 14:14:26
On 2014/02/20 00:48:24, kbalazs wrote:
Done.
| |
133 return MAX_GAMEPADS; | |
134 } | |
135 | |
136 public boolean updateForEvent(KeyEvent event) { | |
137 GamepadDevice gamepad = getGamepadForEvent(event); | |
138 if (gamepad != null) { | |
139 mHaveDevicesBeenInteractedWith = true; | |
kbalazs
2014/02/20 00:48:24
I think it's not strictly necessary to maintain th
| |
140 return gamepad.updateForEvent(event); | |
141 } | |
142 return false; | |
143 } | |
144 | |
145 public boolean updateForEvent(MotionEvent event) { | |
146 GamepadDevice gamepad = getGamepadForEvent(event); | |
147 if (gamepad != null) { | |
148 mHaveDevicesBeenInteractedWith = true; | |
149 return gamepad.updateForEvent(event); | |
150 } | |
151 return false; | |
152 } | |
153 | |
154 public void onPause() { | |
155 inputManager.unregisterInputDeviceListener(this); | |
156 } | |
157 | |
158 public void onResume() { | |
159 // Re-initialize gamepad list. | |
160 // Check if any registered gamepad is disconnected when webview was in p ause state. | |
kbalazs
2014/02/20 00:48:24
Can you word it more generally? This feature is no
SaurabhK
2014/02/26 14:14:26
On 2014/02/20 00:48:24, kbalazs wrote:
Removing o
| |
161 for (int i = 0; i < getCount(); ++i) { | |
kbalazs
2014/02/20 00:48:24
Isn't it enough to null out the array and enumerat
| |
162 if (mGamepadDevices[i] != null) { | |
163 InputDevice device = InputDevice.getDevice(mGamepadDevices[i].ge tId()); | |
164 if (device == null) { | |
165 // Remove disconnected gamepad. | |
166 mGamepadDevices[i] = null; | |
167 } | |
168 } | |
169 } | |
170 // Check if any new gamepad is connected when webview was in pause state . | |
171 int[] deviceIds = inputManager.getInputDeviceIds(); | |
172 for (int i = 0; i < deviceIds.length; ++i) { | |
173 InputDevice device = InputDevice.getDevice(deviceIds[i]); | |
174 if (isGamepadDevice(device)) { | |
175 GamepadDevice gamepad = getDeviceById(deviceIds[i]); | |
176 if (gamepad == null) { | |
177 // Found unregistered gamepad, could be a new device connect ed when | |
178 // webview was in puase state or disconnected and re-connect ed same device. | |
179 registerGamepad(device); | |
180 } | |
181 } | |
182 } | |
183 inputManager.registerInputDeviceListener(this, null); | |
184 } | |
185 | |
186 protected int getNextAvailableIndex() { | |
187 // When multiple gamepads are connected to a user agent, indices must be assigned on a | |
188 // first-come first-serve basis, starting at zero. If a gamepad is disco nnected, previously | |
189 // assigned indices must not be reassigned to gamepads that continue to be connected. | |
190 // However, if a gamepad is disconnected, and subsequently the same or a different | |
191 // gamepad is then connected, index entries must be reused. | |
192 | |
193 for (int i = 0; i < getCount(); ++i) { | |
194 if (getDevice(i) == null) { | |
195 return i; | |
196 } | |
197 } | |
198 // Reached maximum gamepads limit. | |
199 return -1; | |
200 } | |
201 | |
202 protected boolean registerGamepad(InputDevice inputDevice) { | |
203 int index = getNextAvailableIndex(); | |
204 if (index == -1) { | |
205 return false; // invalid index | |
206 } | |
207 | |
208 GamepadDevice gamepad = new GamepadDevice(index, inputDevice); | |
209 mGamepadDevices[index] = gamepad; | |
210 return true; | |
211 } | |
212 | |
213 protected void unregisterGamepad(int deviceId) { | |
214 GamepadDevice gamepadDevice = getDeviceById(deviceId); | |
215 if (gamepadDevice == null) { | |
216 return; // Not a registered device. | |
217 } | |
218 int index = gamepadDevice.getIndex(); | |
219 mGamepadDevices[index] = null; | |
220 } | |
221 | |
222 private boolean isGamepadDevice(InputDevice inputDevice) { | |
223 int sources = inputDevice.getSources(); | |
224 if ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JO YSTICK ) { | |
kbalazs
2014/02/20 00:48:24
Shouln't it be '(sources & InputDevice.SOURCE_JOYS
| |
225 //Found gamepad device | |
226 return true; | |
227 } | |
228 return false; | |
229 } | |
230 | |
231 private GamepadDevice getGamepadForEvent(InputEvent event) { | |
232 int deviceId = event.getDeviceId(); | |
233 GamepadDevice gamepad = getDeviceById(deviceId); | |
234 return gamepad; | |
235 } | |
236 | |
237 public boolean isGamepadAccessed() { | |
238 return IS_GAMEPAD_ACCESSED; | |
239 } | |
240 | |
241 public boolean isGamepadEvent(MotionEvent event) { | |
242 if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOU RCE_JOYSTICK) { | |
kbalazs
2014/02/20 00:48:24
Ditto about the condition.
| |
243 return true; | |
244 } | |
245 return false; | |
246 } | |
247 | |
248 // Returns true if event's keycode corresponds to a gamepad key. | |
249 // Specific handling for dpad keys is required because | |
250 // KeyEvent.isGamepadButton doesn't consider dpad keys. | |
251 public boolean isGamepadEvent(KeyEvent event) { | |
252 int keyCode = event.getKeyCode(); | |
253 switch (keyCode) { | |
254 case KeyEvent.KEYCODE_DPAD_UP: | |
255 case KeyEvent.KEYCODE_DPAD_DOWN: | |
256 case KeyEvent.KEYCODE_DPAD_LEFT: | |
257 case KeyEvent.KEYCODE_DPAD_RIGHT: | |
258 return true; | |
259 default: | |
260 return KeyEvent.isGamepadButton(keyCode); | |
261 } | |
262 } | |
263 | |
264 @CalledByNative | |
265 private void getGamepadData() { | |
266 int devicecount = getDeviceCount(); | |
267 if (devicecount == 0 || !haveDevicesBeenInteractedWith()) | |
268 nativeUpdateDeviceCount(mNativeGamepadReader, 0); | |
269 else | |
270 nativeUpdateDeviceCount(mNativeGamepadReader, devicecount); | |
271 for (int i = 0; i < MAX_GAMEPADS; i++) { | |
272 if (isDeviceConnected(i)) | |
273 nativeSetGamepadData(mNativeGamepadReader, i, true, getDevic eName(i), | |
274 getDeviceTimestamp(i), getDeviceAxes(i) , | |
275 getDeviceButtons(i)); | |
276 else | |
277 nativeSetGamepadData(mNativeGamepadReader, i, false, null, 0 , null, null); | |
278 } | |
279 } | |
280 | |
281 @CalledByNative | |
282 public static GamepadList getInstance(long nativeGamepadReader) { | |
283 if (gamepadList != null) { | |
284 gamepadList.mNativeGamepadReader = nativeGamepadReader; | |
285 return gamepadList; | |
286 } else { | |
287 return null; | |
288 } | |
289 } | |
290 | |
291 @CalledByNative | |
292 private void notifyForGamepadsAccess(boolean isaccesspaused) { | |
293 IS_GAMEPAD_ACCESSED = !isaccesspaused; | |
294 } | |
295 | |
296 private native void nativeSetGamepadData(long nativeGamepadsReader, | |
297 int index, | |
298 boolean connected, | |
299 String devicename, | |
300 long timestamp, | |
301 float[] axes, | |
302 float[] buttons); | |
303 | |
304 private native void nativeUpdateDeviceCount(long nativeGamepadsReader, int d evicecount); | |
305 | |
306 } | |
OLD | NEW |