blob: 81b579d9174fb453c1cb64fa76c722ea0a395737 [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
Jeff Brown4532e612012-04-05 14:27:12 -070017package com.android.server.input;
Jeff Brown46b9ac02010-04-22 18:58:52 -070018
Jeff Brownca9bc702014-02-11 14:32:56 -080019import android.view.Display;
Jeff Browncf39bdf2012-05-18 14:41:19 -070020import com.android.internal.R;
Jeff Brown46b9ac02010-04-22 18:58:52 -070021import com.android.internal.util.XmlUtils;
Jeff Brown4ccb8232014-01-16 22:16:42 -080022import com.android.server.DisplayThread;
23import com.android.server.LocalServices;
Jeff Brown89ef0722011-08-10 16:25:21 -070024import com.android.server.Watchdog;
Jeff Brown46b9ac02010-04-22 18:58:52 -070025
26import org.xmlpull.v1.XmlPullParser;
27
Jeff Browna3bc5652012-04-17 11:42:25 -070028import android.Manifest;
Jeff Browncf39bdf2012-05-18 14:41:19 -070029import android.app.Notification;
30import android.app.NotificationManager;
31import android.app.PendingIntent;
Jeff Brown5bbd4b42012-04-20 19:28:00 -070032import android.bluetooth.BluetoothAdapter;
33import android.bluetooth.BluetoothDevice;
Jeff Brown6ec6f792012-04-17 16:52:41 -070034import android.content.BroadcastReceiver;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070035import android.content.ComponentName;
Jeff Brown46b9ac02010-04-22 18:58:52 -070036import android.content.Context;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070037import android.content.Intent;
Jeff Brown6ec6f792012-04-17 16:52:41 -070038import android.content.IntentFilter;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070039import android.content.pm.ActivityInfo;
Jeff Brown349703e2010-06-22 01:27:15 -070040import android.content.pm.PackageManager;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070041import android.content.pm.ResolveInfo;
42import android.content.pm.PackageManager.NameNotFoundException;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070043import android.content.res.Resources;
Jeff Brown6ec6f792012-04-17 16:52:41 -070044import android.content.res.Resources.NotFoundException;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070045import android.content.res.TypedArray;
46import android.content.res.XmlResourceParser;
Jeff Brown1a84fd12011-06-02 01:26:32 -070047import android.database.ContentObserver;
Jeff Brown4ccb8232014-01-16 22:16:42 -080048import android.hardware.display.DisplayViewport;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070049import android.hardware.input.IInputDevicesChangedListener;
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -070050import android.hardware.input.IInputManager;
RoboErikfb290df2013-12-16 11:27:55 -080051import android.hardware.input.InputDeviceIdentifier;
Jeff Brownac143512012-04-05 18:57:33 -070052import android.hardware.input.InputManager;
Jeff Brown4ccb8232014-01-16 22:16:42 -080053import android.hardware.input.InputManagerInternal;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070054import android.hardware.input.KeyboardLayout;
Jason Gerecked6396d62014-01-27 18:30:37 -080055import android.hardware.input.TouchCalibration;
Jeff Brown4532e612012-04-05 14:27:12 -070056import android.os.Binder;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070057import android.os.Bundle;
Jeff Brown46b9ac02010-04-22 18:58:52 -070058import android.os.Environment;
Jeff Brown4532e612012-04-05 14:27:12 -070059import android.os.Handler;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070060import android.os.IBinder;
Jeff Browna9d131c2012-09-20 16:48:17 -070061import android.os.Looper;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070062import android.os.Message;
Jeff Brown05dc66a2011-03-02 14:41:58 -080063import android.os.MessageQueue;
Jeff Brownac143512012-04-05 18:57:33 -070064import android.os.Process;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070065import android.os.RemoteException;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -070066import android.os.UserHandle;
Jeff Brown1a84fd12011-06-02 01:26:32 -070067import android.provider.Settings;
68import android.provider.Settings.SettingNotFoundException;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070069import android.util.Log;
Jeff Brown46b9ac02010-04-22 18:58:52 -070070import android.util.Slog;
Jeff Brownaf9e8d32012-04-12 17:32:48 -070071import android.util.SparseArray;
Jeff Brown46b9ac02010-04-22 18:58:52 -070072import android.util.Xml;
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -070073import android.view.IInputFilter;
74import android.view.IInputFilterHost;
Jeff Brown46b9ac02010-04-22 18:58:52 -070075import android.view.InputChannel;
Jeff Brown8d608662010-08-30 03:02:23 -070076import android.view.InputDevice;
Jeff Brown6ec402b2010-07-28 15:48:59 -070077import android.view.InputEvent;
Jeff Brown1f245102010-11-18 20:53:46 -080078import android.view.KeyEvent;
Jeff Brown2352b972011-04-12 22:39:53 -070079import android.view.PointerIcon;
Jason Gerecked5220742014-03-10 09:47:59 -070080import android.view.Surface;
Jeff Browna4547672011-03-02 21:38:11 -080081import android.view.ViewConfiguration;
Jeff Brown0029c662011-03-30 02:25:18 -070082import android.view.WindowManagerPolicy;
Jeff Browncf39bdf2012-05-18 14:41:19 -070083import android.widget.Toast;
Jeff Brown46b9ac02010-04-22 18:58:52 -070084
Jeff Brown46b9ac02010-04-22 18:58:52 -070085import java.io.File;
Jeff Brown4532e612012-04-05 14:27:12 -070086import java.io.FileDescriptor;
Jeff Brown46b9ac02010-04-22 18:58:52 -070087import java.io.FileNotFoundException;
88import java.io.FileReader;
89import java.io.IOException;
Jeff Brown6ec6f792012-04-17 16:52:41 -070090import java.io.InputStreamReader;
Jeff Brown46b9ac02010-04-22 18:58:52 -070091import java.io.PrintWriter;
92import java.util.ArrayList;
Jeff Brown9f25b7f2012-04-10 14:30:49 -070093import java.util.HashMap;
Jeff Browncf39bdf2012-05-18 14:41:19 -070094import java.util.HashSet;
Jeff Browna3bc5652012-04-17 11:42:25 -070095
Jeff Brown6ec6f792012-04-17 16:52:41 -070096import libcore.io.Streams;
Jeff Browna3bc5652012-04-17 11:42:25 -070097import libcore.util.Objects;
Jeff Brown46b9ac02010-04-22 18:58:52 -070098
99/*
100 * Wraps the C++ InputManager and provides its callbacks.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700101 */
Jeff Brownd728bf52012-09-08 18:05:28 -0700102public class InputManagerService extends IInputManager.Stub
Jeff Brown4ccb8232014-01-16 22:16:42 -0800103 implements Watchdog.Monitor {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700104 static final String TAG = "InputManager";
Jeff Brown1b9ba572012-05-21 10:54:18 -0700105 static final boolean DEBUG = false;
Jeff Brownb6997262010-10-08 22:31:17 -0700106
Jeff Brown4532e612012-04-05 14:27:12 -0700107 private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
108
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700109 private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
Jeff Browncf39bdf2012-05-18 14:41:19 -0700110 private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
111 private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
112 private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
113 private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700114
Jeff Brown4532e612012-04-05 14:27:12 -0700115 // Pointer to native input manager service object.
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000116 private final long mPtr;
Jeff Brown4532e612012-04-05 14:27:12 -0700117
Jeff Brown46b9ac02010-04-22 18:58:52 -0700118 private final Context mContext;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700119 private final InputManagerHandler mHandler;
Jeff Browna9d131c2012-09-20 16:48:17 -0700120
121 private WindowManagerCallbacks mWindowManagerCallbacks;
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700122 private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
Jeff Brown6ec6f792012-04-17 16:52:41 -0700123 private boolean mSystemReady;
Jeff Browncf39bdf2012-05-18 14:41:19 -0700124 private NotificationManager mNotificationManager;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700125
Jeff Browna3bc5652012-04-17 11:42:25 -0700126 // Persistent data store. Must be locked each time during use.
127 private final PersistentDataStore mDataStore = new PersistentDataStore();
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700128
129 // List of currently registered input devices changed listeners by process id.
130 private Object mInputDevicesLock = new Object();
131 private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
132 private InputDevice[] mInputDevices = new InputDevice[0];
133 private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
134 new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
135 private final ArrayList<InputDevicesChangedListenerRecord>
136 mTempInputDevicesChangedListenersToNotify =
137 new ArrayList<InputDevicesChangedListenerRecord>(); // handler thread only
Jeff Browncf39bdf2012-05-18 14:41:19 -0700138 private final ArrayList<InputDevice>
139 mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
140 private boolean mKeyboardLayoutNotificationShown;
141 private PendingIntent mKeyboardLayoutIntent;
142 private Toast mSwitchedKeyboardLayoutToast;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700143
Jeff Browna47425a2012-04-13 04:09:27 -0700144 // State for vibrator tokens.
145 private Object mVibratorLock = new Object();
146 private HashMap<IBinder, VibratorToken> mVibratorTokens =
147 new HashMap<IBinder, VibratorToken>();
148 private int mNextVibratorTokenValue;
149
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700150 // State for the currently installed input filter.
151 final Object mInputFilterLock = new Object();
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700152 IInputFilter mInputFilter; // guarded by mInputFilterLock
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700153 InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
Jeff Brown1a84fd12011-06-02 01:26:32 -0700154
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000155 private static native long nativeInit(InputManagerService service,
Jeff Brown4532e612012-04-05 14:27:12 -0700156 Context context, MessageQueue messageQueue);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000157 private static native void nativeStart(long ptr);
158 private static native void nativeSetDisplayViewport(long ptr, boolean external,
Jeff Brownd728bf52012-09-08 18:05:28 -0700159 int displayId, int rotation,
160 int logicalLeft, int logicalTop, int logicalRight, int logicalBottom,
Jeff Brown83d616a2012-09-09 20:33:43 -0700161 int physicalLeft, int physicalTop, int physicalRight, int physicalBottom,
162 int deviceWidth, int deviceHeight);
Jeff Brownd728bf52012-09-08 18:05:28 -0700163
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000164 private static native int nativeGetScanCodeState(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700165 int deviceId, int sourceMask, int scanCode);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000166 private static native int nativeGetKeyCodeState(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700167 int deviceId, int sourceMask, int keyCode);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000168 private static native int nativeGetSwitchState(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700169 int deviceId, int sourceMask, int sw);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000170 private static native boolean nativeHasKeys(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700171 int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000172 private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
Jeff Brown928e0542011-01-10 11:17:36 -0800173 InputWindowHandle inputWindowHandle, boolean monitor);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000174 private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
175 private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
Jeff Brownca9bc702014-02-11 14:32:56 -0800176 private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
Jeff Brown0029c662011-03-30 02:25:18 -0700177 int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
178 int policyFlags);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000179 private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
180 private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
181 private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
182 private static native void nativeSetFocusedApplication(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700183 InputApplicationHandle application);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000184 private static native boolean nativeTransferTouchFocus(long ptr,
Jeff Brown4532e612012-04-05 14:27:12 -0700185 InputChannel fromChannel, InputChannel toChannel);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000186 private static native void nativeSetPointerSpeed(long ptr, int speed);
187 private static native void nativeSetShowTouches(long ptr, boolean enabled);
Jeff Brown037c33e2014-04-09 00:31:55 -0700188 private static native void nativeSetInteractive(long ptr, boolean interactive);
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800189 private static native void nativeReloadCalibration(long ptr);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000190 private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
Jeff Browna47425a2012-04-13 04:09:27 -0700191 int repeat, int token);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000192 private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
193 private static native void nativeReloadKeyboardLayouts(long ptr);
194 private static native void nativeReloadDeviceAliases(long ptr);
195 private static native String nativeDump(long ptr);
196 private static native void nativeMonitor(long ptr);
Jeff Brown4532e612012-04-05 14:27:12 -0700197
Jeff Brownac143512012-04-05 18:57:33 -0700198 // Input event injection constants defined in InputDispatcher.h.
199 private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
200 private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
201 private static final int INPUT_EVENT_INJECTION_FAILED = 2;
202 private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
203
204 // Maximum number of milliseconds to wait for input event injection.
205 private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
206
Jeff Brown6d0fec22010-07-23 21:28:06 -0700207 // Key states (may be returned by queries about the current state of a
208 // particular key code, scan code or switch).
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700209
Jeff Brown6d0fec22010-07-23 21:28:06 -0700210 /** The key state is unknown or the requested key itself is not supported. */
211 public static final int KEY_STATE_UNKNOWN = -1;
212
213 /** The key is up. /*/
214 public static final int KEY_STATE_UP = 0;
215
216 /** The key is down. */
217 public static final int KEY_STATE_DOWN = 1;
218
219 /** The key is down but is a virtual key press that is being emulated by the system. */
220 public static final int KEY_STATE_VIRTUAL = 2;
221
Jeff Brownc458ce92012-04-30 14:58:40 -0700222 /** Scan code: Mouse / trackball button. */
223 public static final int BTN_MOUSE = 0x110;
224
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700225 // Switch code values must match bionic/libc/kernel/common/linux/input.h
Jeff Brownc458ce92012-04-30 14:58:40 -0700226 /** Switch code: Lid switch. When set, lid is shut. */
227 public static final int SW_LID = 0x00;
228
229 /** Switch code: Keypad slide. When set, keyboard is exposed. */
230 public static final int SW_KEYPAD_SLIDE = 0x0a;
231
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700232 /** Switch code: Headphone. When set, headphone is inserted. */
233 public static final int SW_HEADPHONE_INSERT = 0x02;
234
235 /** Switch code: Microphone. When set, microphone is inserted. */
236 public static final int SW_MICROPHONE_INSERT = 0x04;
237
Jon Eklund43cc8bb2014-07-28 16:07:24 -0500238 /** Switch code: Line out. When set, Line out (hi-Z) is inserted. */
239 public static final int SW_LINEOUT_INSERT = 0x06;
240
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700241 /** Switch code: Headphone/Microphone Jack. When set, something is inserted. */
242 public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
243
Michael Wright3818c922014-09-02 13:59:07 -0700244 /** Switch code: Camera lens cover. When set the lens is covered. */
245 public static final int SW_CAMERA_LENS_COVER = 0x09;
246
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700247 public static final int SW_LID_BIT = 1 << SW_LID;
248 public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
249 public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
250 public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
Jon Eklund43cc8bb2014-07-28 16:07:24 -0500251 public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT;
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700252 public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
253 public static final int SW_JACK_BITS =
Jon Eklund43cc8bb2014-07-28 16:07:24 -0500254 SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
Michael Wright3818c922014-09-02 13:59:07 -0700255 public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700256
257 /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
258 final boolean mUseDevInputEventForAudioJack;
259
Jeff Brown4ccb8232014-01-16 22:16:42 -0800260 public InputManagerService(Context context) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700261 this.mContext = context;
Jeff Brown4ccb8232014-01-16 22:16:42 -0800262 this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
Jeff Brown05dc66a2011-03-02 14:41:58 -0800263
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700264 mUseDevInputEventForAudioJack =
265 context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
266 Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
267 + mUseDevInputEventForAudioJack);
Jeff Brown4532e612012-04-05 14:27:12 -0700268 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
Jeff Brown4ccb8232014-01-16 22:16:42 -0800269
270 LocalServices.addService(InputManagerInternal.class, new LocalService());
Jeff Brown46b9ac02010-04-22 18:58:52 -0700271 }
Jeff Brown1a84fd12011-06-02 01:26:32 -0700272
Jeff Browna9d131c2012-09-20 16:48:17 -0700273 public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
274 mWindowManagerCallbacks = callbacks;
275 }
276
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700277 public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
278 mWiredAccessoryCallbacks = callbacks;
279 }
280
Jeff Brown46b9ac02010-04-22 18:58:52 -0700281 public void start() {
282 Slog.i(TAG, "Starting input manager");
Jeff Brown4532e612012-04-05 14:27:12 -0700283 nativeStart(mPtr);
284
285 // Add ourself to the Watchdog monitors.
286 Watchdog.getInstance().addMonitor(this);
Jeff Brown1a84fd12011-06-02 01:26:32 -0700287
288 registerPointerSpeedSettingObserver();
Jeff Browndaf4a122011-08-26 17:14:14 -0700289 registerShowTouchesSettingObserver();
290
Jeff Brownd4935962012-09-25 13:27:20 -0700291 mContext.registerReceiver(new BroadcastReceiver() {
292 @Override
293 public void onReceive(Context context, Intent intent) {
294 updatePointerSpeedFromSettings();
295 updateShowTouchesFromSettings();
296 }
297 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
298
Jeff Brown1a84fd12011-06-02 01:26:32 -0700299 updatePointerSpeedFromSettings();
Jeff Browndaf4a122011-08-26 17:14:14 -0700300 updateShowTouchesFromSettings();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700301 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700302
Matthew Xie96313142012-06-29 16:57:31 -0700303 // TODO(BT) Pass in paramter for bluetooth system
Svetoslav Ganova0027152013-06-25 14:59:53 -0700304 public void systemRunning() {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700305 if (DEBUG) {
306 Slog.d(TAG, "System ready.");
307 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700308 mNotificationManager = (NotificationManager)mContext.getSystemService(
309 Context.NOTIFICATION_SERVICE);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700310 mSystemReady = true;
Jeff Brown6ec6f792012-04-17 16:52:41 -0700311
312 IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
313 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
314 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
Jeff Brown69b07162013-11-07 00:30:16 -0800315 filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700316 filter.addDataScheme("package");
317 mContext.registerReceiver(new BroadcastReceiver() {
318 @Override
319 public void onReceive(Context context, Intent intent) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700320 updateKeyboardLayouts();
Jeff Brown6ec6f792012-04-17 16:52:41 -0700321 }
322 }, filter, null, mHandler);
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700323
324 filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
325 mContext.registerReceiver(new BroadcastReceiver() {
326 @Override
327 public void onReceive(Context context, Intent intent) {
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700328 reloadDeviceAliases();
329 }
330 }, filter, null, mHandler);
331
Jeff Browncf39bdf2012-05-18 14:41:19 -0700332 mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
333 mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700334
335 if (mWiredAccessoryCallbacks != null) {
336 mWiredAccessoryCallbacks.systemReady();
337 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700338 }
339
340 private void reloadKeyboardLayouts() {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700341 if (DEBUG) {
342 Slog.d(TAG, "Reloading keyboard layouts.");
343 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700344 nativeReloadKeyboardLayouts(mPtr);
345 }
346
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700347 private void reloadDeviceAliases() {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700348 if (DEBUG) {
349 Slog.d(TAG, "Reloading device names.");
350 }
Jeff Brown5bbd4b42012-04-20 19:28:00 -0700351 nativeReloadDeviceAliases(mPtr);
352 }
353
Jeff Brown4ccb8232014-01-16 22:16:42 -0800354 private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
Jeff Brownd728bf52012-09-08 18:05:28 -0700355 DisplayViewport externalTouchViewport) {
356 if (defaultViewport.valid) {
357 setDisplayViewport(false, defaultViewport);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700358 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700359
360 if (externalTouchViewport.valid) {
361 setDisplayViewport(true, externalTouchViewport);
362 } else if (defaultViewport.valid) {
363 setDisplayViewport(true, defaultViewport);
Jeff Brownb6997262010-10-08 22:31:17 -0700364 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700365 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700366
Jeff Brownd728bf52012-09-08 18:05:28 -0700367 private void setDisplayViewport(boolean external, DisplayViewport viewport) {
368 nativeSetDisplayViewport(mPtr, external,
369 viewport.displayId, viewport.orientation,
370 viewport.logicalFrame.left, viewport.logicalFrame.top,
371 viewport.logicalFrame.right, viewport.logicalFrame.bottom,
372 viewport.physicalFrame.left, viewport.physicalFrame.top,
Jeff Brown83d616a2012-09-09 20:33:43 -0700373 viewport.physicalFrame.right, viewport.physicalFrame.bottom,
374 viewport.deviceWidth, viewport.deviceHeight);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700375 }
Jeff Brownac143512012-04-05 18:57:33 -0700376
Jeff Brown6d0fec22010-07-23 21:28:06 -0700377 /**
378 * Gets the current state of a key or button by key code.
379 * @param deviceId The input device id, or -1 to consult all devices.
380 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
381 * consider all input sources. An input device is consulted if at least one of its
382 * non-class input source bits matches the specified source mask.
383 * @param keyCode The key code to check.
384 * @return The key state.
385 */
386 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700387 return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700388 }
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700389
Jeff Brown6d0fec22010-07-23 21:28:06 -0700390 /**
391 * Gets the current state of a key or button by scan code.
392 * @param deviceId The input device id, or -1 to consult all devices.
393 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
394 * consider all input sources. An input device is consulted if at least one of its
395 * non-class input source bits matches the specified source mask.
396 * @param scanCode The scan code to check.
397 * @return The key state.
398 */
399 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700400 return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700401 }
RoboErikfb290df2013-12-16 11:27:55 -0800402
Jeff Brown6d0fec22010-07-23 21:28:06 -0700403 /**
404 * Gets the current state of a switch by switch code.
405 * @param deviceId The input device id, or -1 to consult all devices.
406 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
407 * consider all input sources. An input device is consulted if at least one of its
408 * non-class input source bits matches the specified source mask.
409 * @param switchCode The switch code to check.
410 * @return The switch state.
411 */
412 public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
Jeff Brown4532e612012-04-05 14:27:12 -0700413 return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700414 }
415
Jeff Brown6d0fec22010-07-23 21:28:06 -0700416 /**
417 * Determines whether the specified key codes are supported by a particular device.
418 * @param deviceId The input device id, or -1 to consult all devices.
419 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
420 * consider all input sources. An input device is consulted if at least one of its
421 * non-class input source bits matches the specified source mask.
422 * @param keyCodes The array of key codes to check.
423 * @param keyExists An array at least as large as keyCodes whose entries will be set
424 * to true or false based on the presence or absence of support for the corresponding
425 * key codes.
426 * @return True if the lookup was successful, false otherwise.
427 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700428 @Override // Binder call
Jeff Brown6d0fec22010-07-23 21:28:06 -0700429 public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700430 if (keyCodes == null) {
431 throw new IllegalArgumentException("keyCodes must not be null.");
432 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700433 if (keyExists == null || keyExists.length < keyCodes.length) {
434 throw new IllegalArgumentException("keyExists must not be null and must be at "
435 + "least as large as keyCodes.");
Jeff Brown46b9ac02010-04-22 18:58:52 -0700436 }
RoboErikfb290df2013-12-16 11:27:55 -0800437
Jeff Brown4532e612012-04-05 14:27:12 -0700438 return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700439 }
RoboErikfb290df2013-12-16 11:27:55 -0800440
Jeff Browna41ca772010-08-11 14:46:32 -0700441 /**
442 * Creates an input channel that will receive all input from the input dispatcher.
443 * @param inputChannelName The input channel name.
444 * @return The input channel.
445 */
446 public InputChannel monitorInput(String inputChannelName) {
447 if (inputChannelName == null) {
448 throw new IllegalArgumentException("inputChannelName must not be null.");
449 }
RoboErikfb290df2013-12-16 11:27:55 -0800450
Jeff Browna41ca772010-08-11 14:46:32 -0700451 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
Jeff Brown4532e612012-04-05 14:27:12 -0700452 nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
Jeff Browna41ca772010-08-11 14:46:32 -0700453 inputChannels[0].dispose(); // don't need to retain the Java object reference
454 return inputChannels[1];
455 }
456
457 /**
458 * Registers an input channel so that it can be used as an input event target.
459 * @param inputChannel The input channel to register.
Jeff Brown928e0542011-01-10 11:17:36 -0800460 * @param inputWindowHandle The handle of the input window associated with the
461 * input channel, or null if none.
Jeff Browna41ca772010-08-11 14:46:32 -0700462 */
Jeff Brown928e0542011-01-10 11:17:36 -0800463 public void registerInputChannel(InputChannel inputChannel,
464 InputWindowHandle inputWindowHandle) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700465 if (inputChannel == null) {
466 throw new IllegalArgumentException("inputChannel must not be null.");
467 }
RoboErikfb290df2013-12-16 11:27:55 -0800468
Jeff Brown4532e612012-04-05 14:27:12 -0700469 nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700470 }
RoboErikfb290df2013-12-16 11:27:55 -0800471
Jeff Browna41ca772010-08-11 14:46:32 -0700472 /**
473 * Unregisters an input channel.
474 * @param inputChannel The input channel to unregister.
475 */
Jeff Brown46b9ac02010-04-22 18:58:52 -0700476 public void unregisterInputChannel(InputChannel inputChannel) {
477 if (inputChannel == null) {
478 throw new IllegalArgumentException("inputChannel must not be null.");
479 }
RoboErikfb290df2013-12-16 11:27:55 -0800480
Jeff Brown4532e612012-04-05 14:27:12 -0700481 nativeUnregisterInputChannel(mPtr, inputChannel);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700482 }
Jeff Brown0029c662011-03-30 02:25:18 -0700483
484 /**
485 * Sets an input filter that will receive all input events before they are dispatched.
486 * The input filter may then reinterpret input events or inject new ones.
487 *
488 * To ensure consistency, the input dispatcher automatically drops all events
489 * in progress whenever an input filter is installed or uninstalled. After an input
490 * filter is uninstalled, it can no longer send input events unless it is reinstalled.
491 * Any events it attempts to send after it has been uninstalled will be dropped.
492 *
493 * @param filter The input filter, or null to remove the current filter.
494 */
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700495 public void setInputFilter(IInputFilter filter) {
Jeff Brown0029c662011-03-30 02:25:18 -0700496 synchronized (mInputFilterLock) {
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700497 final IInputFilter oldFilter = mInputFilter;
Jeff Brown0029c662011-03-30 02:25:18 -0700498 if (oldFilter == filter) {
499 return; // nothing to do
500 }
501
502 if (oldFilter != null) {
503 mInputFilter = null;
504 mInputFilterHost.disconnectLocked();
505 mInputFilterHost = null;
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700506 try {
507 oldFilter.uninstall();
508 } catch (RemoteException re) {
509 /* ignore */
510 }
Jeff Brown0029c662011-03-30 02:25:18 -0700511 }
512
513 if (filter != null) {
514 mInputFilter = filter;
515 mInputFilterHost = new InputFilterHost();
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -0700516 try {
517 filter.install(mInputFilterHost);
518 } catch (RemoteException re) {
519 /* ignore */
520 }
Jeff Brown0029c662011-03-30 02:25:18 -0700521 }
522
Jeff Brown4532e612012-04-05 14:27:12 -0700523 nativeSetInputFilterEnabled(mPtr, filter != null);
Jeff Brown0029c662011-03-30 02:25:18 -0700524 }
525 }
526
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700527 @Override // Binder call
Jeff Brownac143512012-04-05 18:57:33 -0700528 public boolean injectInputEvent(InputEvent event, int mode) {
Jeff Brownca9bc702014-02-11 14:32:56 -0800529 return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
530 }
531
532 private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
Jeff Brown7fbdc842010-06-17 20:52:56 -0700533 if (event == null) {
534 throw new IllegalArgumentException("event must not be null");
535 }
Jeff Brownac143512012-04-05 18:57:33 -0700536 if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
537 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
538 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
539 throw new IllegalArgumentException("mode is invalid");
Jeff Brown7fbdc842010-06-17 20:52:56 -0700540 }
Jeff Brown6ec402b2010-07-28 15:48:59 -0700541
Jeff Brownac143512012-04-05 18:57:33 -0700542 final int pid = Binder.getCallingPid();
543 final int uid = Binder.getCallingUid();
544 final long ident = Binder.clearCallingIdentity();
545 final int result;
546 try {
Jeff Brownca9bc702014-02-11 14:32:56 -0800547 result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
Jeff Brownac143512012-04-05 18:57:33 -0700548 INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
549 } finally {
550 Binder.restoreCallingIdentity(ident);
551 }
552 switch (result) {
553 case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
554 Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
555 throw new SecurityException(
556 "Injecting to another application requires INJECT_EVENTS permission");
557 case INPUT_EVENT_INJECTION_SUCCEEDED:
558 return true;
559 case INPUT_EVENT_INJECTION_TIMED_OUT:
560 Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
561 return false;
562 case INPUT_EVENT_INJECTION_FAILED:
563 default:
564 Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
565 return false;
566 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700567 }
Jeff Brown0029c662011-03-30 02:25:18 -0700568
Jeff Brown8d608662010-08-30 03:02:23 -0700569 /**
570 * Gets information about the input device with the specified id.
Craig Mautner2f39e9f2012-09-21 11:39:54 -0700571 * @param deviceId The device id.
Jeff Brown8d608662010-08-30 03:02:23 -0700572 * @return The input device or null if not found.
573 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700574 @Override // Binder call
Jeff Brown8d608662010-08-30 03:02:23 -0700575 public InputDevice getInputDevice(int deviceId) {
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700576 synchronized (mInputDevicesLock) {
577 final int count = mInputDevices.length;
578 for (int i = 0; i < count; i++) {
579 final InputDevice inputDevice = mInputDevices[i];
580 if (inputDevice.getId() == deviceId) {
581 return inputDevice;
582 }
583 }
584 }
585 return null;
Jeff Brown8d608662010-08-30 03:02:23 -0700586 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700587
Jeff Brown8d608662010-08-30 03:02:23 -0700588 /**
589 * Gets the ids of all input devices in the system.
590 * @return The input device ids.
591 */
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700592 @Override // Binder call
Jeff Brown8d608662010-08-30 03:02:23 -0700593 public int[] getInputDeviceIds() {
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700594 synchronized (mInputDevicesLock) {
595 final int count = mInputDevices.length;
596 int[] ids = new int[count];
597 for (int i = 0; i < count; i++) {
598 ids[i] = mInputDevices[i].getId();
599 }
600 return ids;
601 }
602 }
603
Jeff Browndaa37532012-05-01 15:54:03 -0700604 /**
605 * Gets all input devices in the system.
606 * @return The array of input devices.
607 */
608 public InputDevice[] getInputDevices() {
609 synchronized (mInputDevicesLock) {
610 return mInputDevices;
611 }
612 }
613
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700614 @Override // Binder call
615 public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
616 if (listener == null) {
617 throw new IllegalArgumentException("listener must not be null");
618 }
619
620 synchronized (mInputDevicesLock) {
621 int callingPid = Binder.getCallingPid();
622 if (mInputDevicesChangedListeners.get(callingPid) != null) {
623 throw new SecurityException("The calling process has already "
624 + "registered an InputDevicesChangedListener.");
625 }
626
627 InputDevicesChangedListenerRecord record =
628 new InputDevicesChangedListenerRecord(callingPid, listener);
629 try {
630 IBinder binder = listener.asBinder();
631 binder.linkToDeath(record, 0);
632 } catch (RemoteException ex) {
633 // give up
634 throw new RuntimeException(ex);
635 }
636
637 mInputDevicesChangedListeners.put(callingPid, record);
638 }
639 }
640
641 private void onInputDevicesChangedListenerDied(int pid) {
642 synchronized (mInputDevicesLock) {
643 mInputDevicesChangedListeners.remove(pid);
644 }
645 }
646
647 // Must be called on handler.
Jeff Browncf39bdf2012-05-18 14:41:19 -0700648 private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {
649 // Scan for changes.
650 int numFullKeyboardsAdded = 0;
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700651 mTempInputDevicesChangedListenersToNotify.clear();
Jeff Browncf39bdf2012-05-18 14:41:19 -0700652 mTempFullKeyboards.clear();
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700653 final int numListeners;
654 final int[] deviceIdAndGeneration;
655 synchronized (mInputDevicesLock) {
656 if (!mInputDevicesChangedPending) {
657 return;
658 }
659 mInputDevicesChangedPending = false;
660
661 numListeners = mInputDevicesChangedListeners.size();
662 for (int i = 0; i < numListeners; i++) {
663 mTempInputDevicesChangedListenersToNotify.add(
664 mInputDevicesChangedListeners.valueAt(i));
665 }
666
667 final int numDevices = mInputDevices.length;
668 deviceIdAndGeneration = new int[numDevices * 2];
669 for (int i = 0; i < numDevices; i++) {
670 final InputDevice inputDevice = mInputDevices[i];
671 deviceIdAndGeneration[i * 2] = inputDevice.getId();
672 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
Jeff Browncf39bdf2012-05-18 14:41:19 -0700673
Jeff Brown7e4ff4b2012-05-30 14:32:16 -0700674 if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700675 if (!containsInputDeviceWithDescriptor(oldInputDevices,
676 inputDevice.getDescriptor())) {
677 mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice);
678 } else {
679 mTempFullKeyboards.add(inputDevice);
680 }
681 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700682 }
683 }
684
Jeff Browncf39bdf2012-05-18 14:41:19 -0700685 // Notify listeners.
Jeff Brownaf9e8d32012-04-12 17:32:48 -0700686 for (int i = 0; i < numListeners; i++) {
687 mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
688 deviceIdAndGeneration);
689 }
Jeff Browncf39bdf2012-05-18 14:41:19 -0700690 mTempInputDevicesChangedListenersToNotify.clear();
691
692 // Check for missing keyboard layouts.
693 if (mNotificationManager != null) {
694 final int numFullKeyboards = mTempFullKeyboards.size();
695 boolean missingLayoutForExternalKeyboard = false;
696 boolean missingLayoutForExternalKeyboardAdded = false;
697 synchronized (mDataStore) {
698 for (int i = 0; i < numFullKeyboards; i++) {
699 final InputDevice inputDevice = mTempFullKeyboards.get(i);
Michael Wright86aaca62014-09-08 18:54:45 -0700700 final String layout =
701 getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
702 if (layout == null) {
Jeff Browncf39bdf2012-05-18 14:41:19 -0700703 missingLayoutForExternalKeyboard = true;
704 if (i < numFullKeyboardsAdded) {
705 missingLayoutForExternalKeyboardAdded = true;
706 }
707 }
708 }
709 }
710 if (missingLayoutForExternalKeyboard) {
711 if (missingLayoutForExternalKeyboardAdded) {
712 showMissingKeyboardLayoutNotification();
713 }
714 } else if (mKeyboardLayoutNotificationShown) {
715 hideMissingKeyboardLayoutNotification();
716 }
717 }
718 mTempFullKeyboards.clear();
719 }
720
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800721 @Override // Binder call & native callback
Jason Gerecked5220742014-03-10 09:47:59 -0700722 public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
723 int surfaceRotation) {
Jason Gerecked6396d62014-01-27 18:30:37 -0800724 if (inputDeviceDescriptor == null) {
725 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
726 }
727
728 synchronized (mDataStore) {
Jason Gerecked5220742014-03-10 09:47:59 -0700729 return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
Jason Gerecked6396d62014-01-27 18:30:37 -0800730 }
731 }
732
733 @Override // Binder call
Jason Gerecked5220742014-03-10 09:47:59 -0700734 public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
Jason Gerecked6396d62014-01-27 18:30:37 -0800735 TouchCalibration calibration) {
736 if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
737 "setTouchCalibrationForInputDevice()")) {
738 throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
739 }
740 if (inputDeviceDescriptor == null) {
741 throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
742 }
743 if (calibration == null) {
744 throw new IllegalArgumentException("calibration must not be null");
745 }
Jason Gerecked5220742014-03-10 09:47:59 -0700746 if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
747 throw new IllegalArgumentException("surfaceRotation value out of bounds");
748 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800749
750 synchronized (mDataStore) {
751 try {
Jason Gerecked5220742014-03-10 09:47:59 -0700752 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
753 calibration)) {
Jason Gerecke857aa7b2014-01-27 18:34:20 -0800754 nativeReloadCalibration(mPtr);
755 }
Jason Gerecked6396d62014-01-27 18:30:37 -0800756 } finally {
757 mDataStore.saveIfNeeded();
758 }
759 }
760 }
761
Jeff Browncf39bdf2012-05-18 14:41:19 -0700762 // Must be called on handler.
763 private void showMissingKeyboardLayoutNotification() {
764 if (!mKeyboardLayoutNotificationShown) {
765 if (mKeyboardLayoutIntent == null) {
766 final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS");
767 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
768 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
769 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700770 mKeyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
771 intent, 0, null, UserHandle.CURRENT);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700772 }
773
774 Resources r = mContext.getResources();
775 Notification notification = new Notification.Builder(mContext)
776 .setContentTitle(r.getString(
777 R.string.select_keyboard_layout_notification_title))
778 .setContentText(r.getString(
779 R.string.select_keyboard_layout_notification_message))
780 .setContentIntent(mKeyboardLayoutIntent)
781 .setSmallIcon(R.drawable.ic_settings_language)
782 .setPriority(Notification.PRIORITY_LOW)
Selim Cinek255dd042014-08-19 22:29:02 +0200783 .setColor(mContext.getResources().getColor(
784 com.android.internal.R.color.system_notification_accent_color))
Jeff Browncf39bdf2012-05-18 14:41:19 -0700785 .build();
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700786 mNotificationManager.notifyAsUser(null,
787 R.string.select_keyboard_layout_notification_title,
788 notification, UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700789 mKeyboardLayoutNotificationShown = true;
790 }
791 }
792
793 // Must be called on handler.
794 private void hideMissingKeyboardLayoutNotification() {
795 if (mKeyboardLayoutNotificationShown) {
796 mKeyboardLayoutNotificationShown = false;
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700797 mNotificationManager.cancelAsUser(null,
798 R.string.select_keyboard_layout_notification_title,
799 UserHandle.ALL);
Jeff Browncf39bdf2012-05-18 14:41:19 -0700800 }
801 }
802
803 // Must be called on handler.
804 private void updateKeyboardLayouts() {
805 // Scan all input devices state for keyboard layouts that have been uninstalled.
806 final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
807 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
808 @Override
809 public void visitKeyboardLayout(Resources resources,
810 String descriptor, String label, String collection, int keyboardLayoutResId) {
811 availableKeyboardLayouts.add(descriptor);
812 }
813 });
814 synchronized (mDataStore) {
815 try {
816 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
817 } finally {
818 mDataStore.saveIfNeeded();
819 }
820 }
821
822 // Reload keyboard layouts.
823 reloadKeyboardLayouts();
824 }
825
Jeff Browncf39bdf2012-05-18 14:41:19 -0700826 private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
827 String descriptor) {
828 final int numDevices = inputDevices.length;
829 for (int i = 0; i < numDevices; i++) {
830 final InputDevice inputDevice = inputDevices[i];
831 if (inputDevice.getDescriptor().equals(descriptor)) {
832 return true;
833 }
834 }
835 return false;
Jeff Brown8d608662010-08-30 03:02:23 -0700836 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700837
838 @Override // Binder call
839 public KeyboardLayout[] getKeyboardLayouts() {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700840 final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
841 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
842 @Override
843 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700844 String descriptor, String label, String collection, int keyboardLayoutResId) {
845 list.add(new KeyboardLayout(descriptor, label, collection));
Jeff Brown6ec6f792012-04-17 16:52:41 -0700846 }
847 });
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700848 return list.toArray(new KeyboardLayout[list.size()]);
849 }
850
851 @Override // Binder call
852 public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
853 if (keyboardLayoutDescriptor == null) {
854 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
855 }
856
Jeff Brown6ec6f792012-04-17 16:52:41 -0700857 final KeyboardLayout[] result = new KeyboardLayout[1];
858 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
859 @Override
860 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700861 String descriptor, String label, String collection, int keyboardLayoutResId) {
862 result[0] = new KeyboardLayout(descriptor, label, collection);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700863 }
864 });
865 if (result[0] == null) {
866 Log.w(TAG, "Could not get keyboard layout with descriptor '"
867 + keyboardLayoutDescriptor + "'.");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700868 }
Jeff Brown6ec6f792012-04-17 16:52:41 -0700869 return result[0];
870 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700871
Jeff Brown6ec6f792012-04-17 16:52:41 -0700872 private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700873 final PackageManager pm = mContext.getPackageManager();
Jeff Brown6ec6f792012-04-17 16:52:41 -0700874 Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
875 for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
876 PackageManager.GET_META_DATA)) {
877 visitKeyboardLayoutsInPackage(pm, resolveInfo.activityInfo, null, visitor);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700878 }
879 }
880
Jeff Brown6ec6f792012-04-17 16:52:41 -0700881 private void visitKeyboardLayout(String keyboardLayoutDescriptor,
882 KeyboardLayoutVisitor visitor) {
883 KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor);
884 if (d != null) {
885 final PackageManager pm = mContext.getPackageManager();
886 try {
887 ActivityInfo receiver = pm.getReceiverInfo(
888 new ComponentName(d.packageName, d.receiverName),
889 PackageManager.GET_META_DATA);
890 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, visitor);
891 } catch (NameNotFoundException ex) {
892 }
893 }
894 }
895
896 private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver,
897 String keyboardName, KeyboardLayoutVisitor visitor) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700898 Bundle metaData = receiver.metaData;
899 if (metaData == null) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700900 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700901 }
902
903 int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
904 if (configResId == 0) {
905 Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
906 + "' on receiver " + receiver.packageName + "/" + receiver.name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700907 return;
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700908 }
909
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700910 CharSequence receiverLabel = receiver.loadLabel(pm);
911 String collection = receiverLabel != null ? receiverLabel.toString() : "";
912
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700913 try {
914 Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
915 XmlResourceParser parser = resources.getXml(configResId);
916 try {
917 XmlUtils.beginDocument(parser, "keyboard-layouts");
918
919 for (;;) {
920 XmlUtils.nextElement(parser);
921 String element = parser.getName();
922 if (element == null) {
923 break;
924 }
925 if (element.equals("keyboard-layout")) {
926 TypedArray a = resources.obtainAttributes(
927 parser, com.android.internal.R.styleable.KeyboardLayout);
928 try {
929 String name = a.getString(
930 com.android.internal.R.styleable.KeyboardLayout_name);
931 String label = a.getString(
932 com.android.internal.R.styleable.KeyboardLayout_label);
Jeff Brown2f095762012-05-10 21:29:33 -0700933 int keyboardLayoutResId = a.getResourceId(
934 com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
935 0);
936 if (name == null || label == null || keyboardLayoutResId == 0) {
937 Log.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700938 + "attributes in keyboard layout "
939 + "resource from receiver "
940 + receiver.packageName + "/" + receiver.name);
941 } else {
942 String descriptor = KeyboardLayoutDescriptor.format(
943 receiver.packageName, receiver.name, name);
Jeff Brown6ec6f792012-04-17 16:52:41 -0700944 if (keyboardName == null || name.equals(keyboardName)) {
945 visitor.visitKeyboardLayout(resources, descriptor,
Jeff Brownd9fec5d2012-05-17 16:01:54 -0700946 label, collection, keyboardLayoutResId);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700947 }
948 }
949 } finally {
950 a.recycle();
951 }
952 } else {
953 Log.w(TAG, "Skipping unrecognized element '" + element
954 + "' in keyboard layout resource from receiver "
955 + receiver.packageName + "/" + receiver.name);
956 }
957 }
958 } finally {
959 parser.close();
960 }
961 } catch (Exception ex) {
Jeff Brown6ec6f792012-04-17 16:52:41 -0700962 Log.w(TAG, "Could not parse keyboard layout resource from receiver "
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700963 + receiver.packageName + "/" + receiver.name, ex);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700964 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700965 }
966
RoboErikfb290df2013-12-16 11:27:55 -0800967 /**
968 * Builds a layout descriptor for the vendor/product. This returns the
969 * descriptor for ids that aren't useful (such as the default 0, 0).
970 */
971 private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
972 if (identifier == null || identifier.getDescriptor() == null) {
973 throw new IllegalArgumentException("identifier and descriptor must not be null");
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700974 }
975
RoboErikfb290df2013-12-16 11:27:55 -0800976 if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
977 return identifier.getDescriptor();
978 }
979 StringBuilder bob = new StringBuilder();
980 bob.append("vendor:").append(identifier.getVendorId());
981 bob.append(",product:").append(identifier.getProductId());
982 return bob.toString();
983 }
984
985 @Override // Binder call
986 public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
987
988 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -0700989 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -0800990 String layout = null;
991 // try loading it using the layout descriptor if we have it
992 layout = mDataStore.getCurrentKeyboardLayout(key);
993 if (layout == null && !key.equals(identifier.getDescriptor())) {
994 // if it doesn't exist fall back to the device descriptor
995 layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
996 }
997 if (DEBUG) {
998 Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
999 + layout);
1000 }
1001 return layout;
Jeff Browna3bc5652012-04-17 11:42:25 -07001002 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001003 }
1004
1005 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001006 public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001007 String keyboardLayoutDescriptor) {
1008 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001009 "setCurrentKeyboardLayoutForInputDevice()")) {
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001010 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1011 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001012 if (keyboardLayoutDescriptor == null) {
1013 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1014 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001015
RoboErikfb290df2013-12-16 11:27:55 -08001016 String key = getLayoutDescriptor(identifier);
Jeff Browna3bc5652012-04-17 11:42:25 -07001017 synchronized (mDataStore) {
1018 try {
RoboErikfb290df2013-12-16 11:27:55 -08001019 if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
1020 if (DEBUG) {
1021 Slog.d(TAG, "Saved keyboard layout using " + key);
1022 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001023 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1024 }
Jeff Browna3bc5652012-04-17 11:42:25 -07001025 } finally {
1026 mDataStore.saveIfNeeded();
1027 }
1028 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001029 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001030
Jeff Browncf39bdf2012-05-18 14:41:19 -07001031 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001032 public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
1033 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001034 synchronized (mDataStore) {
RoboErikfb290df2013-12-16 11:27:55 -08001035 String[] layouts = mDataStore.getKeyboardLayouts(key);
1036 if ((layouts == null || layouts.length == 0)
1037 && !key.equals(identifier.getDescriptor())) {
1038 layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
1039 }
1040 return layouts;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001041 }
1042 }
1043
1044 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001045 public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001046 String keyboardLayoutDescriptor) {
1047 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1048 "addKeyboardLayoutForInputDevice()")) {
1049 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1050 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001051 if (keyboardLayoutDescriptor == null) {
1052 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1053 }
1054
RoboErikfb290df2013-12-16 11:27:55 -08001055 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001056 synchronized (mDataStore) {
1057 try {
RoboErikfb290df2013-12-16 11:27:55 -08001058 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1059 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1060 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1061 }
1062 if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
Jeff Browncf39bdf2012-05-18 14:41:19 -07001063 && !Objects.equal(oldLayout,
RoboErikfb290df2013-12-16 11:27:55 -08001064 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001065 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1066 }
1067 } finally {
1068 mDataStore.saveIfNeeded();
Jeff Brown6ec6f792012-04-17 16:52:41 -07001069 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001070 }
1071 }
1072
1073 @Override // Binder call
RoboErikfb290df2013-12-16 11:27:55 -08001074 public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
Jeff Browncf39bdf2012-05-18 14:41:19 -07001075 String keyboardLayoutDescriptor) {
1076 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1077 "removeKeyboardLayoutForInputDevice()")) {
1078 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1079 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001080 if (keyboardLayoutDescriptor == null) {
1081 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1082 }
1083
RoboErikfb290df2013-12-16 11:27:55 -08001084 String key = getLayoutDescriptor(identifier);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001085 synchronized (mDataStore) {
1086 try {
RoboErikfb290df2013-12-16 11:27:55 -08001087 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1088 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1089 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1090 }
1091 boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
1092 if (!key.equals(identifier.getDescriptor())) {
1093 // We need to remove from both places to ensure it is gone
1094 removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
1095 keyboardLayoutDescriptor);
1096 }
1097 if (removed && !Objects.equal(oldLayout,
1098 mDataStore.getCurrentKeyboardLayout(key))) {
Jeff Browncf39bdf2012-05-18 14:41:19 -07001099 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1100 }
1101 } finally {
1102 mDataStore.saveIfNeeded();
1103 }
1104 }
1105 }
1106
1107 public void switchKeyboardLayout(int deviceId, int direction) {
1108 mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
1109 }
1110
1111 // Must be called on handler.
1112 private void handleSwitchKeyboardLayout(int deviceId, int direction) {
1113 final InputDevice device = getInputDevice(deviceId);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001114 if (device != null) {
1115 final boolean changed;
1116 final String keyboardLayoutDescriptor;
RoboErikfb290df2013-12-16 11:27:55 -08001117
1118 String key = getLayoutDescriptor(device.getIdentifier());
Jeff Browncf39bdf2012-05-18 14:41:19 -07001119 synchronized (mDataStore) {
1120 try {
RoboErikfb290df2013-12-16 11:27:55 -08001121 changed = mDataStore.switchKeyboardLayout(key, direction);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001122 keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
RoboErikfb290df2013-12-16 11:27:55 -08001123 key);
Jeff Browncf39bdf2012-05-18 14:41:19 -07001124 } finally {
1125 mDataStore.saveIfNeeded();
1126 }
1127 }
1128
1129 if (changed) {
1130 if (mSwitchedKeyboardLayoutToast != null) {
1131 mSwitchedKeyboardLayoutToast.cancel();
1132 mSwitchedKeyboardLayoutToast = null;
1133 }
1134 if (keyboardLayoutDescriptor != null) {
1135 KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
1136 if (keyboardLayout != null) {
1137 mSwitchedKeyboardLayoutToast = Toast.makeText(
1138 mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
1139 mSwitchedKeyboardLayoutToast.show();
1140 }
1141 }
1142
1143 reloadKeyboardLayouts();
1144 }
Jeff Brown6ec6f792012-04-17 16:52:41 -07001145 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001146 }
1147
Jeff Brown9302c872011-07-13 22:51:29 -07001148 public void setInputWindows(InputWindowHandle[] windowHandles) {
Jeff Brown4532e612012-04-05 14:27:12 -07001149 nativeSetInputWindows(mPtr, windowHandles);
Jeff Brown349703e2010-06-22 01:27:15 -07001150 }
RoboErikfb290df2013-12-16 11:27:55 -08001151
Jeff Brown9302c872011-07-13 22:51:29 -07001152 public void setFocusedApplication(InputApplicationHandle application) {
Jeff Brown4532e612012-04-05 14:27:12 -07001153 nativeSetFocusedApplication(mPtr, application);
Jeff Brown349703e2010-06-22 01:27:15 -07001154 }
RoboErikfb290df2013-12-16 11:27:55 -08001155
Jeff Brown349703e2010-06-22 01:27:15 -07001156 public void setInputDispatchMode(boolean enabled, boolean frozen) {
Jeff Brown4532e612012-04-05 14:27:12 -07001157 nativeSetInputDispatchMode(mPtr, enabled, frozen);
Jeff Brown349703e2010-06-22 01:27:15 -07001158 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001159
1160 public void setSystemUiVisibility(int visibility) {
Jeff Brown4532e612012-04-05 14:27:12 -07001161 nativeSetSystemUiVisibility(mPtr, visibility);
Jeff Brown05dc66a2011-03-02 14:41:58 -08001162 }
1163
Jeff Browne6504122010-09-27 14:52:15 -07001164 /**
1165 * Atomically transfers touch focus from one window to another as identified by
1166 * their input channels. It is possible for multiple windows to have
1167 * touch focus if they support split touch dispatch
1168 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
1169 * method only transfers touch focus of the specified window without affecting
1170 * other windows that may also have touch focus at the same time.
1171 * @param fromChannel The channel of a window that currently has touch focus.
1172 * @param toChannel The channel of the window that should receive touch focus in
1173 * place of the first.
1174 * @return True if the transfer was successful. False if the window with the
1175 * specified channel did not actually have touch focus at the time of the request.
1176 */
1177 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
1178 if (fromChannel == null) {
1179 throw new IllegalArgumentException("fromChannel must not be null.");
1180 }
1181 if (toChannel == null) {
1182 throw new IllegalArgumentException("toChannel must not be null.");
1183 }
Jeff Brown4532e612012-04-05 14:27:12 -07001184 return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
Jeff Browne6504122010-09-27 14:52:15 -07001185 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001186
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001187 @Override // Binder call
Jeff Brownac143512012-04-05 18:57:33 -07001188 public void tryPointerSpeed(int speed) {
1189 if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1190 "tryPointerSpeed()")) {
1191 throw new SecurityException("Requires SET_POINTER_SPEED permission");
1192 }
1193
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001194 if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) {
1195 throw new IllegalArgumentException("speed out of range");
1196 }
1197
Jeff Brownac143512012-04-05 18:57:33 -07001198 setPointerSpeedUnchecked(speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001199 }
1200
1201 public void updatePointerSpeedFromSettings() {
Jeff Brownac143512012-04-05 18:57:33 -07001202 int speed = getPointerSpeedSetting();
1203 setPointerSpeedUnchecked(speed);
1204 }
1205
1206 private void setPointerSpeedUnchecked(int speed) {
1207 speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
1208 InputManager.MAX_POINTER_SPEED);
1209 nativeSetPointerSpeed(mPtr, speed);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001210 }
1211
1212 private void registerPointerSpeedSettingObserver() {
1213 mContext.getContentResolver().registerContentObserver(
1214 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001215 new ContentObserver(mHandler) {
Jeff Brown1a84fd12011-06-02 01:26:32 -07001216 @Override
1217 public void onChange(boolean selfChange) {
1218 updatePointerSpeedFromSettings();
1219 }
Jeff Brownd4935962012-09-25 13:27:20 -07001220 }, UserHandle.USER_ALL);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001221 }
1222
Jeff Brownac143512012-04-05 18:57:33 -07001223 private int getPointerSpeedSetting() {
1224 int speed = InputManager.DEFAULT_POINTER_SPEED;
Jeff Brown1a84fd12011-06-02 01:26:32 -07001225 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001226 speed = Settings.System.getIntForUser(mContext.getContentResolver(),
1227 Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
Jeff Brown1a84fd12011-06-02 01:26:32 -07001228 } catch (SettingNotFoundException snfe) {
1229 }
1230 return speed;
1231 }
1232
Jeff Browndaf4a122011-08-26 17:14:14 -07001233 public void updateShowTouchesFromSettings() {
1234 int setting = getShowTouchesSetting(0);
Jeff Brown4532e612012-04-05 14:27:12 -07001235 nativeSetShowTouches(mPtr, setting != 0);
Jeff Browndaf4a122011-08-26 17:14:14 -07001236 }
1237
1238 private void registerShowTouchesSettingObserver() {
1239 mContext.getContentResolver().registerContentObserver(
1240 Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
Jeff Brown4532e612012-04-05 14:27:12 -07001241 new ContentObserver(mHandler) {
Jeff Browndaf4a122011-08-26 17:14:14 -07001242 @Override
1243 public void onChange(boolean selfChange) {
1244 updateShowTouchesFromSettings();
1245 }
Jeff Brownd4935962012-09-25 13:27:20 -07001246 }, UserHandle.USER_ALL);
Jeff Browndaf4a122011-08-26 17:14:14 -07001247 }
1248
1249 private int getShowTouchesSetting(int defaultValue) {
1250 int result = defaultValue;
1251 try {
Jeff Brownd4935962012-09-25 13:27:20 -07001252 result = Settings.System.getIntForUser(mContext.getContentResolver(),
1253 Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
Jeff Browndaf4a122011-08-26 17:14:14 -07001254 } catch (SettingNotFoundException snfe) {
1255 }
1256 return result;
1257 }
1258
Jeff Browna47425a2012-04-13 04:09:27 -07001259 // Binder call
1260 @Override
1261 public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
1262 if (repeat >= pattern.length) {
1263 throw new ArrayIndexOutOfBoundsException();
1264 }
1265
1266 VibratorToken v;
1267 synchronized (mVibratorLock) {
1268 v = mVibratorTokens.get(token);
1269 if (v == null) {
1270 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1271 try {
1272 token.linkToDeath(v, 0);
1273 } catch (RemoteException ex) {
1274 // give up
1275 throw new RuntimeException(ex);
1276 }
1277 mVibratorTokens.put(token, v);
1278 }
1279 }
1280
1281 synchronized (v) {
1282 v.mVibrating = true;
1283 nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);
1284 }
1285 }
1286
1287 // Binder call
1288 @Override
1289 public void cancelVibrate(int deviceId, IBinder token) {
1290 VibratorToken v;
1291 synchronized (mVibratorLock) {
1292 v = mVibratorTokens.get(token);
1293 if (v == null || v.mDeviceId != deviceId) {
1294 return; // nothing to cancel
1295 }
1296 }
1297
1298 cancelVibrateIfNeeded(v);
1299 }
1300
1301 void onVibratorTokenDied(VibratorToken v) {
1302 synchronized (mVibratorLock) {
1303 mVibratorTokens.remove(v.mToken);
1304 }
1305
1306 cancelVibrateIfNeeded(v);
1307 }
1308
1309 private void cancelVibrateIfNeeded(VibratorToken v) {
1310 synchronized (v) {
1311 if (v.mVibrating) {
1312 nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue);
1313 v.mVibrating = false;
1314 }
1315 }
1316 }
1317
Jeff Brown4532e612012-04-05 14:27:12 -07001318 @Override
1319 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Browna3bc5652012-04-17 11:42:25 -07001320 if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
Jeff Brown4532e612012-04-05 14:27:12 -07001321 != PackageManager.PERMISSION_GRANTED) {
1322 pw.println("Permission Denial: can't dump InputManager from from pid="
1323 + Binder.getCallingPid()
1324 + ", uid=" + Binder.getCallingUid());
1325 return;
1326 }
1327
1328 pw.println("INPUT MANAGER (dumpsys input)\n");
1329 String dumpStr = nativeDump(mPtr);
Jeff Browne33348b2010-07-15 23:54:05 -07001330 if (dumpStr != null) {
1331 pw.println(dumpStr);
1332 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001333 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001334
Jeff Brownac143512012-04-05 18:57:33 -07001335 private boolean checkCallingPermission(String permission, String func) {
1336 // Quick check: if the calling permission is me, it's all okay.
1337 if (Binder.getCallingPid() == Process.myPid()) {
1338 return true;
1339 }
1340
1341 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1342 return true;
1343 }
1344 String msg = "Permission Denial: " + func + " from pid="
1345 + Binder.getCallingPid()
1346 + ", uid=" + Binder.getCallingUid()
1347 + " requires " + permission;
1348 Slog.w(TAG, msg);
1349 return false;
1350 }
1351
Jeff Brown4532e612012-04-05 14:27:12 -07001352 // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001353 @Override
Jeff Brown89ef0722011-08-10 16:25:21 -07001354 public void monitor() {
1355 synchronized (mInputFilterLock) { }
Jeff Brown4532e612012-04-05 14:27:12 -07001356 nativeMonitor(mPtr);
Jeff Brown89ef0722011-08-10 16:25:21 -07001357 }
1358
Jeff Brown4532e612012-04-05 14:27:12 -07001359 // Native callback.
1360 private void notifyConfigurationChanged(long whenNanos) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001361 mWindowManagerCallbacks.notifyConfigurationChanged();
Jeff Brown4532e612012-04-05 14:27:12 -07001362 }
1363
1364 // Native callback.
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001365 private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
1366 synchronized (mInputDevicesLock) {
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001367 if (!mInputDevicesChangedPending) {
1368 mInputDevicesChangedPending = true;
Jeff Browncf39bdf2012-05-18 14:41:19 -07001369 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
1370 mInputDevices).sendToTarget();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001371 }
Jeff Browncf39bdf2012-05-18 14:41:19 -07001372
1373 mInputDevices = inputDevices;
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001374 }
1375 }
1376
1377 // Native callback.
Jeff Brownbcc046a2012-09-27 20:46:43 -07001378 private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1379 if (DEBUG) {
1380 Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1381 + ", mask=" + Integer.toHexString(switchMask));
1382 }
1383
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001384 if ((switchMask & SW_LID_BIT) != 0) {
1385 final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
Jeff Brownbcc046a2012-09-27 20:46:43 -07001386 mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
Jeff Brown53384282012-08-20 20:16:01 -07001387 }
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001388
Michael Wright3818c922014-09-02 13:59:07 -07001389 if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
Michael Wright9e10d252014-09-13 19:41:20 -07001390 final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
Michael Wright3818c922014-09-02 13:59:07 -07001391 mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
1392 }
1393
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001394 if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
1395 mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
1396 switchMask);
1397 }
Jeff Brown4532e612012-04-05 14:27:12 -07001398 }
1399
1400 // Native callback.
1401 private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001402 mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
Jeff Brown4532e612012-04-05 14:27:12 -07001403 }
1404
1405 // Native callback.
1406 private long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001407 InputWindowHandle inputWindowHandle, String reason) {
1408 return mWindowManagerCallbacks.notifyANR(
1409 inputApplicationHandle, inputWindowHandle, reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001410 }
1411
1412 // Native callback.
1413 final boolean filterInputEvent(InputEvent event, int policyFlags) {
1414 synchronized (mInputFilterLock) {
1415 if (mInputFilter != null) {
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001416 try {
1417 mInputFilter.filterInputEvent(event, policyFlags);
1418 } catch (RemoteException e) {
1419 /* ignore */
1420 }
Jeff Brown4532e612012-04-05 14:27:12 -07001421 return false;
1422 }
1423 }
1424 event.recycle();
1425 return true;
1426 }
1427
1428 // Native callback.
Jeff Brown037c33e2014-04-09 00:31:55 -07001429 private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1430 return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001431 }
1432
1433 // Native callback.
Michael Wright70af00a2014-09-03 19:30:20 -07001434 private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
1435 return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
Jeff Brown26875502014-01-30 21:47:47 -08001436 whenNanos, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001437 }
1438
1439 // Native callback.
1440 private long interceptKeyBeforeDispatching(InputWindowHandle focus,
1441 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001442 return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001443 }
1444
1445 // Native callback.
1446 private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1447 KeyEvent event, int policyFlags) {
Jeff Browna9d131c2012-09-20 16:48:17 -07001448 return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001449 }
1450
1451 // Native callback.
1452 private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
1453 return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
1454 injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
1455 }
1456
1457 // Native callback.
1458 private int getVirtualKeyQuietTimeMillis() {
1459 return mContext.getResources().getInteger(
1460 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
1461 }
1462
1463 // Native callback.
1464 private String[] getExcludedDeviceNames() {
1465 ArrayList<String> names = new ArrayList<String>();
1466
1467 // Read partner-provided list of excluded input devices
1468 XmlPullParser parser = null;
1469 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
1470 File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
1471 FileReader confreader = null;
1472 try {
1473 confreader = new FileReader(confFile);
1474 parser = Xml.newPullParser();
1475 parser.setInput(confreader);
1476 XmlUtils.beginDocument(parser, "devices");
1477
1478 while (true) {
1479 XmlUtils.nextElement(parser);
1480 if (!"device".equals(parser.getName())) {
1481 break;
1482 }
1483 String name = parser.getAttributeValue(null, "name");
1484 if (name != null) {
1485 names.add(name);
1486 }
1487 }
1488 } catch (FileNotFoundException e) {
1489 // It's ok if the file does not exist.
1490 } catch (Exception e) {
1491 Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
1492 } finally {
1493 try { if (confreader != null) confreader.close(); } catch (IOException e) { }
1494 }
1495
1496 return names.toArray(new String[names.size()]);
1497 }
1498
1499 // Native callback.
1500 private int getKeyRepeatTimeout() {
1501 return ViewConfiguration.getKeyRepeatTimeout();
1502 }
1503
1504 // Native callback.
1505 private int getKeyRepeatDelay() {
1506 return ViewConfiguration.getKeyRepeatDelay();
1507 }
1508
1509 // Native callback.
1510 private int getHoverTapTimeout() {
1511 return ViewConfiguration.getHoverTapTimeout();
1512 }
1513
1514 // Native callback.
1515 private int getHoverTapSlop() {
1516 return ViewConfiguration.getHoverTapSlop();
1517 }
1518
1519 // Native callback.
1520 private int getDoubleTapTimeout() {
1521 return ViewConfiguration.getDoubleTapTimeout();
1522 }
1523
1524 // Native callback.
1525 private int getLongPressTimeout() {
1526 return ViewConfiguration.getLongPressTimeout();
1527 }
1528
1529 // Native callback.
1530 private int getPointerLayer() {
Jeff Browna9d131c2012-09-20 16:48:17 -07001531 return mWindowManagerCallbacks.getPointerLayer();
Jeff Brown4532e612012-04-05 14:27:12 -07001532 }
1533
1534 // Native callback.
1535 private PointerIcon getPointerIcon() {
1536 return PointerIcon.getDefaultIcon(mContext);
1537 }
1538
Jeff Brown6ec6f792012-04-17 16:52:41 -07001539 // Native callback.
RoboErikfb290df2013-12-16 11:27:55 -08001540 private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001541 if (!mSystemReady) {
1542 return null;
1543 }
1544
RoboErikfb290df2013-12-16 11:27:55 -08001545 String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001546 if (keyboardLayoutDescriptor == null) {
1547 return null;
1548 }
1549
1550 final String[] result = new String[2];
1551 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
1552 @Override
1553 public void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -07001554 String descriptor, String label, String collection, int keyboardLayoutResId) {
Jeff Brown6ec6f792012-04-17 16:52:41 -07001555 try {
1556 result[0] = descriptor;
1557 result[1] = Streams.readFully(new InputStreamReader(
Jeff Brown2f095762012-05-10 21:29:33 -07001558 resources.openRawResource(keyboardLayoutResId)));
Jeff Brown6ec6f792012-04-17 16:52:41 -07001559 } catch (IOException ex) {
1560 } catch (NotFoundException ex) {
1561 }
1562 }
1563 });
1564 if (result[0] == null) {
1565 Log.w(TAG, "Could not get keyboard layout with descriptor '"
1566 + keyboardLayoutDescriptor + "'.");
1567 return null;
1568 }
1569 return result;
1570 }
1571
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001572 // Native callback.
1573 private String getDeviceAlias(String uniqueId) {
Matthew Xie96313142012-06-29 16:57:31 -07001574 if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
1575 // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
1576 return null;
Jeff Brown5bbd4b42012-04-20 19:28:00 -07001577 }
1578 return null;
1579 }
1580
Jeff Brown4532e612012-04-05 14:27:12 -07001581 /**
1582 * Callback interface implemented by the Window Manager.
1583 */
Jeff Browna9d131c2012-09-20 16:48:17 -07001584 public interface WindowManagerCallbacks {
Jeff Brown4532e612012-04-05 14:27:12 -07001585 public void notifyConfigurationChanged();
1586
1587 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
1588
Michael Wright3818c922014-09-02 13:59:07 -07001589 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
1590
Jeff Brown4532e612012-04-05 14:27:12 -07001591 public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
1592
1593 public long notifyANR(InputApplicationHandle inputApplicationHandle,
Jeff Brownbd181bb2013-09-10 16:44:24 -07001594 InputWindowHandle inputWindowHandle, String reason);
Jeff Brown4532e612012-04-05 14:27:12 -07001595
Jeff Brown037c33e2014-04-09 00:31:55 -07001596 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001597
Michael Wright70af00a2014-09-03 19:30:20 -07001598 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
Jeff Brown4532e612012-04-05 14:27:12 -07001599
1600 public long interceptKeyBeforeDispatching(InputWindowHandle focus,
1601 KeyEvent event, int policyFlags);
1602
1603 public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1604 KeyEvent event, int policyFlags);
1605
1606 public int getPointerLayer();
1607 }
1608
1609 /**
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001610 * Callback interface implemented by WiredAccessoryObserver.
1611 */
1612 public interface WiredAccessoryCallbacks {
1613 public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
Eric Laurent4a5eeb92014-05-06 10:49:04 -07001614 public void systemReady();
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001615 }
1616
1617 /**
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001618 * Private handler for the input manager.
1619 */
1620 private final class InputManagerHandler extends Handler {
Jeff Browna9d131c2012-09-20 16:48:17 -07001621 public InputManagerHandler(Looper looper) {
1622 super(looper, null, true /*async*/);
Jeff Browna2910d02012-08-25 12:29:46 -07001623 }
1624
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001625 @Override
1626 public void handleMessage(Message msg) {
1627 switch (msg.what) {
1628 case MSG_DELIVER_INPUT_DEVICES_CHANGED:
Jeff Browncf39bdf2012-05-18 14:41:19 -07001629 deliverInputDevicesChanged((InputDevice[])msg.obj);
1630 break;
1631 case MSG_SWITCH_KEYBOARD_LAYOUT:
1632 handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
1633 break;
1634 case MSG_RELOAD_KEYBOARD_LAYOUTS:
1635 reloadKeyboardLayouts();
1636 break;
1637 case MSG_UPDATE_KEYBOARD_LAYOUTS:
1638 updateKeyboardLayouts();
1639 break;
1640 case MSG_RELOAD_DEVICE_ALIASES:
1641 reloadDeviceAliases();
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001642 break;
1643 }
1644 }
1645 }
1646
1647 /**
Jeff Brown4532e612012-04-05 14:27:12 -07001648 * Hosting interface for input filters to call back into the input manager.
1649 */
Svetoslav Ganovc9c9a482012-07-16 08:46:07 -07001650 private final class InputFilterHost extends IInputFilterHost.Stub {
Jeff Brown0029c662011-03-30 02:25:18 -07001651 private boolean mDisconnected;
1652
1653 public void disconnectLocked() {
1654 mDisconnected = true;
1655 }
1656
Craig Mautner2f39e9f2012-09-21 11:39:54 -07001657 @Override
Jeff Brown0029c662011-03-30 02:25:18 -07001658 public void sendInputEvent(InputEvent event, int policyFlags) {
1659 if (event == null) {
1660 throw new IllegalArgumentException("event must not be null");
1661 }
1662
1663 synchronized (mInputFilterLock) {
1664 if (!mDisconnected) {
Jeff Brownca9bc702014-02-11 14:32:56 -08001665 nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
Jeff Brownac143512012-04-05 18:57:33 -07001666 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
Jeff Brown0029c662011-03-30 02:25:18 -07001667 policyFlags | WindowManagerPolicy.FLAG_FILTERED);
1668 }
1669 }
1670 }
1671 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001672
1673 private static final class KeyboardLayoutDescriptor {
1674 public String packageName;
1675 public String receiverName;
1676 public String keyboardLayoutName;
1677
1678 public static String format(String packageName,
1679 String receiverName, String keyboardName) {
1680 return packageName + "/" + receiverName + "/" + keyboardName;
1681 }
1682
1683 public static KeyboardLayoutDescriptor parse(String descriptor) {
1684 int pos = descriptor.indexOf('/');
1685 if (pos < 0 || pos + 1 == descriptor.length()) {
1686 return null;
1687 }
1688 int pos2 = descriptor.indexOf('/', pos + 1);
1689 if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
1690 return null;
1691 }
1692
1693 KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
1694 result.packageName = descriptor.substring(0, pos);
1695 result.receiverName = descriptor.substring(pos + 1, pos2);
1696 result.keyboardLayoutName = descriptor.substring(pos2 + 1);
1697 return result;
1698 }
1699 }
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001700
Jeff Brown6ec6f792012-04-17 16:52:41 -07001701 private interface KeyboardLayoutVisitor {
1702 void visitKeyboardLayout(Resources resources,
Jeff Brownd9fec5d2012-05-17 16:01:54 -07001703 String descriptor, String label, String collection, int keyboardLayoutResId);
Jeff Brown6ec6f792012-04-17 16:52:41 -07001704 }
1705
Jeff Brownaf9e8d32012-04-12 17:32:48 -07001706 private final class InputDevicesChangedListenerRecord implements DeathRecipient {
1707 private final int mPid;
1708 private final IInputDevicesChangedListener mListener;
1709
1710 public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
1711 mPid = pid;
1712 mListener = listener;
1713 }
1714
1715 @Override
1716 public void binderDied() {
1717 if (DEBUG) {
1718 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
1719 }
1720 onInputDevicesChangedListenerDied(mPid);
1721 }
1722
1723 public void notifyInputDevicesChanged(int[] info) {
1724 try {
1725 mListener.onInputDevicesChanged(info);
1726 } catch (RemoteException ex) {
1727 Slog.w(TAG, "Failed to notify process "
1728 + mPid + " that input devices changed, assuming it died.", ex);
1729 binderDied();
1730 }
1731 }
1732 }
Jeff Browna47425a2012-04-13 04:09:27 -07001733
1734 private final class VibratorToken implements DeathRecipient {
1735 public final int mDeviceId;
1736 public final IBinder mToken;
1737 public final int mTokenValue;
1738
1739 public boolean mVibrating;
1740
1741 public VibratorToken(int deviceId, IBinder token, int tokenValue) {
1742 mDeviceId = deviceId;
1743 mToken = token;
1744 mTokenValue = tokenValue;
1745 }
1746
1747 @Override
1748 public void binderDied() {
1749 if (DEBUG) {
1750 Slog.d(TAG, "Vibrator token died.");
1751 }
1752 onVibratorTokenDied(this);
1753 }
1754 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001755
1756 private final class LocalService extends InputManagerInternal {
1757 @Override
1758 public void setDisplayViewports(
1759 DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
1760 setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
1761 }
Jeff Brownca9bc702014-02-11 14:32:56 -08001762
1763 @Override
1764 public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
1765 return injectInputEventInternal(event, displayId, mode);
1766 }
Jeff Brown037c33e2014-04-09 00:31:55 -07001767
1768 @Override
1769 public void setInteractive(boolean interactive) {
1770 nativeSetInteractive(mPtr, interactive);
1771 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001772 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001773}