blob: 30b49d3173160e4097d31c292e79432de3cf6d20 [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import com.android.internal.util.XmlUtils;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070020
21import org.xmlpull.v1.XmlPullParser;
22
23import android.content.Context;
Jeff Brown349703e2010-06-22 01:27:15 -070024import android.content.pm.PackageManager;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025import android.content.res.Configuration;
26import android.os.Environment;
Jeff Brownae9fc032010-08-18 15:51:08 -070027import android.os.SystemProperties;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070028import android.util.Slog;
29import android.util.Xml;
30import android.view.InputChannel;
Jeff Brown8d608662010-08-30 03:02:23 -070031import android.view.InputDevice;
Jeff Brown6ec402b2010-07-28 15:48:59 -070032import android.view.InputEvent;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070033import android.view.Surface;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070034
35import java.io.BufferedReader;
36import java.io.File;
37import java.io.FileInputStream;
38import java.io.FileNotFoundException;
39import java.io.FileReader;
40import java.io.IOException;
41import java.io.InputStreamReader;
42import java.io.PrintWriter;
43import java.util.ArrayList;
44
45/*
46 * Wraps the C++ InputManager and provides its callbacks.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070047 */
48public class InputManager {
49 static final String TAG = "InputManager";
50
Jeff Brownb6997262010-10-08 22:31:17 -070051 private static final boolean DEBUG = false;
52
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070053 private final Callbacks mCallbacks;
54 private final Context mContext;
55 private final WindowManagerService mWindowManagerService;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070056
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070057 private static native void nativeInit(Callbacks callbacks);
58 private static native void nativeStart();
59 private static native void nativeSetDisplaySize(int displayId, int width, int height);
60 private static native void nativeSetDisplayOrientation(int displayId, int rotation);
61
Jeff Brown6d0fec22010-07-23 21:28:06 -070062 private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070063 int scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -070064 private static native int nativeGetKeyCodeState(int deviceId, int sourceMask,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070065 int keyCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -070066 private static native int nativeGetSwitchState(int deviceId, int sourceMask,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070067 int sw);
Jeff Brown6d0fec22010-07-23 21:28:06 -070068 private static native boolean nativeHasKeys(int deviceId, int sourceMask,
69 int[] keyCodes, boolean[] keyExists);
Jeff Browna41ca772010-08-11 14:46:32 -070070 private static native void nativeRegisterInputChannel(InputChannel inputChannel,
71 boolean monitor);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070072 private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
Jeff Brown6ec402b2010-07-28 15:48:59 -070073 private static native int nativeInjectInputEvent(InputEvent event,
74 int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
Jeff Brown349703e2010-06-22 01:27:15 -070075 private static native void nativeSetInputWindows(InputWindow[] windows);
76 private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
77 private static native void nativeSetFocusedApplication(InputApplication application);
Jeff Brown8d608662010-08-30 03:02:23 -070078 private static native InputDevice nativeGetInputDevice(int deviceId);
Jeff Brown57c59372010-09-21 18:22:55 -070079 private static native void nativeGetInputConfiguration(Configuration configuration);
Jeff Brown8d608662010-08-30 03:02:23 -070080 private static native int[] nativeGetInputDeviceIds();
Jeff Browne6504122010-09-27 14:52:15 -070081 private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
82 InputChannel toChannel);
Jeff Browne33348b2010-07-15 23:54:05 -070083 private static native String nativeDump();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070084
Jeff Brown7fbdc842010-06-17 20:52:56 -070085 // Input event injection constants defined in InputDispatcher.h.
86 static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
87 static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
88 static final int INPUT_EVENT_INJECTION_FAILED = 2;
89 static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
90
Jeff Brown6ec402b2010-07-28 15:48:59 -070091 // Input event injection synchronization modes defined in InputDispatcher.h
92 static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0;
93 static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1;
94 static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2;
95
Jeff Brown6d0fec22010-07-23 21:28:06 -070096 // Key states (may be returned by queries about the current state of a
97 // particular key code, scan code or switch).
98
99 /** The key state is unknown or the requested key itself is not supported. */
100 public static final int KEY_STATE_UNKNOWN = -1;
101
102 /** The key is up. /*/
103 public static final int KEY_STATE_UP = 0;
104
105 /** The key is down. */
106 public static final int KEY_STATE_DOWN = 1;
107
108 /** The key is down but is a virtual key press that is being emulated by the system. */
109 public static final int KEY_STATE_VIRTUAL = 2;
110
Jeff Browne33348b2010-07-15 23:54:05 -0700111 public InputManager(Context context, WindowManagerService windowManagerService) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700112 this.mContext = context;
113 this.mWindowManagerService = windowManagerService;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700114
115 this.mCallbacks = new Callbacks();
116
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700117 init();
118 }
119
120 private void init() {
121 Slog.i(TAG, "Initializing input manager");
122 nativeInit(mCallbacks);
123 }
124
125 public void start() {
126 Slog.i(TAG, "Starting input manager");
127 nativeStart();
128 }
129
130 public void setDisplaySize(int displayId, int width, int height) {
131 if (width <= 0 || height <= 0) {
132 throw new IllegalArgumentException("Invalid display id or dimensions.");
133 }
134
Jeff Brownb6997262010-10-08 22:31:17 -0700135 if (DEBUG) {
136 Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height);
137 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700138 nativeSetDisplaySize(displayId, width, height);
139 }
140
141 public void setDisplayOrientation(int displayId, int rotation) {
142 if (rotation < Surface.ROTATION_0 || rotation > Surface.ROTATION_270) {
143 throw new IllegalArgumentException("Invalid rotation.");
144 }
145
Jeff Brownb6997262010-10-08 22:31:17 -0700146 if (DEBUG) {
147 Slog.d(TAG, "Setting display #" + displayId + " orientation to " + rotation);
148 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700149 nativeSetDisplayOrientation(displayId, rotation);
150 }
151
152 public void getInputConfiguration(Configuration config) {
153 if (config == null) {
154 throw new IllegalArgumentException("config must not be null.");
155 }
156
Jeff Brown57c59372010-09-21 18:22:55 -0700157 nativeGetInputConfiguration(config);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700158 }
159
Jeff Brown6d0fec22010-07-23 21:28:06 -0700160 /**
161 * Gets the current state of a key or button by key code.
162 * @param deviceId The input device id, or -1 to consult all devices.
163 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
164 * consider all input sources. An input device is consulted if at least one of its
165 * non-class input source bits matches the specified source mask.
166 * @param keyCode The key code to check.
167 * @return The key state.
168 */
169 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
170 return nativeGetKeyCodeState(deviceId, sourceMask, keyCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700171 }
172
Jeff Brown6d0fec22010-07-23 21:28:06 -0700173 /**
174 * Gets the current state of a key or button by scan code.
175 * @param deviceId The input device id, or -1 to consult all devices.
176 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
177 * consider all input sources. An input device is consulted if at least one of its
178 * non-class input source bits matches the specified source mask.
179 * @param scanCode The scan code to check.
180 * @return The key state.
181 */
182 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
183 return nativeGetScanCodeState(deviceId, sourceMask, scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700184 }
185
Jeff Brown6d0fec22010-07-23 21:28:06 -0700186 /**
187 * Gets the current state of a switch by switch code.
188 * @param deviceId The input device id, or -1 to consult all devices.
189 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
190 * consider all input sources. An input device is consulted if at least one of its
191 * non-class input source bits matches the specified source mask.
192 * @param switchCode The switch code to check.
193 * @return The switch state.
194 */
195 public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
196 return nativeGetSwitchState(deviceId, sourceMask, switchCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700197 }
198
Jeff Brown6d0fec22010-07-23 21:28:06 -0700199 /**
200 * Determines whether the specified key codes are supported by a particular device.
201 * @param deviceId The input device id, or -1 to consult all devices.
202 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
203 * consider all input sources. An input device is consulted if at least one of its
204 * non-class input source bits matches the specified source mask.
205 * @param keyCodes The array of key codes to check.
206 * @param keyExists An array at least as large as keyCodes whose entries will be set
207 * to true or false based on the presence or absence of support for the corresponding
208 * key codes.
209 * @return True if the lookup was successful, false otherwise.
210 */
211 public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700212 if (keyCodes == null) {
213 throw new IllegalArgumentException("keyCodes must not be null.");
214 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700215 if (keyExists == null || keyExists.length < keyCodes.length) {
216 throw new IllegalArgumentException("keyExists must not be null and must be at "
217 + "least as large as keyCodes.");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700218 }
219
Jeff Brown6d0fec22010-07-23 21:28:06 -0700220 return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700221 }
222
Jeff Browna41ca772010-08-11 14:46:32 -0700223 /**
224 * Creates an input channel that will receive all input from the input dispatcher.
225 * @param inputChannelName The input channel name.
226 * @return The input channel.
227 */
228 public InputChannel monitorInput(String inputChannelName) {
229 if (inputChannelName == null) {
230 throw new IllegalArgumentException("inputChannelName must not be null.");
231 }
232
233 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
234 nativeRegisterInputChannel(inputChannels[0], true);
235 inputChannels[0].dispose(); // don't need to retain the Java object reference
236 return inputChannels[1];
237 }
238
239 /**
240 * Registers an input channel so that it can be used as an input event target.
241 * @param inputChannel The input channel to register.
242 */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700243 public void registerInputChannel(InputChannel inputChannel) {
244 if (inputChannel == null) {
245 throw new IllegalArgumentException("inputChannel must not be null.");
246 }
247
Jeff Browna41ca772010-08-11 14:46:32 -0700248 nativeRegisterInputChannel(inputChannel, false);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700249 }
250
Jeff Browna41ca772010-08-11 14:46:32 -0700251 /**
252 * Unregisters an input channel.
253 * @param inputChannel The input channel to unregister.
254 */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700255 public void unregisterInputChannel(InputChannel inputChannel) {
256 if (inputChannel == null) {
257 throw new IllegalArgumentException("inputChannel must not be null.");
258 }
259
260 nativeUnregisterInputChannel(inputChannel);
261 }
262
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700263 /**
Jeff Brown6ec402b2010-07-28 15:48:59 -0700264 * Injects an input event into the event system on behalf of an application.
265 * The synchronization mode determines whether the method blocks while waiting for
266 * input injection to proceed.
267 *
268 * {@link #INPUT_EVENT_INJECTION_SYNC_NONE} never blocks. Injection is asynchronous and
269 * is assumed always to be successful.
270 *
271 * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT} waits for previous events to be
272 * dispatched so that the input dispatcher can determine whether input event injection will
273 * be permitted based on the current input focus. Does not wait for the input event to
274 * finish processing.
275 *
276 * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH} waits for the input event to
277 * be completely processed.
278 *
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700279 * @param event The event to inject.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700280 * @param injectorPid The pid of the injecting application.
281 * @param injectorUid The uid of the injecting application.
Jeff Brown6ec402b2010-07-28 15:48:59 -0700282 * @param syncMode The synchronization mode.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700283 * @param timeoutMillis The injection timeout in milliseconds.
284 * @return One of the INPUT_EVENT_INJECTION_XXX constants.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700285 */
Jeff Brown6ec402b2010-07-28 15:48:59 -0700286 public int injectInputEvent(InputEvent event, int injectorPid, int injectorUid,
287 int syncMode, int timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700288 if (event == null) {
289 throw new IllegalArgumentException("event must not be null");
290 }
291 if (injectorPid < 0 || injectorUid < 0) {
292 throw new IllegalArgumentException("injectorPid and injectorUid must not be negative.");
293 }
294 if (timeoutMillis <= 0) {
295 throw new IllegalArgumentException("timeoutMillis must be positive");
296 }
Jeff Brown6ec402b2010-07-28 15:48:59 -0700297
298 return nativeInjectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700299 }
300
Jeff Brown8d608662010-08-30 03:02:23 -0700301 /**
302 * Gets information about the input device with the specified id.
303 * @param id The device id.
304 * @return The input device or null if not found.
305 */
306 public InputDevice getInputDevice(int deviceId) {
307 return nativeGetInputDevice(deviceId);
308 }
309
310 /**
311 * Gets the ids of all input devices in the system.
312 * @return The input device ids.
313 */
314 public int[] getInputDeviceIds() {
315 return nativeGetInputDeviceIds();
316 }
317
Jeff Brown349703e2010-06-22 01:27:15 -0700318 public void setInputWindows(InputWindow[] windows) {
319 nativeSetInputWindows(windows);
320 }
321
322 public void setFocusedApplication(InputApplication application) {
323 nativeSetFocusedApplication(application);
324 }
325
Jeff Brown349703e2010-06-22 01:27:15 -0700326 public void setInputDispatchMode(boolean enabled, boolean frozen) {
327 nativeSetInputDispatchMode(enabled, frozen);
328 }
329
Jeff Browne6504122010-09-27 14:52:15 -0700330 /**
331 * Atomically transfers touch focus from one window to another as identified by
332 * their input channels. It is possible for multiple windows to have
333 * touch focus if they support split touch dispatch
334 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
335 * method only transfers touch focus of the specified window without affecting
336 * other windows that may also have touch focus at the same time.
337 * @param fromChannel The channel of a window that currently has touch focus.
338 * @param toChannel The channel of the window that should receive touch focus in
339 * place of the first.
340 * @return True if the transfer was successful. False if the window with the
341 * specified channel did not actually have touch focus at the time of the request.
342 */
343 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
344 if (fromChannel == null) {
345 throw new IllegalArgumentException("fromChannel must not be null.");
346 }
347 if (toChannel == null) {
348 throw new IllegalArgumentException("toChannel must not be null.");
349 }
350 return nativeTransferTouchFocus(fromChannel, toChannel);
351 }
352
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700353 public void dump(PrintWriter pw) {
Jeff Browne33348b2010-07-15 23:54:05 -0700354 String dumpStr = nativeDump();
355 if (dumpStr != null) {
356 pw.println(dumpStr);
357 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700358 }
359
360 private static final class VirtualKeyDefinition {
361 public int scanCode;
362
363 // configured position data, specified in display coords
364 public int centerX;
365 public int centerY;
366 public int width;
367 public int height;
368 }
369
370 /*
371 * Callbacks from native.
372 */
373 private class Callbacks {
374 static final String TAG = "InputManager-Callbacks";
375
376 private static final boolean DEBUG_VIRTUAL_KEYS = false;
377 private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
Jeff Brown8d608662010-08-30 03:02:23 -0700378 private static final String CALIBRATION_DIR_PATH = "usr/idc/";
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700379
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700380 @SuppressWarnings("unused")
Jeff Brown57c59372010-09-21 18:22:55 -0700381 public void notifyConfigurationChanged(long whenNanos) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700382 mWindowManagerService.sendNewConfiguration();
383 }
384
385 @SuppressWarnings("unused")
386 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700387 mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700388 }
389
390 @SuppressWarnings("unused")
Jeff Brown7fbdc842010-06-17 20:52:56 -0700391 public void notifyInputChannelBroken(InputChannel inputChannel) {
Jeff Brown349703e2010-06-22 01:27:15 -0700392 mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700393 }
Jeff Brown7fbdc842010-06-17 20:52:56 -0700394
395 @SuppressWarnings("unused")
Jeff Brown519e0242010-09-15 15:18:56 -0700396 public long notifyANR(Object token, InputChannel inputChannel) {
397 return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel);
Jeff Brown349703e2010-06-22 01:27:15 -0700398 }
399
400 @SuppressWarnings("unused")
Jeff Brown4d396052010-10-29 21:50:21 -0700401 public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
402 int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700403 return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
Jeff Brown4d396052010-10-29 21:50:21 -0700404 whenNanos, action, flags, keyCode, scanCode, policyFlags, isScreenOn);
Jeff Brown349703e2010-06-22 01:27:15 -0700405 }
406
407 @SuppressWarnings("unused")
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700408 public boolean interceptKeyBeforeDispatching(InputChannel focus, int action,
Jeff Brown4d396052010-10-29 21:50:21 -0700409 int flags, int keyCode, int scanCode, int metaState, int repeatCount,
410 int policyFlags) {
Jeff Brown349703e2010-06-22 01:27:15 -0700411 return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus,
Jeff Brown4d396052010-10-29 21:50:21 -0700412 action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -0700413 }
414
415 @SuppressWarnings("unused")
Jeff Brown3915bb82010-11-05 15:02:16 -0700416 public boolean dispatchUnhandledKey(InputChannel focus, int action,
417 int flags, int keyCode, int scanCode, int metaState, int repeatCount,
418 int policyFlags) {
419 return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(focus,
420 action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags);
421 }
422
423 @SuppressWarnings("unused")
Jeff Brown349703e2010-06-22 01:27:15 -0700424 public boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
425 return mContext.checkPermission(
426 android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid)
427 == PackageManager.PERMISSION_GRANTED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700428 }
429
430 @SuppressWarnings("unused")
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700431 public boolean filterTouchEvents() {
432 return mContext.getResources().getBoolean(
433 com.android.internal.R.bool.config_filterTouchEvents);
434 }
435
436 @SuppressWarnings("unused")
437 public boolean filterJumpyTouchEvents() {
438 return mContext.getResources().getBoolean(
439 com.android.internal.R.bool.config_filterJumpyTouchEvents);
440 }
441
442 @SuppressWarnings("unused")
443 public VirtualKeyDefinition[] getVirtualKeyDefinitions(String deviceName) {
444 ArrayList<VirtualKeyDefinition> keys = new ArrayList<VirtualKeyDefinition>();
445
446 try {
447 FileInputStream fis = new FileInputStream(
448 "/sys/board_properties/virtualkeys." + deviceName);
449 InputStreamReader isr = new InputStreamReader(fis);
450 BufferedReader br = new BufferedReader(isr, 2048);
451 String str = br.readLine();
452 if (str != null) {
453 String[] it = str.split(":");
454 if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "***** VIRTUAL KEYS: " + it);
455 final int N = it.length-6;
456 for (int i=0; i<=N; i+=6) {
457 if (!"0x01".equals(it[i])) {
Jeff Brown8d608662010-08-30 03:02:23 -0700458 Slog.w(TAG, "Unknown virtual key type at elem #"
459 + i + ": " + it[i] + " for device " + deviceName);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700460 continue;
461 }
462 try {
463 VirtualKeyDefinition key = new VirtualKeyDefinition();
464 key.scanCode = Integer.parseInt(it[i+1]);
465 key.centerX = Integer.parseInt(it[i+2]);
466 key.centerY = Integer.parseInt(it[i+3]);
467 key.width = Integer.parseInt(it[i+4]);
468 key.height = Integer.parseInt(it[i+5]);
469 if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Virtual key "
470 + key.scanCode + ": center=" + key.centerX + ","
471 + key.centerY + " size=" + key.width + "x"
472 + key.height);
473 keys.add(key);
474 } catch (NumberFormatException e) {
Jeff Brown8d608662010-08-30 03:02:23 -0700475 Slog.w(TAG, "Bad number in virtual key definition at region "
476 + i + " in: " + str + " for device " + deviceName, e);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700477 }
478 }
479 }
480 br.close();
481 } catch (FileNotFoundException e) {
Jeff Brown8d608662010-08-30 03:02:23 -0700482 Slog.i(TAG, "No virtual keys found for device " + deviceName + ".");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700483 } catch (IOException e) {
Jeff Brown8d608662010-08-30 03:02:23 -0700484 Slog.w(TAG, "Error reading virtual keys for device " + deviceName + ".", e);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700485 }
486
487 return keys.toArray(new VirtualKeyDefinition[keys.size()]);
488 }
489
490 @SuppressWarnings("unused")
491 public String[] getExcludedDeviceNames() {
492 ArrayList<String> names = new ArrayList<String>();
493
494 // Read partner-provided list of excluded input devices
495 XmlPullParser parser = null;
496 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
497 File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
498 FileReader confreader = null;
499 try {
500 confreader = new FileReader(confFile);
501 parser = Xml.newPullParser();
502 parser.setInput(confreader);
503 XmlUtils.beginDocument(parser, "devices");
504
505 while (true) {
506 XmlUtils.nextElement(parser);
507 if (!"device".equals(parser.getName())) {
508 break;
509 }
510 String name = parser.getAttributeValue(null, "name");
511 if (name != null) {
512 names.add(name);
513 }
514 }
515 } catch (FileNotFoundException e) {
516 // It's ok if the file does not exist.
517 } catch (Exception e) {
518 Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
519 } finally {
520 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
521 }
522
523 return names.toArray(new String[names.size()]);
524 }
Jeff Brownae9fc032010-08-18 15:51:08 -0700525
526 @SuppressWarnings("unused")
527 public int getMaxEventsPerSecond() {
528 int result = 0;
529 try {
530 result = Integer.parseInt(SystemProperties.get("windowsmgr.max_events_per_sec"));
531 } catch (NumberFormatException e) {
532 }
533 if (result < 1) {
Jeff Brown3d8c9bd2010-08-18 17:48:53 -0700534 result = 60;
Jeff Brownae9fc032010-08-18 15:51:08 -0700535 }
536 return result;
537 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700538 }
539}