blob: b0978a3f251cf0e9e40f4f1c148a7416d9418293 [file] [log] [blame]
Jeff Brown46b9ac02010-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
Dianne Hackborna924dc0d2011-02-17 14:22:17 -080017package com.android.server.wm;
Jeff Brown46b9ac02010-04-22 18:58:52 -070018
19import com.android.internal.util.XmlUtils;
Jeff Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070025import android.content.res.Configuration;
Jeff Brownb4ff35d2011-01-02 16:37:43 -080026import android.content.res.Resources;
27import android.content.res.TypedArray;
28import android.content.res.XmlResourceParser;
29import android.graphics.Bitmap;
30import android.graphics.drawable.BitmapDrawable;
31import android.graphics.drawable.Drawable;
Jeff Brown46b9ac02010-04-22 18:58:52 -070032import android.os.Environment;
Jeff Brown05dc66a2011-03-02 14:41:58 -080033import android.os.Looper;
34import android.os.MessageQueue;
Jeff Brownae9fc032010-08-18 15:51:08 -070035import android.os.SystemProperties;
Jeff Brown46b9ac02010-04-22 18:58:52 -070036import android.util.Slog;
37import android.util.Xml;
38import android.view.InputChannel;
Jeff Brown8d608662010-08-30 03:02:23 -070039import android.view.InputDevice;
Jeff Brown6ec402b2010-07-28 15:48:59 -070040import android.view.InputEvent;
Jeff Brown1f245102010-11-18 20:53:46 -080041import android.view.KeyEvent;
Jeff Brown46b9ac02010-04-22 18:58:52 -070042import android.view.Surface;
Jeff Browna4547672011-03-02 21:38:11 -080043import android.view.ViewConfiguration;
Jeff Brown83c09682010-12-23 17:50:18 -080044import android.view.WindowManager;
Jeff Brown0029c662011-03-30 02:25:18 -070045import android.view.WindowManagerPolicy;
Jeff Brown46b9ac02010-04-22 18:58:52 -070046
Jeff Brown46b9ac02010-04-22 18:58:52 -070047import java.io.File;
Jeff Brown46b9ac02010-04-22 18:58:52 -070048import java.io.FileNotFoundException;
49import java.io.FileReader;
50import java.io.IOException;
Jeff Brown46b9ac02010-04-22 18:58:52 -070051import java.io.PrintWriter;
52import java.util.ArrayList;
53
54/*
55 * Wraps the C++ InputManager and provides its callbacks.
Jeff Brown46b9ac02010-04-22 18:58:52 -070056 */
57public class InputManager {
58 static final String TAG = "InputManager";
59
Jeff Brownb6997262010-10-08 22:31:17 -070060 private static final boolean DEBUG = false;
61
Jeff Brown46b9ac02010-04-22 18:58:52 -070062 private final Callbacks mCallbacks;
63 private final Context mContext;
64 private final WindowManagerService mWindowManagerService;
Jeff Brown46b9ac02010-04-22 18:58:52 -070065
Jeff Brown05dc66a2011-03-02 14:41:58 -080066 private static native void nativeInit(Callbacks callbacks, MessageQueue messageQueue);
Jeff Brown46b9ac02010-04-22 18:58:52 -070067 private static native void nativeStart();
68 private static native void nativeSetDisplaySize(int displayId, int width, int height);
69 private static native void nativeSetDisplayOrientation(int displayId, int rotation);
70
Jeff Brown6d0fec22010-07-23 21:28:06 -070071 private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
Jeff Brown46b9ac02010-04-22 18:58:52 -070072 int scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -070073 private static native int nativeGetKeyCodeState(int deviceId, int sourceMask,
Jeff Brown46b9ac02010-04-22 18:58:52 -070074 int keyCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -070075 private static native int nativeGetSwitchState(int deviceId, int sourceMask,
Jeff Brown46b9ac02010-04-22 18:58:52 -070076 int sw);
Jeff Brown6d0fec22010-07-23 21:28:06 -070077 private static native boolean nativeHasKeys(int deviceId, int sourceMask,
78 int[] keyCodes, boolean[] keyExists);
Jeff Browna41ca772010-08-11 14:46:32 -070079 private static native void nativeRegisterInputChannel(InputChannel inputChannel,
Jeff Brown928e0542011-01-10 11:17:36 -080080 InputWindowHandle inputWindowHandle, boolean monitor);
Jeff Brown46b9ac02010-04-22 18:58:52 -070081 private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
Jeff Brown0029c662011-03-30 02:25:18 -070082 private static native void nativeSetInputFilterEnabled(boolean enable);
Jeff Brown6ec402b2010-07-28 15:48:59 -070083 private static native int nativeInjectInputEvent(InputEvent event,
Jeff Brown0029c662011-03-30 02:25:18 -070084 int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
85 int policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -070086 private static native void nativeSetInputWindows(InputWindow[] windows);
87 private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
Jeff Brown05dc66a2011-03-02 14:41:58 -080088 private static native void nativeSetSystemUiVisibility(int visibility);
Jeff Brown349703e2010-06-22 01:27:15 -070089 private static native void nativeSetFocusedApplication(InputApplication application);
Jeff Brown8d608662010-08-30 03:02:23 -070090 private static native InputDevice nativeGetInputDevice(int deviceId);
Jeff Brown57c59372010-09-21 18:22:55 -070091 private static native void nativeGetInputConfiguration(Configuration configuration);
Jeff Brown8d608662010-08-30 03:02:23 -070092 private static native int[] nativeGetInputDeviceIds();
Jeff Browne6504122010-09-27 14:52:15 -070093 private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
94 InputChannel toChannel);
Jeff Browne33348b2010-07-15 23:54:05 -070095 private static native String nativeDump();
Jeff Brown46b9ac02010-04-22 18:58:52 -070096
Jeff Brown7fbdc842010-06-17 20:52:56 -070097 // Input event injection constants defined in InputDispatcher.h.
98 static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
99 static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
100 static final int INPUT_EVENT_INJECTION_FAILED = 2;
101 static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
102
Jeff Brown6ec402b2010-07-28 15:48:59 -0700103 // Input event injection synchronization modes defined in InputDispatcher.h
104 static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0;
105 static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1;
106 static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2;
107
Jeff Brown6d0fec22010-07-23 21:28:06 -0700108 // Key states (may be returned by queries about the current state of a
109 // particular key code, scan code or switch).
110
111 /** The key state is unknown or the requested key itself is not supported. */
112 public static final int KEY_STATE_UNKNOWN = -1;
113
114 /** The key is up. /*/
115 public static final int KEY_STATE_UP = 0;
116
117 /** The key is down. */
118 public static final int KEY_STATE_DOWN = 1;
119
120 /** The key is down but is a virtual key press that is being emulated by the system. */
121 public static final int KEY_STATE_VIRTUAL = 2;
122
Jeff Brown0029c662011-03-30 02:25:18 -0700123 // State for the currently installed input filter.
124 final Object mInputFilterLock = new Object();
125 InputFilter mInputFilter;
126 InputFilterHost mInputFilterHost;
127
Jeff Browne33348b2010-07-15 23:54:05 -0700128 public InputManager(Context context, WindowManagerService windowManagerService) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700129 this.mContext = context;
130 this.mWindowManagerService = windowManagerService;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700131 this.mCallbacks = new Callbacks();
Jeff Brown05dc66a2011-03-02 14:41:58 -0800132
133 Looper looper = windowManagerService.mH.getLooper();
134
Jeff Brown46b9ac02010-04-22 18:58:52 -0700135 Slog.i(TAG, "Initializing input manager");
Jeff Brown05dc66a2011-03-02 14:41:58 -0800136 nativeInit(mCallbacks, looper.getQueue());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700137 }
138
139 public void start() {
140 Slog.i(TAG, "Starting input manager");
141 nativeStart();
142 }
143
144 public void setDisplaySize(int displayId, int width, int height) {
145 if (width <= 0 || height <= 0) {
146 throw new IllegalArgumentException("Invalid display id or dimensions.");
147 }
148
Jeff Brownb6997262010-10-08 22:31:17 -0700149 if (DEBUG) {
150 Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height);
151 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700152 nativeSetDisplaySize(displayId, width, height);
153 }
154
155 public void setDisplayOrientation(int displayId, int rotation) {
156 if (rotation < Surface.ROTATION_0 || rotation > Surface.ROTATION_270) {
157 throw new IllegalArgumentException("Invalid rotation.");
158 }
159
Jeff Brownb6997262010-10-08 22:31:17 -0700160 if (DEBUG) {
161 Slog.d(TAG, "Setting display #" + displayId + " orientation to " + rotation);
162 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700163 nativeSetDisplayOrientation(displayId, rotation);
164 }
165
166 public void getInputConfiguration(Configuration config) {
167 if (config == null) {
168 throw new IllegalArgumentException("config must not be null.");
169 }
170
Jeff Brown57c59372010-09-21 18:22:55 -0700171 nativeGetInputConfiguration(config);
Jeff Brown46b9ac02010-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 key 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 keyCode The key code to check.
181 * @return The key state.
182 */
183 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
184 return nativeGetKeyCodeState(deviceId, sourceMask, keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700185 }
186
Jeff Brown6d0fec22010-07-23 21:28:06 -0700187 /**
188 * Gets the current state of a key or button by scan 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 scanCode The scan code to check.
194 * @return The key state.
195 */
196 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
197 return nativeGetScanCodeState(deviceId, sourceMask, scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700198 }
199
Jeff Brown6d0fec22010-07-23 21:28:06 -0700200 /**
201 * Gets the current state of a switch by switch code.
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 switchCode The switch code to check.
207 * @return The switch state.
208 */
209 public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
210 return nativeGetSwitchState(deviceId, sourceMask, switchCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700211 }
212
Jeff Brown6d0fec22010-07-23 21:28:06 -0700213 /**
214 * Determines whether the specified key codes are supported by a particular device.
215 * @param deviceId The input device id, or -1 to consult all devices.
216 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
217 * consider all input sources. An input device is consulted if at least one of its
218 * non-class input source bits matches the specified source mask.
219 * @param keyCodes The array of key codes to check.
220 * @param keyExists An array at least as large as keyCodes whose entries will be set
221 * to true or false based on the presence or absence of support for the corresponding
222 * key codes.
223 * @return True if the lookup was successful, false otherwise.
224 */
225 public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700226 if (keyCodes == null) {
227 throw new IllegalArgumentException("keyCodes must not be null.");
228 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700229 if (keyExists == null || keyExists.length < keyCodes.length) {
230 throw new IllegalArgumentException("keyExists must not be null and must be at "
231 + "least as large as keyCodes.");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700232 }
233
Jeff Brown6d0fec22010-07-23 21:28:06 -0700234 return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700235 }
236
Jeff Browna41ca772010-08-11 14:46:32 -0700237 /**
238 * Creates an input channel that will receive all input from the input dispatcher.
239 * @param inputChannelName The input channel name.
240 * @return The input channel.
241 */
242 public InputChannel monitorInput(String inputChannelName) {
243 if (inputChannelName == null) {
244 throw new IllegalArgumentException("inputChannelName must not be null.");
245 }
246
247 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
Jeff Brown928e0542011-01-10 11:17:36 -0800248 nativeRegisterInputChannel(inputChannels[0], null, true);
Jeff Browna41ca772010-08-11 14:46:32 -0700249 inputChannels[0].dispose(); // don't need to retain the Java object reference
250 return inputChannels[1];
251 }
252
253 /**
254 * Registers an input channel so that it can be used as an input event target.
255 * @param inputChannel The input channel to register.
Jeff Brown928e0542011-01-10 11:17:36 -0800256 * @param inputWindowHandle The handle of the input window associated with the
257 * input channel, or null if none.
Jeff Browna41ca772010-08-11 14:46:32 -0700258 */
Jeff Brown928e0542011-01-10 11:17:36 -0800259 public void registerInputChannel(InputChannel inputChannel,
260 InputWindowHandle inputWindowHandle) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700261 if (inputChannel == null) {
262 throw new IllegalArgumentException("inputChannel must not be null.");
263 }
264
Jeff Brown928e0542011-01-10 11:17:36 -0800265 nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700266 }
267
Jeff Browna41ca772010-08-11 14:46:32 -0700268 /**
269 * Unregisters an input channel.
270 * @param inputChannel The input channel to unregister.
271 */
Jeff Brown46b9ac02010-04-22 18:58:52 -0700272 public void unregisterInputChannel(InputChannel inputChannel) {
273 if (inputChannel == null) {
274 throw new IllegalArgumentException("inputChannel must not be null.");
275 }
276
277 nativeUnregisterInputChannel(inputChannel);
278 }
Jeff Brown0029c662011-03-30 02:25:18 -0700279
280 /**
281 * Sets an input filter that will receive all input events before they are dispatched.
282 * The input filter may then reinterpret input events or inject new ones.
283 *
284 * To ensure consistency, the input dispatcher automatically drops all events
285 * in progress whenever an input filter is installed or uninstalled. After an input
286 * filter is uninstalled, it can no longer send input events unless it is reinstalled.
287 * Any events it attempts to send after it has been uninstalled will be dropped.
288 *
289 * @param filter The input filter, or null to remove the current filter.
290 */
291 public void setInputFilter(InputFilter filter) {
292 synchronized (mInputFilterLock) {
293 final InputFilter oldFilter = mInputFilter;
294 if (oldFilter == filter) {
295 return; // nothing to do
296 }
297
298 if (oldFilter != null) {
299 mInputFilter = null;
300 mInputFilterHost.disconnectLocked();
301 mInputFilterHost = null;
302 oldFilter.uninstall();
303 }
304
305 if (filter != null) {
306 mInputFilter = filter;
307 mInputFilterHost = new InputFilterHost();
308 filter.install(mInputFilterHost);
309 }
310
311 nativeSetInputFilterEnabled(filter != null);
312 }
313 }
314
Jeff Brown46b9ac02010-04-22 18:58:52 -0700315 /**
Jeff Brown6ec402b2010-07-28 15:48:59 -0700316 * Injects an input event into the event system on behalf of an application.
317 * The synchronization mode determines whether the method blocks while waiting for
318 * input injection to proceed.
319 *
320 * {@link #INPUT_EVENT_INJECTION_SYNC_NONE} never blocks. Injection is asynchronous and
321 * is assumed always to be successful.
322 *
323 * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT} waits for previous events to be
324 * dispatched so that the input dispatcher can determine whether input event injection will
325 * be permitted based on the current input focus. Does not wait for the input event to
326 * finish processing.
327 *
328 * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH} waits for the input event to
329 * be completely processed.
330 *
Jeff Brown46b9ac02010-04-22 18:58:52 -0700331 * @param event The event to inject.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700332 * @param injectorPid The pid of the injecting application.
333 * @param injectorUid The uid of the injecting application.
Jeff Brown6ec402b2010-07-28 15:48:59 -0700334 * @param syncMode The synchronization mode.
Jeff Brown7fbdc842010-06-17 20:52:56 -0700335 * @param timeoutMillis The injection timeout in milliseconds.
336 * @return One of the INPUT_EVENT_INJECTION_XXX constants.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700337 */
Jeff Brown6ec402b2010-07-28 15:48:59 -0700338 public int injectInputEvent(InputEvent event, int injectorPid, int injectorUid,
339 int syncMode, int timeoutMillis) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700340 if (event == null) {
341 throw new IllegalArgumentException("event must not be null");
342 }
343 if (injectorPid < 0 || injectorUid < 0) {
344 throw new IllegalArgumentException("injectorPid and injectorUid must not be negative.");
345 }
346 if (timeoutMillis <= 0) {
347 throw new IllegalArgumentException("timeoutMillis must be positive");
348 }
Jeff Brown6ec402b2010-07-28 15:48:59 -0700349
Jeff Brown0029c662011-03-30 02:25:18 -0700350 return nativeInjectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis,
351 WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700352 }
Jeff Brown0029c662011-03-30 02:25:18 -0700353
Jeff Brown8d608662010-08-30 03:02:23 -0700354 /**
355 * Gets information about the input device with the specified id.
356 * @param id The device id.
357 * @return The input device or null if not found.
358 */
359 public InputDevice getInputDevice(int deviceId) {
360 return nativeGetInputDevice(deviceId);
361 }
362
363 /**
364 * Gets the ids of all input devices in the system.
365 * @return The input device ids.
366 */
367 public int[] getInputDeviceIds() {
368 return nativeGetInputDeviceIds();
369 }
370
Jeff Brown349703e2010-06-22 01:27:15 -0700371 public void setInputWindows(InputWindow[] windows) {
372 nativeSetInputWindows(windows);
373 }
374
375 public void setFocusedApplication(InputApplication application) {
376 nativeSetFocusedApplication(application);
377 }
378
Jeff Brown349703e2010-06-22 01:27:15 -0700379 public void setInputDispatchMode(boolean enabled, boolean frozen) {
380 nativeSetInputDispatchMode(enabled, frozen);
381 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800382
383 public void setSystemUiVisibility(int visibility) {
384 nativeSetSystemUiVisibility(visibility);
385 }
386
Jeff Browne6504122010-09-27 14:52:15 -0700387 /**
388 * Atomically transfers touch focus from one window to another as identified by
389 * their input channels. It is possible for multiple windows to have
390 * touch focus if they support split touch dispatch
391 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
392 * method only transfers touch focus of the specified window without affecting
393 * other windows that may also have touch focus at the same time.
394 * @param fromChannel The channel of a window that currently has touch focus.
395 * @param toChannel The channel of the window that should receive touch focus in
396 * place of the first.
397 * @return True if the transfer was successful. False if the window with the
398 * specified channel did not actually have touch focus at the time of the request.
399 */
400 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
401 if (fromChannel == null) {
402 throw new IllegalArgumentException("fromChannel must not be null.");
403 }
404 if (toChannel == null) {
405 throw new IllegalArgumentException("toChannel must not be null.");
406 }
407 return nativeTransferTouchFocus(fromChannel, toChannel);
408 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800409
Jeff Brown46b9ac02010-04-22 18:58:52 -0700410 public void dump(PrintWriter pw) {
Jeff Browne33348b2010-07-15 23:54:05 -0700411 String dumpStr = nativeDump();
412 if (dumpStr != null) {
413 pw.println(dumpStr);
414 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700415 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800416
Jeff Brown0029c662011-03-30 02:25:18 -0700417 private final class InputFilterHost implements InputFilter.Host {
418 private boolean mDisconnected;
419
420 public void disconnectLocked() {
421 mDisconnected = true;
422 }
423
424 public void sendInputEvent(InputEvent event, int policyFlags) {
425 if (event == null) {
426 throw new IllegalArgumentException("event must not be null");
427 }
428
429 synchronized (mInputFilterLock) {
430 if (!mDisconnected) {
431 nativeInjectInputEvent(event, 0, 0, INPUT_EVENT_INJECTION_SYNC_NONE, 0,
432 policyFlags | WindowManagerPolicy.FLAG_FILTERED);
433 }
434 }
435 }
436 }
437
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800438 private static final class PointerIcon {
439 public Bitmap bitmap;
440 public float hotSpotX;
441 public float hotSpotY;
442
443 public static PointerIcon load(Resources resources, int resourceId) {
444 PointerIcon icon = new PointerIcon();
445
446 XmlResourceParser parser = resources.getXml(resourceId);
447 final int bitmapRes;
448 try {
449 XmlUtils.beginDocument(parser, "pointer-icon");
450
451 TypedArray a = resources.obtainAttributes(
452 parser, com.android.internal.R.styleable.PointerIcon);
453 bitmapRes = a.getResourceId(com.android.internal.R.styleable.PointerIcon_bitmap, 0);
454 icon.hotSpotX = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
455 icon.hotSpotY = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
456 a.recycle();
457 } catch (Exception ex) {
458 Slog.e(TAG, "Exception parsing pointer icon resource.", ex);
459 return null;
460 } finally {
461 parser.close();
462 }
463
464 if (bitmapRes == 0) {
465 Slog.e(TAG, "<pointer-icon> is missing bitmap attribute");
466 return null;
467 }
468
469 Drawable drawable = resources.getDrawable(bitmapRes);
470 if (!(drawable instanceof BitmapDrawable)) {
471 Slog.e(TAG, "<pointer-icon> bitmap attribute must refer to a bitmap drawable");
472 return null;
473 }
474
475 icon.bitmap = ((BitmapDrawable)drawable).getBitmap();
476 return icon;
477 }
478 }
479
Jeff Brown46b9ac02010-04-22 18:58:52 -0700480 /*
481 * Callbacks from native.
482 */
Jeff Brown0029c662011-03-30 02:25:18 -0700483 private final class Callbacks {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700484 static final String TAG = "InputManager-Callbacks";
485
486 private static final boolean DEBUG_VIRTUAL_KEYS = false;
487 private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
Jeff Brown8d608662010-08-30 03:02:23 -0700488 private static final String CALIBRATION_DIR_PATH = "usr/idc/";
Jeff Brown46b9ac02010-04-22 18:58:52 -0700489
Jeff Brown46b9ac02010-04-22 18:58:52 -0700490 @SuppressWarnings("unused")
Jeff Brown57c59372010-09-21 18:22:55 -0700491 public void notifyConfigurationChanged(long whenNanos) {
Jeff Brownb09abc12011-01-13 21:08:27 -0800492 mWindowManagerService.mInputMonitor.notifyConfigurationChanged();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700493 }
494
495 @SuppressWarnings("unused")
496 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700497 mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700498 }
499
500 @SuppressWarnings("unused")
Jeff Brown928e0542011-01-10 11:17:36 -0800501 public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
502 mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
Jeff Brown7fbdc842010-06-17 20:52:56 -0700503 }
Jeff Brown7fbdc842010-06-17 20:52:56 -0700504
505 @SuppressWarnings("unused")
Jeff Brown928e0542011-01-10 11:17:36 -0800506 public long notifyANR(InputApplicationHandle inputApplicationHandle,
507 InputWindowHandle inputWindowHandle) {
508 return mWindowManagerService.mInputMonitor.notifyANR(
509 inputApplicationHandle, inputWindowHandle);
Jeff Brown349703e2010-06-22 01:27:15 -0700510 }
Jeff Brown0029c662011-03-30 02:25:18 -0700511
512 @SuppressWarnings("unused")
513 final boolean filterInputEvent(InputEvent event, int policyFlags) {
514 synchronized (mInputFilterLock) {
515 if (mInputFilter != null) {
516 mInputFilter.filterInputEvent(event, policyFlags);
517 return false;
518 }
519 }
520 event.recycle();
521 return true;
522 }
523
Jeff Brown349703e2010-06-22 01:27:15 -0700524 @SuppressWarnings("unused")
Jeff Brown1f245102010-11-18 20:53:46 -0800525 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700526 return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
Jeff Brown1f245102010-11-18 20:53:46 -0800527 event, policyFlags, isScreenOn);
Jeff Brown349703e2010-06-22 01:27:15 -0700528 }
Jeff Brown56194eb2011-03-02 19:23:13 -0800529
530 @SuppressWarnings("unused")
531 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
532 return mWindowManagerService.mInputMonitor.interceptMotionBeforeQueueingWhenScreenOff(
533 policyFlags);
534 }
535
Jeff Brown349703e2010-06-22 01:27:15 -0700536 @SuppressWarnings("unused")
Jeff Brown928e0542011-01-10 11:17:36 -0800537 public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
Jeff Brown1f245102010-11-18 20:53:46 -0800538 KeyEvent event, int policyFlags) {
539 return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
540 focus, event, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -0700541 }
542
543 @SuppressWarnings("unused")
Jeff Brown928e0542011-01-10 11:17:36 -0800544 public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
Jeff Brown1f245102010-11-18 20:53:46 -0800545 KeyEvent event, int policyFlags) {
546 return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
547 focus, event, policyFlags);
Jeff Brown3915bb82010-11-05 15:02:16 -0700548 }
549
550 @SuppressWarnings("unused")
Jeff Brown349703e2010-06-22 01:27:15 -0700551 public boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
552 return mContext.checkPermission(
553 android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid)
554 == PackageManager.PERMISSION_GRANTED;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700555 }
556
557 @SuppressWarnings("unused")
Jeff Brown46b9ac02010-04-22 18:58:52 -0700558 public boolean filterTouchEvents() {
559 return mContext.getResources().getBoolean(
560 com.android.internal.R.bool.config_filterTouchEvents);
561 }
562
563 @SuppressWarnings("unused")
564 public boolean filterJumpyTouchEvents() {
565 return mContext.getResources().getBoolean(
566 com.android.internal.R.bool.config_filterJumpyTouchEvents);
567 }
Jeff Brownfe508922011-01-18 15:10:10 -0800568
569 @SuppressWarnings("unused")
570 public int getVirtualKeyQuietTimeMillis() {
571 return mContext.getResources().getInteger(
572 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
573 }
574
Jeff Brown46b9ac02010-04-22 18:58:52 -0700575 @SuppressWarnings("unused")
Jeff Brown46b9ac02010-04-22 18:58:52 -0700576 public String[] getExcludedDeviceNames() {
577 ArrayList<String> names = new ArrayList<String>();
578
579 // Read partner-provided list of excluded input devices
580 XmlPullParser parser = null;
581 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
582 File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
583 FileReader confreader = null;
584 try {
585 confreader = new FileReader(confFile);
586 parser = Xml.newPullParser();
587 parser.setInput(confreader);
588 XmlUtils.beginDocument(parser, "devices");
589
590 while (true) {
591 XmlUtils.nextElement(parser);
592 if (!"device".equals(parser.getName())) {
593 break;
594 }
595 String name = parser.getAttributeValue(null, "name");
596 if (name != null) {
597 names.add(name);
598 }
599 }
600 } catch (FileNotFoundException e) {
601 // It's ok if the file does not exist.
602 } catch (Exception e) {
603 Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
604 } finally {
605 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
606 }
607
608 return names.toArray(new String[names.size()]);
609 }
Jeff Browna4547672011-03-02 21:38:11 -0800610
611 @SuppressWarnings("unused")
612 public int getKeyRepeatTimeout() {
613 return ViewConfiguration.getKeyRepeatTimeout();
614 }
615
616 @SuppressWarnings("unused")
617 public int getKeyRepeatDelay() {
618 return ViewConfiguration.getKeyRepeatDelay();
619 }
620
Jeff Brownae9fc032010-08-18 15:51:08 -0700621 @SuppressWarnings("unused")
622 public int getMaxEventsPerSecond() {
623 int result = 0;
624 try {
625 result = Integer.parseInt(SystemProperties.get("windowsmgr.max_events_per_sec"));
626 } catch (NumberFormatException e) {
627 }
628 if (result < 1) {
makarand.karvekar88dd6e62011-03-02 17:11:14 -0600629 result = 55;
Jeff Brownae9fc032010-08-18 15:51:08 -0700630 }
631 return result;
632 }
Jeff Brown83c09682010-12-23 17:50:18 -0800633
634 @SuppressWarnings("unused")
635 public int getPointerLayer() {
636 return mWindowManagerService.mPolicy.windowTypeToLayerLw(
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800637 WindowManager.LayoutParams.TYPE_POINTER)
Jeff Brown83c09682010-12-23 17:50:18 -0800638 * WindowManagerService.TYPE_LAYER_MULTIPLIER
639 + WindowManagerService.TYPE_LAYER_OFFSET;
640 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800641
642 @SuppressWarnings("unused")
643 public PointerIcon getPointerIcon() {
644 return PointerIcon.load(mContext.getResources(),
Jeff Brown909733c2011-01-13 21:51:44 -0800645 com.android.internal.R.drawable.pointer_arrow_icon);
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800646 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700647 }
648}