blob: e7eb1293d0e054d04d822f5d3e2f80e8be94fd85 [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;
Jeff Brown8d608662010-08-30 03:02:23 -070044import java.util.Properties;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070045
46/*
47 * Wraps the C++ InputManager and provides its callbacks.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048 */
49public class InputManager {
50 static final String TAG = "InputManager";
51
Jeff Brownb6997262010-10-08 22:31:17 -070052 private static final boolean DEBUG = false;
53
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070054 private final Callbacks mCallbacks;
55 private final Context mContext;
56 private final WindowManagerService mWindowManagerService;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070057
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070058 private static native void nativeInit(Callbacks callbacks);
59 private static native void nativeStart();
60 private static native void nativeSetDisplaySize(int displayId, int width, int height);
61 private static native void nativeSetDisplayOrientation(int displayId, int rotation);
62
Jeff Brown6d0fec22010-07-23 21:28:06 -070063 private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070064 int scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -070065 private static native int nativeGetKeyCodeState(int deviceId, int sourceMask,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070066 int keyCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -070067 private static native int nativeGetSwitchState(int deviceId, int sourceMask,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070068 int sw);
Jeff Brown6d0fec22010-07-23 21:28:06 -070069 private static native boolean nativeHasKeys(int deviceId, int sourceMask,
70 int[] keyCodes, boolean[] keyExists);
Jeff Browna41ca772010-08-11 14:46:32 -070071 private static native void nativeRegisterInputChannel(InputChannel inputChannel,
72 boolean monitor);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070073 private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
Jeff Brown6ec402b2010-07-28 15:48:59 -070074 private static native int nativeInjectInputEvent(InputEvent event,
75 int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
Jeff Brown349703e2010-06-22 01:27:15 -070076 private static native void nativeSetInputWindows(InputWindow[] windows);
77 private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
78 private static native void nativeSetFocusedApplication(InputApplication application);
Jeff Brown8d608662010-08-30 03:02:23 -070079 private static native InputDevice nativeGetInputDevice(int deviceId);
Jeff Brown57c59372010-09-21 18:22:55 -070080 private static native void nativeGetInputConfiguration(Configuration configuration);
Jeff Brown8d608662010-08-30 03:02:23 -070081 private static native int[] nativeGetInputDeviceIds();
Jeff Browne6504122010-09-27 14:52:15 -070082 private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
83 InputChannel toChannel);
Jeff Browne33348b2010-07-15 23:54:05 -070084 private static native String nativeDump();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070085
Jeff Brown7fbdc842010-06-17 20:52:56 -070086 // Input event injection constants defined in InputDispatcher.h.
87 static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
88 static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
89 static final int INPUT_EVENT_INJECTION_FAILED = 2;
90 static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
91
Jeff Brown6ec402b2010-07-28 15:48:59 -070092 // Input event injection synchronization modes defined in InputDispatcher.h
93 static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0;
94 static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1;
95 static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2;
96
Jeff Brown6d0fec22010-07-23 21:28:06 -070097 // Key states (may be returned by queries about the current state of a
98 // particular key code, scan code or switch).
99
100 /** The key state is unknown or the requested key itself is not supported. */
101 public static final int KEY_STATE_UNKNOWN = -1;
102
103 /** The key is up. /*/
104 public static final int KEY_STATE_UP = 0;
105
106 /** The key is down. */
107 public static final int KEY_STATE_DOWN = 1;
108
109 /** The key is down but is a virtual key press that is being emulated by the system. */
110 public static final int KEY_STATE_VIRTUAL = 2;
111
Jeff Browne33348b2010-07-15 23:54:05 -0700112 public InputManager(Context context, WindowManagerService windowManagerService) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700113 this.mContext = context;
114 this.mWindowManagerService = windowManagerService;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700115
116 this.mCallbacks = new Callbacks();
117
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700118 init();
119 }
120
121 private void init() {
122 Slog.i(TAG, "Initializing input manager");
123 nativeInit(mCallbacks);
124 }
125
126 public void start() {
127 Slog.i(TAG, "Starting input manager");
128 nativeStart();
129 }
130
131 public void setDisplaySize(int displayId, int width, int height) {
132 if (width <= 0 || height <= 0) {
133 throw new IllegalArgumentException("Invalid display id or dimensions.");
134 }
135
Jeff Brownb6997262010-10-08 22:31:17 -0700136 if (DEBUG) {
137 Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height);
138 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700139 nativeSetDisplaySize(displayId, width, height);
140 }
141
142 public void setDisplayOrientation(int displayId, int rotation) {
143 if (rotation < Surface.ROTATION_0 || rotation > Surface.ROTATION_270) {
144 throw new IllegalArgumentException("Invalid rotation.");
145 }
146
Jeff Brownb6997262010-10-08 22:31:17 -0700147 if (DEBUG) {
148 Slog.d(TAG, "Setting display #" + displayId + " orientation to " + rotation);
149 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700150 nativeSetDisplayOrientation(displayId, rotation);
151 }
152
153 public void getInputConfiguration(Configuration config) {
154 if (config == null) {
155 throw new IllegalArgumentException("config must not be null.");
156 }
157
Jeff Brown57c59372010-09-21 18:22:55 -0700158 nativeGetInputConfiguration(config);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700159 }
160
Jeff Brown6d0fec22010-07-23 21:28:06 -0700161 /**
162 * Gets the current state of a key or button by key code.
163 * @param deviceId The input device id, or -1 to consult all devices.
164 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
165 * consider all input sources. An input device is consulted if at least one of its
166 * non-class input source bits matches the specified source mask.
167 * @param keyCode The key code to check.
168 * @return The key state.
169 */
170 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
171 return nativeGetKeyCodeState(deviceId, sourceMask, keyCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700172 }
173
Jeff Brown6d0fec22010-07-23 21:28:06 -0700174 /**
175 * Gets the current state of a key or button by scan code.
176 * @param deviceId The input device id, or -1 to consult all devices.
177 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
178 * consider all input sources. An input device is consulted if at least one of its
179 * non-class input source bits matches the specified source mask.
180 * @param scanCode The scan code to check.
181 * @return The key state.
182 */
183 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
184 return nativeGetScanCodeState(deviceId, sourceMask, scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700185 }
186
Jeff Brown6d0fec22010-07-23 21:28:06 -0700187 /**
188 * Gets the current state of a switch by switch code.
189 * @param deviceId The input device id, or -1 to consult all devices.
190 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
191 * consider all input sources. An input device is consulted if at least one of its
192 * non-class input source bits matches the specified source mask.
193 * @param switchCode The switch code to check.
194 * @return The switch state.
195 */
196 public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
197 return nativeGetSwitchState(deviceId, sourceMask, switchCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700198 }
199
Jeff Brown6d0fec22010-07-23 21:28:06 -0700200 /**
201 * Determines whether the specified key codes are supported by a particular device.
202 * @param deviceId The input device id, or -1 to consult all devices.
203 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
204 * consider all input sources. An input device is consulted if at least one of its
205 * non-class input source bits matches the specified source mask.
206 * @param keyCodes The array of key codes to check.
207 * @param keyExists An array at least as large as keyCodes whose entries will be set
208 * to true or false based on the presence or absence of support for the corresponding
209 * key codes.
210 * @return True if the lookup was successful, false otherwise.
211 */
212 public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700213 if (keyCodes == null) {
214 throw new IllegalArgumentException("keyCodes must not be null.");
215 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700216 if (keyExists == null || keyExists.length < keyCodes.length) {
217 throw new IllegalArgumentException("keyExists must not be null and must be at "
218 + "least as large as keyCodes.");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700219 }
220
Jeff Brown6d0fec22010-07-23 21:28:06 -0700221 return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700222 }
223
Jeff Browna41ca772010-08-11 14:46:32 -0700224 /**
225 * Creates an input channel that will receive all input from the input dispatcher.
226 * @param inputChannelName The input channel name.
227 * @return The input channel.
228 */
229 public InputChannel monitorInput(String inputChannelName) {
230 if (inputChannelName == null) {
231 throw new IllegalArgumentException("inputChannelName must not be null.");
232 }
233
234 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
235 nativeRegisterInputChannel(inputChannels[0], true);
236 inputChannels[0].dispose(); // don't need to retain the Java object reference
237 return inputChannels[1];
238 }
239
240 /**
241 * Registers an input channel so that it can be used as an input event target.
242 * @param inputChannel The input channel to register.
243 */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700244 public void registerInputChannel(InputChannel inputChannel) {
245 if (inputChannel == null) {
246 throw new IllegalArgumentException("inputChannel must not be null.");
247 }
248
Jeff Browna41ca772010-08-11 14:46:32 -0700249 nativeRegisterInputChannel(inputChannel, false);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700250 }
251
Jeff Browna41ca772010-08-11 14:46:32 -0700252 /**
253 * Unregisters an input channel.
254 * @param inputChannel The input channel to unregister.
255 */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700256 public void unregisterInputChannel(InputChannel inputChannel) {
257 if (inputChannel == null) {
258 throw new IllegalArgumentException("inputChannel must not be null.");
259 }
260
261 nativeUnregisterInputChannel(inputChannel);
262 }
263
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700264 /**
Jeff Brown6ec402b2010-07-28 15:48:59 -0700265 * Injects an input event into the event system on behalf of an application.
266 * The synchronization mode determines whether the method blocks while waiting for
267 * input injection to proceed.
268 *
269 * {@link #INPUT_EVENT_INJECTION_SYNC_NONE} never blocks. Injection is asynchronous and
270 * is assumed always to be successful.
271 *
272 * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT} waits for previous events to be
273 * dispatched so that the input dispatcher can determine whether input event injection will
274 * be permitted based on the current input focus. Does not wait for the input event to
275 * finish processing.
276 *
277 * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH} waits for the input event to
278 * be completely processed.
279 *
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700280 * @param event The event to inject.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700281 * @param injectorPid The pid of the injecting application.
282 * @param injectorUid The uid of the injecting application.
Jeff Brown6ec402b2010-07-28 15:48:59 -0700283 * @param syncMode The synchronization mode.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700284 * @param timeoutMillis The injection timeout in milliseconds.
285 * @return One of the INPUT_EVENT_INJECTION_XXX constants.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700286 */
Jeff Brown6ec402b2010-07-28 15:48:59 -0700287 public int injectInputEvent(InputEvent event, int injectorPid, int injectorUid,
288 int syncMode, int timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700289 if (event == null) {
290 throw new IllegalArgumentException("event must not be null");
291 }
292 if (injectorPid < 0 || injectorUid < 0) {
293 throw new IllegalArgumentException("injectorPid and injectorUid must not be negative.");
294 }
295 if (timeoutMillis <= 0) {
296 throw new IllegalArgumentException("timeoutMillis must be positive");
297 }
Jeff Brown6ec402b2010-07-28 15:48:59 -0700298
299 return nativeInjectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700300 }
301
Jeff Brown8d608662010-08-30 03:02:23 -0700302 /**
303 * Gets information about the input device with the specified id.
304 * @param id The device id.
305 * @return The input device or null if not found.
306 */
307 public InputDevice getInputDevice(int deviceId) {
308 return nativeGetInputDevice(deviceId);
309 }
310
311 /**
312 * Gets the ids of all input devices in the system.
313 * @return The input device ids.
314 */
315 public int[] getInputDeviceIds() {
316 return nativeGetInputDeviceIds();
317 }
318
Jeff Brown349703e2010-06-22 01:27:15 -0700319 public void setInputWindows(InputWindow[] windows) {
320 nativeSetInputWindows(windows);
321 }
322
323 public void setFocusedApplication(InputApplication application) {
324 nativeSetFocusedApplication(application);
325 }
326
Jeff Brown349703e2010-06-22 01:27:15 -0700327 public void setInputDispatchMode(boolean enabled, boolean frozen) {
328 nativeSetInputDispatchMode(enabled, frozen);
329 }
330
Jeff Browne6504122010-09-27 14:52:15 -0700331 /**
332 * Atomically transfers touch focus from one window to another as identified by
333 * their input channels. It is possible for multiple windows to have
334 * touch focus if they support split touch dispatch
335 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
336 * method only transfers touch focus of the specified window without affecting
337 * other windows that may also have touch focus at the same time.
338 * @param fromChannel The channel of a window that currently has touch focus.
339 * @param toChannel The channel of the window that should receive touch focus in
340 * place of the first.
341 * @return True if the transfer was successful. False if the window with the
342 * specified channel did not actually have touch focus at the time of the request.
343 */
344 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
345 if (fromChannel == null) {
346 throw new IllegalArgumentException("fromChannel must not be null.");
347 }
348 if (toChannel == null) {
349 throw new IllegalArgumentException("toChannel must not be null.");
350 }
351 return nativeTransferTouchFocus(fromChannel, toChannel);
352 }
353
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700354 public void dump(PrintWriter pw) {
Jeff Browne33348b2010-07-15 23:54:05 -0700355 String dumpStr = nativeDump();
356 if (dumpStr != null) {
357 pw.println(dumpStr);
358 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700359 }
360
361 private static final class VirtualKeyDefinition {
362 public int scanCode;
363
364 // configured position data, specified in display coords
365 public int centerX;
366 public int centerY;
367 public int width;
368 public int height;
369 }
370
Jeff Brown8d608662010-08-30 03:02:23 -0700371 private static final class InputDeviceCalibration {
372 public String[] keys;
373 public String[] values;
374 }
375
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700376 /*
377 * Callbacks from native.
378 */
379 private class Callbacks {
380 static final String TAG = "InputManager-Callbacks";
381
382 private static final boolean DEBUG_VIRTUAL_KEYS = false;
383 private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
Jeff Brown8d608662010-08-30 03:02:23 -0700384 private static final String CALIBRATION_DIR_PATH = "usr/idc/";
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700385
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700386 @SuppressWarnings("unused")
Jeff Brown57c59372010-09-21 18:22:55 -0700387 public void notifyConfigurationChanged(long whenNanos) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700388 mWindowManagerService.sendNewConfiguration();
389 }
390
391 @SuppressWarnings("unused")
392 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700393 mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700394 }
395
396 @SuppressWarnings("unused")
Jeff Brown7fbdc842010-06-17 20:52:56 -0700397 public void notifyInputChannelBroken(InputChannel inputChannel) {
Jeff Brown349703e2010-06-22 01:27:15 -0700398 mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputChannel);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700399 }
Jeff Brown7fbdc842010-06-17 20:52:56 -0700400
401 @SuppressWarnings("unused")
Jeff Brown519e0242010-09-15 15:18:56 -0700402 public long notifyANR(Object token, InputChannel inputChannel) {
403 return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel);
Jeff Brown349703e2010-06-22 01:27:15 -0700404 }
405
406 @SuppressWarnings("unused")
Jeff Brown4d396052010-10-29 21:50:21 -0700407 public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
408 int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700409 return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
Jeff Brown4d396052010-10-29 21:50:21 -0700410 whenNanos, action, flags, keyCode, scanCode, policyFlags, isScreenOn);
Jeff Brown349703e2010-06-22 01:27:15 -0700411 }
412
413 @SuppressWarnings("unused")
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700414 public boolean interceptKeyBeforeDispatching(InputChannel focus, int action,
Jeff Brown4d396052010-10-29 21:50:21 -0700415 int flags, int keyCode, int scanCode, int metaState, int repeatCount,
416 int policyFlags) {
Jeff Brown349703e2010-06-22 01:27:15 -0700417 return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus,
Jeff Brown4d396052010-10-29 21:50:21 -0700418 action, flags, keyCode, scanCode, metaState, repeatCount, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -0700419 }
420
421 @SuppressWarnings("unused")
422 public boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
423 return mContext.checkPermission(
424 android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid)
425 == PackageManager.PERMISSION_GRANTED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700426 }
427
428 @SuppressWarnings("unused")
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700429 public boolean filterTouchEvents() {
430 return mContext.getResources().getBoolean(
431 com.android.internal.R.bool.config_filterTouchEvents);
432 }
433
434 @SuppressWarnings("unused")
435 public boolean filterJumpyTouchEvents() {
436 return mContext.getResources().getBoolean(
437 com.android.internal.R.bool.config_filterJumpyTouchEvents);
438 }
439
440 @SuppressWarnings("unused")
441 public VirtualKeyDefinition[] getVirtualKeyDefinitions(String deviceName) {
442 ArrayList<VirtualKeyDefinition> keys = new ArrayList<VirtualKeyDefinition>();
443
444 try {
445 FileInputStream fis = new FileInputStream(
446 "/sys/board_properties/virtualkeys." + deviceName);
447 InputStreamReader isr = new InputStreamReader(fis);
448 BufferedReader br = new BufferedReader(isr, 2048);
449 String str = br.readLine();
450 if (str != null) {
451 String[] it = str.split(":");
452 if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "***** VIRTUAL KEYS: " + it);
453 final int N = it.length-6;
454 for (int i=0; i<=N; i+=6) {
455 if (!"0x01".equals(it[i])) {
Jeff Brown8d608662010-08-30 03:02:23 -0700456 Slog.w(TAG, "Unknown virtual key type at elem #"
457 + i + ": " + it[i] + " for device " + deviceName);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700458 continue;
459 }
460 try {
461 VirtualKeyDefinition key = new VirtualKeyDefinition();
462 key.scanCode = Integer.parseInt(it[i+1]);
463 key.centerX = Integer.parseInt(it[i+2]);
464 key.centerY = Integer.parseInt(it[i+3]);
465 key.width = Integer.parseInt(it[i+4]);
466 key.height = Integer.parseInt(it[i+5]);
467 if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Virtual key "
468 + key.scanCode + ": center=" + key.centerX + ","
469 + key.centerY + " size=" + key.width + "x"
470 + key.height);
471 keys.add(key);
472 } catch (NumberFormatException e) {
Jeff Brown8d608662010-08-30 03:02:23 -0700473 Slog.w(TAG, "Bad number in virtual key definition at region "
474 + i + " in: " + str + " for device " + deviceName, e);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700475 }
476 }
477 }
478 br.close();
479 } catch (FileNotFoundException e) {
Jeff Brown8d608662010-08-30 03:02:23 -0700480 Slog.i(TAG, "No virtual keys found for device " + deviceName + ".");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700481 } catch (IOException e) {
Jeff Brown8d608662010-08-30 03:02:23 -0700482 Slog.w(TAG, "Error reading virtual keys for device " + deviceName + ".", e);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700483 }
484
485 return keys.toArray(new VirtualKeyDefinition[keys.size()]);
486 }
487
488 @SuppressWarnings("unused")
Jeff Brown8d608662010-08-30 03:02:23 -0700489 public InputDeviceCalibration getInputDeviceCalibration(String deviceName) {
490 // Calibration is specified as a sequence of colon-delimited key value pairs.
491 Properties properties = new Properties();
492 File calibrationFile = new File(Environment.getRootDirectory(),
493 CALIBRATION_DIR_PATH + deviceName + ".idc");
494 if (calibrationFile.exists()) {
495 try {
496 properties.load(new FileInputStream(calibrationFile));
497 } catch (IOException ex) {
498 Slog.w(TAG, "Error reading input device calibration properties for device "
499 + deviceName + " from " + calibrationFile + ".", ex);
500 }
501 } else {
502 Slog.i(TAG, "No input device calibration properties found for device "
503 + deviceName + ".");
504 return null;
505 }
506
507 InputDeviceCalibration calibration = new InputDeviceCalibration();
508 calibration.keys = properties.keySet().toArray(new String[properties.size()]);
509 calibration.values = properties.values().toArray(new String[properties.size()]);
510 return calibration;
511 }
512
513 @SuppressWarnings("unused")
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700514 public String[] getExcludedDeviceNames() {
515 ArrayList<String> names = new ArrayList<String>();
516
517 // Read partner-provided list of excluded input devices
518 XmlPullParser parser = null;
519 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
520 File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
521 FileReader confreader = null;
522 try {
523 confreader = new FileReader(confFile);
524 parser = Xml.newPullParser();
525 parser.setInput(confreader);
526 XmlUtils.beginDocument(parser, "devices");
527
528 while (true) {
529 XmlUtils.nextElement(parser);
530 if (!"device".equals(parser.getName())) {
531 break;
532 }
533 String name = parser.getAttributeValue(null, "name");
534 if (name != null) {
535 names.add(name);
536 }
537 }
538 } catch (FileNotFoundException e) {
539 // It's ok if the file does not exist.
540 } catch (Exception e) {
541 Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
542 } finally {
543 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
544 }
545
546 return names.toArray(new String[names.size()]);
547 }
Jeff Brownae9fc032010-08-18 15:51:08 -0700548
549 @SuppressWarnings("unused")
550 public int getMaxEventsPerSecond() {
551 int result = 0;
552 try {
553 result = Integer.parseInt(SystemProperties.get("windowsmgr.max_events_per_sec"));
554 } catch (NumberFormatException e) {
555 }
556 if (result < 1) {
Jeff Brown3d8c9bd2010-08-18 17:48:53 -0700557 result = 60;
Jeff Brownae9fc032010-08-18 15:51:08 -0700558 }
559 return result;
560 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700561 }
562}